/** * HistoryManager – Frontend for conversion history * Renders paginated table, detail view, stats, and filters. */ window.EDIBridge = window.EDIBridge || {}; class HistoryManager { constructor(app) { this.app = app; this.currentPage = 1; this.pageSize = 20; this.statusFilter = 'ALL'; this.dateFilter = 'ALL'; this.searchTerm = ''; this.totalRows = 0; } /** * Called when the History page becomes visible. */ async activate() { await this.loadStats(); await this.loadTable(); } /** * Load and render statistics cards. */ async loadStats() { if (!window.electronAPI) return; const stats = await window.electronAPI.dbGetStats(); const container = document.getElementById('historyStats'); if (!container) return; container.innerHTML = `
${stats.total}
Gesamt
${stats.success}
Erfolgreich
${stats.error}
Fehlerhaft
${stats.today}
Heute
`; } /** * Load and render the conversion table. */ async loadTable() { if (!window.electronAPI) return; const offset = (this.currentPage - 1) * this.pageSize; const params = { limit: this.pageSize, offset, statusFilter: this.statusFilter, dateFilter: this.dateFilter, search: this.searchTerm }; console.log('[History] Loading table with params:', params); const result = await window.electronAPI.dbGetAll(params); this.totalRows = result.total; const totalPages = Math.max(1, Math.ceil(result.total / this.pageSize)); const tbody = document.getElementById('historyTableBody'); const pagination = document.getElementById('historyPagination'); if (!tbody) return; if (result.rows.length === 0) { tbody.innerHTML = `Keine Einträge gefunden.`; } else { tbody.innerHTML = result.rows.map(row => { const ts = this._formatTimestamp(row.zeitstempel); const statusIcon = row.status === 'ERFOLGREICH' ? '' : ''; const modus = this._shortModus(row.konvertierungsmodus, row.quellformat, row.zielformat); const source = row.quelle === 'WATCHER' ? 'AUTO' : 'GUI'; return ` ${row.id} ${ts}
${this._escapeHtml(row.dateiname)}
${row.ausgangsdateiname ? `
→ ${this._escapeHtml(row.ausgangsdateiname)}
` : ''} ${modus} ${statusIcon} ${source} `; }).join(''); } if (pagination) { pagination.innerHTML = ` Seite ${this.currentPage} von ${totalPages} (${result.total} Einträge) `; } // Re-render icons if (window.lucide) { try { lucide.createIcons(); } catch (e) { } } } /** * Show detail view for a single conversion. */ async showDetail(id) { if (!window.electronAPI) return; const record = await window.electronAPI.dbGetById(id); if (!record) return; const modal = document.getElementById('historyDetailModal'); const content = document.getElementById('historyDetailContent'); if (!modal || !content) return; const statusBadge = record.status === 'ERFOLGREICH' ? '✅ ERFOLGREICH' : '❌ FEHLERHAFT'; content.innerHTML = `

Konvertierung #${record.id}

Zeitstempel ${this._formatTimestamp(record.zeitstempel)}
Status ${statusBadge}
Eingangsdatei ${this._escapeHtml(record.dateiname)}
Ausgangsdatei ${this._escapeHtml(record.ausgangsdateiname || '-')}
Quellformat ${this._escapeHtml(record.quellformat || '-')}
Zielformat ${this._escapeHtml(record.zielformat || '-')}
Konvertierungsmodus ${this._escapeHtml(record.konvertierungsmodus || '-')}
Kunden-ID ${this._escapeHtml(record.kunden_id || '-')}
Quelle ${record.quelle === 'WATCHER' ? '🤖 Automatisch (Watcher)' : '👤 Manuell (GUI)'}
${record.fehlermeldung ? `
Fehlermeldung:
${this._escapeHtml(record.fehlermeldung)}
` : ''}
${record.ausgang_daten ? ` ` : ''}
${this._escapeHtml(record.eingang_daten || 'Keine Eingangsdaten gespeichert.')}
`; modal.style.display = 'flex'; if (window.lucide) { try { lucide.createIcons(); } catch (e) { } } } switchTab(tab) { const eingang = document.getElementById('historyTabEingang'); const ausgang = document.getElementById('historyTabAusgang'); const buttons = document.querySelectorAll('.history-tab-btn'); buttons.forEach(btn => { btn.classList.toggle('active', btn.dataset.tab === tab); }); if (tab === 'eingang') { if (eingang) eingang.style.display = 'block'; if (ausgang) ausgang.style.display = 'none'; } else { if (eingang) eingang.style.display = 'none'; if (ausgang) ausgang.style.display = 'block'; } } async openInViewer(id) { const record = await window.electronAPI.dbGetById(id); if (!record || !record.ausgang_daten) return; this.closeDetail(); // Switch to viewer page and process the content if (this.app) { this.app.showPage('viewer'); if (this.app.viewer) { this.app.viewer.processContent(record.ausgang_daten); } } } closeDetail() { const modal = document.getElementById('historyDetailModal'); if (modal) modal.style.display = 'none'; } async deleteEntry(id) { if (!confirm('Eintrag wirklich löschen?')) return; await window.electronAPI.dbDelete(id); await this.loadStats(); await this.loadTable(); } goToPage(page) { if (page < 1) return; this.currentPage = page; this.loadTable(); } setFilter(status) { this.statusFilter = status; this.dateFilter = 'ALL'; this.searchTerm = ''; // Clear search when picking a card this.currentPage = 1; // Reset search input const searchInput = document.getElementById('historySearch'); if (searchInput) searchInput.value = ''; // Update active button state document.querySelectorAll('.history-filter-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.filter === status); }); this.loadStats(); this.loadTable(); } setDateFilter(dateType) { this.dateFilter = dateType; this.statusFilter = 'ALL'; // Reset status when picking date this.searchTerm = ''; // Clear search when picking a card this.currentPage = 1; // Reset filter bar buttons document.querySelectorAll('.history-filter-btn').forEach(btn => { btn.classList.toggle('active', false); }); // Reset search input const searchInput = document.getElementById('historySearch'); if (searchInput) searchInput.value = ''; this.loadStats(); this.loadTable(); } onSearch(value) { this.searchTerm = value; this.currentPage = 1; // Debounce clearTimeout(this._searchTimer); this._searchTimer = setTimeout(() => this.loadTable(), 300); } async exportCSV() { if (!window.electronAPI) return; // Fetch all rows (no pagination) const result = await window.electronAPI.dbGetAll({ limit: 99999, offset: 0, statusFilter: this.statusFilter, search: this.searchTerm }); if (!result.rows || result.rows.length === 0) { alert('Keine Daten zum Exportieren.'); return; } const headers = ['ID', 'Zeitstempel', 'Dateiname', 'Ausgangsdatei', 'Quellformat', 'Zielformat', 'Modus', 'Kunden-ID', 'Status', 'Fehlermeldung', 'Quelle']; const csvRows = [headers.join(';')]; result.rows.forEach(row => { csvRows.push([ row.id, row.zeitstempel, `"${(row.dateiname || '').replace(/"/g, '""')}"`, `"${(row.ausgangsdateiname || '').replace(/"/g, '""')}"`, row.quellformat || '', row.zielformat || '', row.konvertierungsmodus || '', row.kunden_id || '', row.status, `"${(row.fehlermeldung || '').replace(/"/g, '""')}"`, row.quelle ].join(';')); }); const csv = csvRows.join('\n'); const blob = new Blob(['\ufeff' + csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `konvertierungen_${new Date().toISOString().slice(0, 10)}.csv`; a.click(); URL.revokeObjectURL(url); } // ─── Helpers ───────────────────────────────────────────────────── _formatTimestamp(ts) { if (!ts) return '-'; try { const d = new Date(ts.replace(' ', 'T')); return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) + ' ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); } catch (e) { return ts; } } _shortModus(modus, quellformat, zielformat) { if (quellformat && zielformat) { // Shorten for display const qf = quellformat.replace('EDIFACT ', '').replace('D04A', '').trim(); const zf = zielformat.replace('EDIFACT ', '').trim(); return `${this._escapeHtml(qf)} → ${this._escapeHtml(zf)}`; } if (modus) return `${this._escapeHtml(modus)}`; return '-'; } _escapeHtml(str) { if (!str) return ''; return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } } window.EDIBridge.HistoryManager = HistoryManager;