Files
vda-to-edifact-converter/index.html
zed 67bd64b688 Separaten Output-Ordner für INVRPT → VDA 4913 Konvertierungen hinzufügen
Der eingehende Watcher nutzt denselben Input-Ordner für alle Dateitypen,
schreibt INVRPT-Konvertierungen nun aber in einen konfigurierbaren
separaten Output-Ordner. Bleibt das Feld leer, wird der Standard-
Output-Ordner als Fallback verwendet (abwärtskompatibel).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 12:22:45 +01:00

802 lines
41 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ERP EDI Bridge | VDA ↔ EDIFACT</title>
<link rel="stylesheet" href="styles.css">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=Fira+Code&display=swap"
rel="stylesheet">
<!-- Icons (External) - Error Handled -->
<script src="https://unpkg.com/lucide@latest"></script>
<script>
window.onerror = function (msg, url, line) {
console.error('Global Error: ' + msg + '\nline: ' + line);
return false;
};
</script>
</head>
<body>
<div class="dashboard">
<header>
<h1>ERP EDI Bridge</h1>
<p class="subtitle">Konvertieren Sie VDA 4913, 4905 und EDIFACT Nachrichten</p>
</header>
<!-- ═══ Page Navigation ═══ -->
<nav class="page-nav">
<button class="page-nav-btn active" data-page="converter" onclick="app.showPage('converter')">
<i data-lucide="repeat"></i>
Converter
</button>
<button class="page-nav-btn" data-page="viewer" onclick="app.showPage('viewer')">
<i data-lucide="file-text"></i>
EDI Viewer
</button>
<button class="page-nav-btn" data-page="editor" onclick="app.showPage('editor')">
<i data-lucide="edit-3"></i>
Editor
</button>
<button class="page-nav-btn" data-page="history" onclick="app.showPage('history')">
<i data-lucide="database"></i>
Historie
</button>
<button class="page-nav-btn" data-page="settings" onclick="app.showPage('settings')">
<i data-lucide="settings"></i>
Settings
</button>
</nav>
<!-- Config Upload (Global) -->
<div class="config-bar" style="max-width: 1200px; margin: 0 auto 20px auto;">
<div class="config-status" id="configStatus">
<i data-lucide="settings-2"></i>
<span>Keine Konfiguration geladen</span>
</div>
<button class="btn-secondary" onclick="document.getElementById('configInput').click()">
<i data-lucide="upload"></i>
Konfig laden
</button>
<button class="btn-secondary" id="btnSaveConfig" onclick="app.saveConfig()" style="display:none">
<i data-lucide="save"></i>
Konfig speichern
</button>
<input type="file" id="configInput" accept=".txt,.ini,.cfg" class="hidden">
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: CONVERTER -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageConverter">
<!-- Mode Toggle 4 modes -->
<div class="mode-toggle">
<button id="btnOutboundBosch" class="mode-btn active" onclick="app.setMode('outbound-bosch')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → Bosch DESADV
</button>
<button id="btnOutboundZf" class="mode-btn" onclick="app.setMode('outbound-zf')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → ZF DESADV
</button>
<button id="btnOutboundIfm" class="mode-btn" onclick="app.setMode('outbound-ifm')">
<i data-lucide="arrow-up-right"></i>
VDA 4913 → IFM DELVRY03
</button>
<button id="btnInboundBosch" class="mode-btn" onclick="app.setMode('inbound-bosch')">
<i data-lucide="arrow-down-left"></i>
DELFOR → VDA 4905
</button>
<button id="btnInboundIfm" class="mode-btn" onclick="app.setMode('inbound-ifm')">
<i data-lucide="arrow-down-left"></i>
IFM DELFOR → VDA 4905
</button>
<button id="btnInboundInvrpt" class="mode-btn" onclick="app.setMode('inbound-invrpt')">
<i data-lucide="arrow-down-left"></i>
INVRPT → VDA 4913
</button>
<button id="btnValidateEdifact" class="mode-btn" onclick="app.setMode('validate-edifact')">
<i data-lucide="check-circle"></i>
EDIFACT Validieren
</button>
</div>
<!-- Drop Zone -->
<div id="dropZone" class="drop-zone">
<i data-lucide="upload-cloud"></i>
<h3>Datei hier ablegen oder klicken</h3>
<p id="dropText">VDA 4913 Datei auswählen für Konvertierung</p>
<input type="file" id="fileInput" class="hidden">
</div>
<!-- Enrichment Section (shown after VDA upload in outbound-bosch mode) -->
<div id="enrichmentSection" class="enrichment-section">
<!-- NAD Segment Editor -->
<div class="preview-header" style="margin-bottom: 20px;">
<h2>Partneradressen (NAD Segmente)</h2>
<span class="badge badge-edi" id="nadSourceBadge">Manuell</span>
</div>
<div class="nad-grid">
<!-- Buyer (BY) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">BY</span><span>Käufer (Buyer)</span>
</div>
<label>ID <input type="text" id="nad-by-id" class="nad-input" value="5060"></label>
<label>Qualifier <input type="text" id="nad-by-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-by-name" class="nad-input wide"
value="Robert Bosch spol. s.r.o."></label>
<label>Firma 2 <input type="text" id="nad-by-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-by-street" class="nad-input wide"
value="Roberta Bosche 2678"></label>
<label>Stadt <input type="text" id="nad-by-city" class="nad-input"
value="Ceske Budejovicen"></label>
<label>PLZ <input type="text" id="nad-by-zip" class="nad-input" value="37004"></label>
<label>Land <input type="text" id="nad-by-country" class="nad-input" value="CZ"
maxlength="2"></label>
</div>
<!-- Seller (SE) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">SE</span><span>Lieferant
(Seller)</span></div>
<label>ID <input type="text" id="nad-se-id" class="nad-input" value="0000062671"></label>
<label>Qualifier <input type="text" id="nad-se-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-se-name" class="nad-input wide"
value="Roechling Precision Components"></label>
<label>Firma 2 <input type="text" id="nad-se-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-se-street" class="nad-input wide"
value="Winter-Ring 3"></label>
<label>Stadt <input type="text" id="nad-se-city" class="nad-input" value="Weidenberg"></label>
<label>PLZ <input type="text" id="nad-se-zip" class="nad-input" value="95466"></label>
<label>Land <input type="text" id="nad-se-country" class="nad-input" value="DE"
maxlength="2"></label>
</div>
<!-- Ship-To (ST) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">ST</span><span>Warenempfänger
(Ship-To)</span></div>
<label>ID <input type="text" id="nad-st-id" class="nad-input" value="5060"></label>
<label>Qualifier <input type="text" id="nad-st-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-st-name" class="nad-input wide"
value="Robert Bosch spol. s.r.o."></label>
<label>Firma 2 <input type="text" id="nad-st-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-st-street" class="nad-input wide"
value="Roberta Bosche 2678"></label>
<label>Stadt <input type="text" id="nad-st-city" class="nad-input"
value="Ceske Budejovicen"></label>
<label>PLZ <input type="text" id="nad-st-zip" class="nad-input" value="37004"></label>
<label>Land <input type="text" id="nad-st-country" class="nad-input" value="CZ"
maxlength="2"></label>
</div>
<!-- Ship-From (SF) -->
<div class="nad-card">
<div class="nad-card-header"><span class="nad-qualifier">SF</span><span>Versender
(Ship-From)</span></div>
<label>ID <input type="text" id="nad-sf-id" class="nad-input" value="0000062671"></label>
<label>Qualifier <input type="text" id="nad-sf-qual" class="nad-input" value="92"></label>
<label>Firma <input type="text" id="nad-sf-name" class="nad-input wide"
value="Roechling Precision Components"></label>
<label>Firma 2 <input type="text" id="nad-sf-name2" class="nad-input wide" value=""></label>
<label>Straße <input type="text" id="nad-sf-street" class="nad-input wide"
value="Winter-Ring 3"></label>
<label>Stadt <input type="text" id="nad-sf-city" class="nad-input" value="Weidenberg"></label>
<label>PLZ <input type="text" id="nad-sf-zip" class="nad-input" value="95466"></label>
<label>Land <input type="text" id="nad-sf-country" class="nad-input" value="DE"
maxlength="2"></label>
</div>
</div>
<!-- Material & Weight Enrichment -->
<div class="preview-header" style="margin-top: 40px;">
<h2>Positionen & Gewichte</h2>
<span class="badge badge-vda">VDA 4913</span>
</div>
<p class="subtitle">Artikel- und Packmittelgewichte können hier angepasst werden.</p>
<div class="table-container">
<table id="enrichmentTable">
<thead>
<tr>
<th>Kunden-Mat.</th>
<th>Lieferanten-Mat.</th>
<th>Menge</th>
<th>Einheit</th>
<th>Artikelgewicht (kg/Stk)</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- Packaging Weight & Dimensions Table -->
<div class="preview-header" style="margin-top: 30px;">
<h2>Packmittel (Gewichte & Maße)</h2>
</div>
<p class="subtitle">Alle Felder sind pflicht in DESADV. Fehlende Werte über Konfig-Datei ergänzen.</p>
<div class="table-container">
<table id="packagingTable">
<thead>
<tr>
<th>Packmittel (Kd)</th>
<th>Packmittel (Lief)</th>
<th>Anz.</th>
<th>Gewicht (kg)</th>
<th>Länge (cm)</th>
<th>Breite (cm)</th>
<th>Höhe (cm)</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div style="margin-top: 30px; text-align: right;">
<button class="btn-primary" onclick="app.generateOutput()">
<i data-lucide="zap"></i>
JETZT KONVERTIEREN
</button>
</div>
</div>
<!-- Result Section -->
<div id="resultSection" class="result-section">
<!-- Stats Grid -->
<div id="stats-grid" class="stats-grid"></div>
<div class="preview-header">
<h2 id="resultTitle">Konvertierungsergebnis</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.viewResult()">
<i data-lucide="eye"></i>
View
</button>
<button class="btn-secondary" onclick="app.editResult()">
<i data-lucide="edit-3"></i>
Edit
</button>
<button class="btn-primary" onclick="app.downloadResult()">
<i data-lucide="download"></i>
Download
</button>
</div>
</div>
<pre id="previewArea"></pre>
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: SETTINGS -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageSettings" style="display:none">
<h2 class="settings-title">
<i data-lucide="folder-search"></i>
Ankommende Dateien (Folder Watch)
</h2>
<p class="subtitle" style="margin-bottom: 30px;">Überwacht einen Netzwerkordner auf neue Dateien,
konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.</p>
<!-- General Settings & ID Mapping -->
<div class="log-section" style="margin-top: 40px;">
<h2 class="settings-title">
<i data-lucide="user-check"></i>
VDA 711 ID-Umschlüsselung
</h2>
<p class="subtitle" style="margin-bottom: 20px;">
Weisen Sie extrahierten IDs (Datenempfänger) eine eigene Kundennummer für den VDA 711 Header zu.
</p>
<div class="mapping-editor">
<div class="folder-input-row" style="margin-bottom: 20px;">
<input type="text" id="newIdMapOriginal" class="folder-path-input"
placeholder="Alt (z.B. 8810)" style="max-width: 200px;">
<input type="text" id="newIdMapTarget" class="folder-path-input"
placeholder="Neu (z.B. 10305)" style="max-width: 200px;">
<button class="btn-primary" onclick="app.addIdMapping711()">
<i data-lucide="plus"></i>
Hinzufügen
</button>
</div>
<div class="table-container">
<table id="idMapping711Table">
<thead>
<tr>
<th>Extrahierte ID (Alt)</th>
<th>Eigene ID (Neu)</th>
<th style="width: 100px;">Aktion</th>
</tr>
</thead>
<tbody>
<!-- Populated by JS -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Electron notice -->
<div id="electronNotice" class="electron-notice" style="display:none">
<i data-lucide="alert-triangle"></i>
<span>Ordnerüberwachung ist nur in der Electron-App verfügbar. Bitte starten Sie die App mit
<code>npm start</code>.</span>
</div>
<!-- Folder Config -->
<div class="settings-grid">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner</span>
</div>
<div class="folder-input-row">
<input type="text" id="inputDirPath" class="folder-path-input"
placeholder="z.B. \\server\edi\input" readonly>
<button class="btn-secondary" id="btnSelectInput" onclick="app.selectInputFolder()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner</span>
</div>
<div class="folder-input-row">
<input type="text" id="outputDirPath" class="folder-path-input"
placeholder="z.B. \\server\edi\output" readonly>
<button class="btn-secondary" id="btnSelectOutput" onclick="app.selectOutputFolder()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner (INVRPT → VDA 4913)</span>
</div>
<div class="folder-input-row">
<input type="text" id="invrptOutputPath" class="folder-path-input"
placeholder="Leer = gleicher Output-Ordner" readonly>
<button class="btn-secondary" id="btnSelectInvrptOutput" onclick="app.selectInvrptOutputFolder()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
</div>
<!-- Watcher Controls -->
<div class="watcher-controls">
<div class="watcher-status-display">
<span class="watcher-status-dot" id="watcherDot"></span>
<span id="watcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartWatcher" onclick="app.startWatcher()">
<i data-lucide="play"></i>
Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseWatcher" onclick="app.pauseWatcher()" disabled>
<i data-lucide="pause"></i>
Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeWatcher" onclick="app.resumeWatcher()"
style="display:none">
<i data-lucide="play"></i>
Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopWatcher" onclick="app.stopWatcher()" disabled>
<i data-lucide="square"></i>
Stoppen
</button>
</div>
</div>
<!-- Outbound Folder Config -->
<div class="log-section" style="margin-top: 40px;">
<h2 class="settings-title">
<i data-lucide="folder-search"></i>
Ausgehende Dateien (Folder Watch)
</h2>
<p class="subtitle" style="margin-bottom: 20px;">
Überwacht einen Netzwerkordner auf ausgehende Dateien, konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.
</p>
<div class="settings-grid">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner (Ausgehend)</span>
</div>
<div class="folder-input-row">
<input type="text" id="outboundInputPath" class="folder-path-input"
placeholder="z.B. \\server\edi\outbound_in" readonly>
<button class="btn-secondary" onclick="app.selectOutboundInput()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner (Ausgehend)</span>
</div>
<div class="folder-input-row">
<input type="text" id="outboundOutputPath" class="folder-path-input"
placeholder="z.B. \\server\edi\outbound_out" readonly>
<button class="btn-secondary" onclick="app.selectOutboundOutput()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
</div>
<div class="watcher-controls">
<div class="watcher-status-display">
<span class="watcher-status-dot" id="outboundWatcherDot"></span>
<span id="outboundWatcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartOutboundWatcher"
onclick="app.startOutboundWatcher()">
<i data-lucide="play"></i>
Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseOutboundWatcher"
onclick="app.pauseOutboundWatcher()" disabled>
<i data-lucide="pause"></i>
Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeOutboundWatcher"
onclick="app.resumeOutboundWatcher()" style="display:none">
<i data-lucide="play"></i>
Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopOutboundWatcher" onclick="app.stopOutboundWatcher()"
disabled>
<i data-lucide="square"></i>
Stoppen
</button>
</div>
</div>
</div>
<!-- Werksnummer Watcher Controls (New Section) -->
<div class="log-section" style="margin-top: 40px;">
<h2 class="settings-title">
<i data-lucide="file-text"></i>
Werksnummer Umbenennung
</h2>
<p class="subtitle" style="margin-bottom: 20px;">
Überwacht VDA-Dateien (RA_VDA*) und benennt sie basierend auf der Werksnummer in Satzart 512 um
(100 → LEIFERS, 280 → PITESTI).
</p>
<div class="settings-grid">
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-input"></i>
<span>Input-Ordner (Werksnummer)</span>
</div>
<div class="folder-input-row">
<input type="text" id="werksInputPath" class="folder-path-input"
placeholder="Input für Umbenennung" readonly>
<button class="btn-secondary" onclick="app.selectWerksInput()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
<div class="settings-card">
<div class="settings-card-header">
<i data-lucide="folder-output"></i>
<span>Output-Ordner (Werksnummer)</span>
</div>
<div class="folder-input-row">
<input type="text" id="werksOutputPath" class="folder-path-input"
placeholder="Output für Umbenennung" readonly>
<button class="btn-secondary" onclick="app.selectWerksOutput()">
<i data-lucide="folder-open"></i>
Wählen
</button>
</div>
</div>
</div>
<div class="watcher-controls">
<div class="watcher-status-display">
<span class="watcher-status-dot" id="werksWatcherDot"></span>
<span id="werksWatcherStatusText">Gestoppt</span>
</div>
<div class="watcher-buttons">
<button class="btn-primary btn-start" id="btnStartWerksWatcher"
onclick="app.startWerksWatcher()">
<i data-lucide="play"></i>
Starten
</button>
<button class="btn-secondary btn-pause" id="btnPauseWerksWatcher"
onclick="app.pauseWerksWatcher()" disabled>
<i data-lucide="pause"></i>
Pausieren
</button>
<button class="btn-secondary btn-resume" id="btnResumeWerksWatcher"
onclick="app.resumeWerksWatcher()" style="display:none">
<i data-lucide="play"></i>
Fortsetzen
</button>
<button class="btn-secondary btn-stop" id="btnStopWerksWatcher" onclick="app.stopWerksWatcher()"
disabled>
<i data-lucide="square"></i>
Stoppen
</button>
</div>
</div>
</div>
<!-- Customer Mappings -->
<div class="log-section" style="margin-top: 40px;">
<div class="preview-header">
<h2>
<i data-lucide="map"></i>
Kundennummern-Zuordnung
</h2>
</div>
<p class="subtitle" style="margin-bottom: 20px;">Weisen Sie Kundennummern automatisch einer
Konvertierung zu.</p>
<div class="mapping-editor">
<div class="folder-input-row" style="margin-bottom: 20px;">
<input type="text" id="newMappingId" class="folder-path-input"
placeholder="Kundennummer (z.B. 5060)" style="max-width: 200px;">
<select id="newMappingMode" class="folder-path-input" style="max-width: 250px;">
<option value="outbound-bosch">VDA 4913 → Bosch DESADV</option>
<option value="outbound-zf">VDA 4913 → ZF DESADV</option>
<option value="outbound-ifm">VDA 4913 → IFM DELVRY03</option>
<option value="inbound-bosch">DELFOR → VDA 4905</option>
<option value="inbound-ifm">IFM DELFOR → VDA 4905</option>
<option value="inbound-invrpt">INVRPT → VDA 4913</option>
<option value="validate-edifact">EDIFACT Validieren</option>
</select>
<button class="btn-primary" onclick="app.addMapping()">
<i data-lucide="plus"></i>
Hinzufügen
</button>
</div>
<div class="table-container">
<table id="mappingTable">
<thead>
<tr>
<th>Kundennummer</th>
<th>Konvertierungs-Modus</th>
<th style="width: 100px;">Aktion</th>
</tr>
</thead>
<tbody>
<!-- Will be populated by JS -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Conversion Log -->
<div class="log-section">
<div class="preview-header">
<h2>Konvertierungs-Log</h2>
<button class="btn-secondary" onclick="app.clearLog()">
<i data-lucide="trash-2"></i>
Leeren
</button>
</div>
<div class="log-container" id="logContainer">
<div class="log-empty">Noch keine Aktivitäten.</div>
</div>
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: VIEWER -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageViewer" style="display:none">
<div class="preview-header no-print">
<h2>EDI Dokument Viewer</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.viewer.reset()" id="btnViewerBack" style="display:none">
<i data-lucide="arrow-left"></i>
Zurück
</button>
<button class="btn-primary" onclick="app.viewer.printDocument()" id="btnViewerPrint"
style="display:none">
<i data-lucide="printer"></i>
Als PDF speichern / Drucken
</button>
</div>
</div>
<div id="viewerDropZone" class="drop-zone no-print">
<i data-lucide="file-search"></i>
<h3>Datei hier ablegen oder klicken zur Anzeige</h3>
<p id="viewerDropText">Unterstützt DELFOR und VDA 4905/4913 Dateien</p>
<input type="file" id="viewerFileInput" class="hidden">
</div>
<!-- This container will hold the rendered HTML document -->
<div id="viewerDocumentRender" class="document-render-area">
<!-- Content injected by JS -->
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: EDITOR -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageEditor" style="display:none">
<div class="preview-header no-print">
<h2>EDI Dokument Editor</h2>
<div class="viewer-actions">
<button class="btn-secondary" onclick="app.editor.reset()" id="btnEditorBack" style="display:none">
<i data-lucide="arrow-left"></i>
Zurück
</button>
<button class="btn-primary" onclick="app.editor.downloadDocument()" id="btnEditorDownload"
style="display:none">
<i data-lucide="download"></i>
Speichern / Download
</button>
</div>
</div>
<div id="editorDropZone" class="drop-zone no-print">
<i data-lucide="edit"></i>
<h3>EDI Datei hier ablegen oder klicken zur Bearbeitung</h3>
<p id="editorDropText">Unterstützt EDIFACT und VDA Dateien</p>
<input type="file" id="editorFileInput" class="hidden">
</div>
<!-- This container will hold the editable segments -->
<div id="editorDocumentRender" class="editor-render-area" style="display:none;">
<!-- Content injected by JS -->
</div>
</main>
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- PAGE: HISTORY -->
<!-- ═══════════════════════════════════════════════════════════ -->
<main class="main-card page-content" id="pageHistory" style="display:none">
<h2 class="settings-title">
<i data-lucide="database"></i>
Konvertierungs-Historie
</h2>
<p class="subtitle" style="margin-bottom: 20px;">Vollständige Nachverfolgung aller durchgeführten
Konvertierungen.</p>
<!-- Stats -->
<div class="stats-grid" id="historyStats">
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Gesamt</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Erfolgreich</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Fehlerhaft</div>
</div>
<div class="stat-card">
<div class="stat-value">-</div>
<div class="stat-label">Heute</div>
</div>
</div>
<!-- Filter Bar -->
<div class="history-filter-bar">
<div class="history-filter-buttons">
<button class="btn-secondary history-filter-btn active" data-filter="ALL"
onclick="app.historyManager.setFilter('ALL')">
Alle
</button>
<button class="btn-secondary history-filter-btn" data-filter="ERFOLGREICH"
onclick="app.historyManager.setFilter('ERFOLGREICH')">
✅ Erfolgreich
</button>
<button class="btn-secondary history-filter-btn" data-filter="FEHLERHAFT"
onclick="app.historyManager.setFilter('FEHLERHAFT')">
❌ Fehlerhaft
</button>
</div>
<div class="history-search-row">
<input type="text" id="historySearch" class="folder-path-input"
placeholder="🔍 Suche nach Dateiname, Kunden-ID..."
oninput="app.historyManager.onSearch(this.value)" style="max-width:350px;">
<button class="btn-secondary" onclick="app.historyManager.exportCSV()">
<i data-lucide="download" style="width:14px;height:14px;"></i> CSV Export
</button>
</div>
</div>
<!-- Table -->
<div class="history-table-wrapper">
<table class="history-table">
<thead>
<tr>
<th style="width:50px;">ID</th>
<th style="width:140px;">Zeitstempel</th>
<th>Dateiname</th>
<th style="width:180px;">Modus</th>
<th style="width:90px;">Status</th>
<th style="width:50px;"></th>
</tr>
</thead>
<tbody id="historyTableBody">
<tr>
<td colspan="6"
style="text-align:center; padding:40px; color: var(--text-dim); font-style:italic;">Lade
Daten...</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<div class="history-pagination" id="historyPagination"></div>
</main>
<!-- History Detail Modal -->
<div id="historyDetailModal" class="history-detail-modal" style="display:none;">
<div class="history-detail-modal-content">
<div id="historyDetailContent"></div>
</div>
</div>
</div>
<!-- SCRIPTS -->
<script src="js/vda-parser.js"></script>
<script src="js/edifact-logic.js"></script>
<script src="js/config-parser.js"></script>
<script src="js/vda4913-to-desadv.js"></script>
<script src="js/vda4913-to-desadv-zf.js"></script>
<script src="js/vda4913-to-delvry03.js"></script>
<script src="js/delfor-parser.js"></script>
<script src="js/vda4905-generator.js"></script>
<script src="js/ifm_delfor-vda4905.js"></script>
<script src="js/invrpt-to-vda4913.js"></script>
<script src="js/watcher-bridge.js"></script>
<script src="js/outbound-watcher-bridge.js"></script>
<script src="js/werks-watcher-bridge.js"></script>
<script src="js/viewer.js"></script>
<script src="js/editor.js"></script>
<script src="js/history.js"></script>
<script src="js/app.js"></script>
<script>
// Init App safely
try {
window.app = new window.EDIBridge.App();
if (window.lucide) {
try { lucide.createIcons(); } catch (e) { console.warn("Lucide Error", e); }
}
} catch (e) {
console.error("App Fatal Error:", e);
alert("App Fatal Error: " + e.message);
}
</script>
</body>
</html>