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",
|
"inputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\LAB\\DELFOR\\ZF",
|
||||||
"outputDir": "\\\\adewbgsvpas03\\Wincarat\\dfue\\LAB",
|
"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 -->
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<!-- PAGE: SETTINGS -->
|
||||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
<main class="main-card page-content" id="pageSettings" style="display:none">
|
<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 -->
|
<!-- Settings Layout: Sidebar + Content -->
|
||||||
<div class="log-section" style="margin-top: 40px;">
|
<div class="settings-layout">
|
||||||
<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">
|
<!-- ── Left Sidebar ── -->
|
||||||
<div class="folder-input-row" style="margin-bottom: 20px;">
|
<nav class="settings-sidebar">
|
||||||
<input type="text" id="newIdMapOriginal" class="folder-path-input"
|
<div class="settings-sidebar-header">
|
||||||
placeholder="Alt (z.B. 8810)" style="max-width: 200px;">
|
<i data-lucide="settings-2"></i>
|
||||||
<input type="text" id="newIdMapTarget" class="folder-path-input"
|
<span>Einstellungen</span>
|
||||||
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>
|
||||||
|
<button class="settings-nav-btn active" data-section="inbound" onclick="app.switchSettingsSection('inbound')">
|
||||||
<div class="table-container">
|
<i data-lucide="arrow-down-to-line"></i>
|
||||||
<table id="idMapping711Table">
|
<span>Eingehend</span>
|
||||||
<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>
|
||||||
<button class="btn-secondary btn-pause" id="btnPauseWatcher" onclick="app.pauseWatcher()" disabled>
|
<button class="settings-nav-btn" data-section="outbound" onclick="app.switchSettingsSection('outbound')">
|
||||||
<i data-lucide="pause"></i>
|
<i data-lucide="arrow-up-from-line"></i>
|
||||||
Pausieren
|
<span>Ausgehend</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-secondary btn-resume" id="btnResumeWatcher" onclick="app.resumeWatcher()"
|
<button class="settings-nav-btn" data-section="werks" onclick="app.switchSettingsSection('werks')">
|
||||||
style="display:none">
|
<i data-lucide="file-symlink"></i>
|
||||||
<i data-lucide="play"></i>
|
<span>Werksnummer</span>
|
||||||
Fortsetzen
|
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-secondary btn-stop" id="btnStopWatcher" onclick="app.stopWatcher()" disabled>
|
<button class="settings-nav-btn" data-section="mapping" onclick="app.switchSettingsSection('mapping')">
|
||||||
<i data-lucide="square"></i>
|
<i data-lucide="git-merge"></i>
|
||||||
Stoppen
|
<span>Mapping</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<button class="settings-nav-btn" data-section="log" onclick="app.switchSettingsSection('log')">
|
||||||
</div>
|
<i data-lucide="scroll-text"></i>
|
||||||
|
<span>Log</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<!-- Outbound Folder Config -->
|
<!-- ── Right Content Area ── -->
|
||||||
<div class="log-section" style="margin-top: 40px;">
|
<div class="settings-content">
|
||||||
<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">
|
<!-- ─── SECTION: Eingehend ─────────────────────────── -->
|
||||||
<div class="settings-card">
|
<div class="settings-section" id="settingsSection-inbound">
|
||||||
<div class="settings-card-header">
|
<div class="settings-section-header">
|
||||||
<i data-lucide="folder-input"></i>
|
<div>
|
||||||
<span>Input-Ordner (Ausgehend)</span>
|
<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>
|
||||||
<div class="folder-input-row">
|
|
||||||
<input type="text" id="outboundInputPath" class="folder-path-input"
|
<!-- Electron notice -->
|
||||||
placeholder="z.B. \\server\edi\outbound_in" readonly>
|
<div id="electronNotice" class="electron-notice" style="display:none">
|
||||||
<button class="btn-secondary" onclick="app.selectOutboundInput()">
|
<i data-lucide="alert-triangle"></i>
|
||||||
<i data-lucide="folder-open"></i>
|
<span>Ordnerüberwachung ist nur in der Electron-App verfügbar. Bitte starten Sie die App mit <code>npm start</code>.</span>
|
||||||
Wählen
|
</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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="log-container" id="logContainer">
|
||||||
<div class="settings-card">
|
<div class="log-empty">Noch keine Aktivitäten.</div>
|
||||||
<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>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="watcher-controls">
|
</div><!-- /settings-content -->
|
||||||
<div class="watcher-status-display">
|
</div><!-- /settings-layout -->
|
||||||
<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>
|
</main>
|
||||||
|
|
||||||
|
|
||||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
<!-- PAGE: VIEWER -->
|
<!-- PAGE: VIEWER -->
|
||||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
|||||||
16
js/app.js
16
js/app.js
@@ -160,6 +160,10 @@ class App {
|
|||||||
document.getElementById('pageConverter').style.display = page === 'converter' ? '' : 'none';
|
document.getElementById('pageConverter').style.display = page === 'converter' ? '' : 'none';
|
||||||
document.getElementById('pageSettings').style.display = page === 'settings' ? '' : 'none';
|
document.getElementById('pageSettings').style.display = page === 'settings' ? '' : 'none';
|
||||||
|
|
||||||
|
if (page === 'settings') {
|
||||||
|
this.switchSettingsSection('inbound');
|
||||||
|
}
|
||||||
|
|
||||||
const pageViewer = document.getElementById('pageViewer');
|
const pageViewer = document.getElementById('pageViewer');
|
||||||
if (pageViewer) pageViewer.style.display = page === 'viewer' ? '' : 'none';
|
if (pageViewer) pageViewer.style.display = page === 'viewer' ? '' : 'none';
|
||||||
|
|
||||||
@@ -177,7 +181,19 @@ class App {
|
|||||||
if (window.lucide) try { lucide.createIcons(); } catch (e) { }
|
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 ──────────────────────────────────────────────────────
|
// ─── Config ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
async loadConfigFromStorage() {
|
async loadConfigFromStorage() {
|
||||||
let stored = null;
|
let stored = null;
|
||||||
|
|
||||||
|
|||||||
176
styles.css
176
styles.css
@@ -450,7 +450,181 @@ pre {
|
|||||||
transform: none;
|
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 {
|
.settings-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user