feat: redesign settings page with sidebar navigation and improved layout
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"inputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\LAB\\DELFOR\\ZF",
|
||||
"outputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\LAB",
|
||||
"mode": "auto"
|
||||
"invrptOutputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\EDL",
|
||||
"mode": "auto",
|
||||
"werksInputDir": "\\\\edisrv\\EDI\\IN",
|
||||
"werksOutputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\LAB"
|
||||
}
|
||||
628
index.html
628
index.html
@@ -276,340 +276,336 @@
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||
<!-- PAGE: SETTINGS -->
|
||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||
<!-- 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>
|
||||
<!-- Settings Layout: Sidebar + Content -->
|
||||
<div class="settings-layout">
|
||||
|
||||
<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>
|
||||
<!-- ── Left Sidebar ── -->
|
||||
<nav class="settings-sidebar">
|
||||
<div class="settings-sidebar-header">
|
||||
<i data-lucide="settings-2"></i>
|
||||
<span>Einstellungen</span>
|
||||
</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 class="settings-nav-btn active" data-section="inbound" onclick="app.switchSettingsSection('inbound')">
|
||||
<i data-lucide="arrow-down-to-line"></i>
|
||||
<span>Eingehend</span>
|
||||
</button>
|
||||
<button class="btn-secondary btn-pause" id="btnPauseWatcher" onclick="app.pauseWatcher()" disabled>
|
||||
<i data-lucide="pause"></i>
|
||||
Pausieren
|
||||
<button class="settings-nav-btn" data-section="outbound" onclick="app.switchSettingsSection('outbound')">
|
||||
<i data-lucide="arrow-up-from-line"></i>
|
||||
<span>Ausgehend</span>
|
||||
</button>
|
||||
<button class="btn-secondary btn-resume" id="btnResumeWatcher" onclick="app.resumeWatcher()"
|
||||
style="display:none">
|
||||
<i data-lucide="play"></i>
|
||||
Fortsetzen
|
||||
<button class="settings-nav-btn" data-section="werks" onclick="app.switchSettingsSection('werks')">
|
||||
<i data-lucide="file-symlink"></i>
|
||||
<span>Werksnummer</span>
|
||||
</button>
|
||||
<button class="btn-secondary btn-stop" id="btnStopWatcher" onclick="app.stopWatcher()" disabled>
|
||||
<i data-lucide="square"></i>
|
||||
Stoppen
|
||||
<button class="settings-nav-btn" data-section="mapping" onclick="app.switchSettingsSection('mapping')">
|
||||
<i data-lucide="git-merge"></i>
|
||||
<span>Mapping</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="settings-nav-btn" data-section="log" onclick="app.switchSettingsSection('log')">
|
||||
<i data-lucide="scroll-text"></i>
|
||||
<span>Log</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<!-- 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>
|
||||
<!-- ── Right Content Area ── -->
|
||||
<div class="settings-content">
|
||||
|
||||
<div class="settings-grid">
|
||||
<div class="settings-card">
|
||||
<div class="settings-card-header">
|
||||
<i data-lucide="folder-input"></i>
|
||||
<span>Input-Ordner (Ausgehend)</span>
|
||||
<!-- ─── SECTION: Eingehend ─────────────────────────── -->
|
||||
<div class="settings-section" id="settingsSection-inbound">
|
||||
<div class="settings-section-header">
|
||||
<div>
|
||||
<h2>Eingehende Dateien <span class="settings-section-sub">(Folder Watch)</span></h2>
|
||||
<p class="subtitle">Überwacht einen Netzwerkordner auf neue Dateien, konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.</p>
|
||||
</div>
|
||||
</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
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- Watcher Status Banner -->
|
||||
<div class="watcher-banner" id="watcherBanner">
|
||||
<div class="watcher-banner-left">
|
||||
<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>
|
||||
|
||||
<!-- Folder Cards: 3-column -->
|
||||
<div class="settings-grid-3">
|
||||
<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>
|
||||
</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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-card">
|
||||
<div class="settings-card-header">
|
||||
<i data-lucide="folder-output"></i>
|
||||
<span>Output (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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VDA 711 ID-Umschlüsselung -->
|
||||
<div class="section-panel" style="margin-top: 24px;">
|
||||
<div class="section-panel-header">
|
||||
<i data-lucide="user-check"></i>
|
||||
<div>
|
||||
<h3>VDA 711 ID-Umschlüsselung</h3>
|
||||
<p class="subtitle">Extrahierten IDs (Datenempfänger) eine eigene Kundennummer zuweisen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder-input-row" style="margin-bottom: 16px; margin-top: 16px;">
|
||||
<input type="text" id="newIdMapOriginal" class="folder-path-input" placeholder="Alt (z.B. 8810)" style="max-width: 180px;">
|
||||
<input type="text" id="newIdMapTarget" class="folder-path-input" placeholder="Neu (z.B. 10305)" style="max-width: 180px;">
|
||||
<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></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ─── SECTION: Ausgehend ─────────────────────────── -->
|
||||
<div class="settings-section" id="settingsSection-outbound" style="display:none">
|
||||
<div class="settings-section-header">
|
||||
<div>
|
||||
<h2>Ausgehende Dateien <span class="settings-section-sub">(Folder Watch)</span></h2>
|
||||
<p class="subtitle">Überwacht einen Netzwerkordner auf ausgehende Dateien, konvertiert sie automatisch und schreibt die Ergebnisse in den Output-Ordner.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Watcher Status Banner -->
|
||||
<div class="watcher-banner" id="outboundWatcherBanner">
|
||||
<div class="watcher-banner-left">
|
||||
<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>
|
||||
|
||||
<!-- Folder Cards: 2-column -->
|
||||
<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>
|
||||
</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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ─── SECTION: Werksnummer ───────────────────────── -->
|
||||
<div class="settings-section" id="settingsSection-werks" style="display:none">
|
||||
<div class="settings-section-header">
|
||||
<div>
|
||||
<h2>Werksnummer Umbenennung</h2>
|
||||
<p class="subtitle">Überwacht VDA-Dateien (RA_VDA*) und benennt sie basierend auf der Werksnummer in Satzart 512 um (100 → LEIFERS, 280 → PITESTI).</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Watcher Status Banner -->
|
||||
<div class="watcher-banner" id="werksWatcherBanner">
|
||||
<div class="watcher-banner-left">
|
||||
<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>
|
||||
|
||||
<!-- Folder Cards: 2-column -->
|
||||
<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>
|
||||
</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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ─── SECTION: Mapping ───────────────────────────── -->
|
||||
<div class="settings-section" id="settingsSection-mapping" style="display:none">
|
||||
<div class="settings-section-header">
|
||||
<div>
|
||||
<h2>Kundennummern-Zuordnung</h2>
|
||||
<p class="subtitle">Weisen Sie Kundennummern automatisch einer Konvertierung zu.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-panel">
|
||||
<div class="folder-input-row" style="margin-bottom: 16px;">
|
||||
<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: 260px;">
|
||||
<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></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ─── SECTION: Log ───────────────────────────────── -->
|
||||
<div class="settings-section" id="settingsSection-log" style="display:none">
|
||||
<div class="settings-section-header">
|
||||
<div>
|
||||
<h2>Konvertierungs-Log</h2>
|
||||
<p class="subtitle">Echtzeit-Protokoll aller automatisierten Konvertierungen.</p>
|
||||
</div>
|
||||
<button class="btn-secondary" onclick="app.clearLog()">
|
||||
<i data-lucide="trash-2"></i> Leeren
|
||||
</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 class="log-container" id="logContainer">
|
||||
<div class="log-empty">Noch keine Aktivitäten.</div>
|
||||
</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>
|
||||
</div><!-- /settings-content -->
|
||||
</div><!-- /settings-layout -->
|
||||
</main>
|
||||
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||
<!-- PAGE: VIEWER -->
|
||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
16
js/app.js
16
js/app.js
@@ -159,6 +159,10 @@ class App {
|
||||
});
|
||||
document.getElementById('pageConverter').style.display = page === 'converter' ? '' : 'none';
|
||||
document.getElementById('pageSettings').style.display = page === 'settings' ? '' : 'none';
|
||||
|
||||
if (page === 'settings') {
|
||||
this.switchSettingsSection('inbound');
|
||||
}
|
||||
|
||||
const pageViewer = document.getElementById('pageViewer');
|
||||
if (pageViewer) pageViewer.style.display = page === 'viewer' ? '' : 'none';
|
||||
@@ -177,7 +181,19 @@ class App {
|
||||
if (window.lucide) try { lucide.createIcons(); } catch (e) { }
|
||||
}
|
||||
|
||||
// ─── Settings Sidebar Navigation ─────────────────────────────
|
||||
switchSettingsSection(section) {
|
||||
document.querySelectorAll('.settings-nav-btn').forEach(btn => {
|
||||
btn.classList.toggle('active', btn.dataset.section === section);
|
||||
});
|
||||
document.querySelectorAll('.settings-section').forEach(el => {
|
||||
el.style.display = el.id === `settingsSection-${section}` ? '' : 'none';
|
||||
});
|
||||
if (window.lucide) try { lucide.createIcons(); } catch (e) { }
|
||||
}
|
||||
|
||||
// ─── Config ──────────────────────────────────────────────────────
|
||||
|
||||
async loadConfigFromStorage() {
|
||||
let stored = null;
|
||||
|
||||
|
||||
176
styles.css
176
styles.css
@@ -450,7 +450,181 @@ pre {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ═══ Settings Page ═══ */
|
||||
/* ═══ Settings Page – Sidebar Layout ═══ */
|
||||
.settings-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 200px 1fr;
|
||||
gap: 24px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.settings-sidebar {
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 16px;
|
||||
padding: 12px;
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
.settings-sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px 14px;
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-dim);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.settings-sidebar-header i {
|
||||
color: var(--primary);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.settings-nav-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 11px 14px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-dim);
|
||||
font-weight: 600;
|
||||
font-size: 0.88rem;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.settings-nav-btn i {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.settings-nav-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.settings-nav-btn.active {
|
||||
background: rgba(99, 102, 241, 0.15);
|
||||
color: var(--text);
|
||||
border-left: 3px solid var(--primary);
|
||||
padding-left: 11px;
|
||||
}
|
||||
|
||||
.settings-nav-btn.active i {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
animation: fadeIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
.settings-section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--glass-border);
|
||||
}
|
||||
|
||||
.settings-section-header h2 {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.settings-section-sub {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 400;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
/* ═══ Watcher Banner ═══ */
|
||||
.watcher-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 14px;
|
||||
padding: 14px 20px;
|
||||
margin-bottom: 20px;
|
||||
transition: border-color 0.3s, background 0.3s;
|
||||
}
|
||||
|
||||
.watcher-banner.running {
|
||||
background: rgba(34, 197, 94, 0.06);
|
||||
border-color: rgba(34, 197, 94, 0.35);
|
||||
}
|
||||
|
||||
.watcher-banner.paused {
|
||||
background: rgba(234, 179, 8, 0.06);
|
||||
border-color: rgba(234, 179, 8, 0.35);
|
||||
}
|
||||
|
||||
.watcher-banner-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* ═══ Section Panel (sub-card) ═══ */
|
||||
.section-panel {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 14px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.section-panel-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.section-panel-header > i {
|
||||
color: var(--primary);
|
||||
margin-top: 4px;
|
||||
flex-shrink: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.section-panel-header h3 {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* ═══ 3-column folder grid ═══ */
|
||||
.settings-grid-3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* ═══ Settings Title (legacy – kept for History page) ═══ */
|
||||
.settings-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user