feat: redesign settings page with sidebar navigation and improved layout

This commit is contained in:
zed
2026-03-13 15:32:29 +01:00
parent 67bd64b688
commit bffe69abaf
4 changed files with 507 additions and 318 deletions

View File

@@ -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"
}

View File

@@ -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 -->
<!-- ═══════════════════════════════════════════════════════════ -->

View File

@@ -160,6 +160,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;

View File

@@ -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;