Separaten Output-Ordner für INVRPT → VDA 4913 Konvertierungen hinzufügen

Der eingehende Watcher nutzt denselben Input-Ordner für alle Dateitypen,
schreibt INVRPT-Konvertierungen nun aber in einen konfigurierbaren
separaten Output-Ordner. Bleibt das Feld leer, wird der Standard-
Output-Ordner als Fallback verwendet (abwärtskompatibel).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
zed
2026-03-13 12:22:45 +01:00
parent 5ebcad02ed
commit 67bd64b688
4 changed files with 43 additions and 9 deletions

View File

@@ -362,6 +362,21 @@
</button> </button>
</div> </div>
</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> </div>
<!-- Watcher Controls --> <!-- Watcher Controls -->

View File

@@ -88,9 +88,11 @@ class App {
// Disable folder buttons // Disable folder buttons
const btnIn = document.getElementById('btnSelectInput'); const btnIn = document.getElementById('btnSelectInput');
const btnOut = document.getElementById('btnSelectOutput'); const btnOut = document.getElementById('btnSelectOutput');
const btnInvrptOut = document.getElementById('btnSelectInvrptOutput');
const btnStart = document.getElementById('btnStartWatcher'); const btnStart = document.getElementById('btnStartWatcher');
if (btnIn) btnIn.disabled = true; if (btnIn) btnIn.disabled = true;
if (btnOut) btnOut.disabled = true; if (btnOut) btnOut.disabled = true;
if (btnInvrptOut) btnInvrptOut.disabled = true;
if (btnStart) btnStart.disabled = true; if (btnStart) btnStart.disabled = true;
} else { } else {
// Load saved settings // Load saved settings
@@ -101,6 +103,9 @@ class App {
if (settings.outputDir) { if (settings.outputDir) {
document.getElementById('outputDirPath').value = settings.outputDir; document.getElementById('outputDirPath').value = settings.outputDir;
} }
if (settings.invrptOutputDir) {
document.getElementById('invrptOutputPath').value = settings.invrptOutputDir;
}
}); });
} }
} }
@@ -1195,18 +1200,28 @@ class App {
} }
} }
async selectInvrptOutputFolder() {
if (!this.watcher) return;
const folder = await this.watcher.selectFolder();
if (folder) {
document.getElementById('invrptOutputPath').value = folder;
this.watcher.saveSettings({ invrptOutputDir: folder });
}
}
// ─── Settings: Watcher Controls ────────────────────────────────── // ─── Settings: Watcher Controls ──────────────────────────────────
async startWatcher() { async startWatcher() {
if (!this.watcher) return; if (!this.watcher) return;
const inputDir = document.getElementById('inputDirPath').value; const inputDir = document.getElementById('inputDirPath').value;
const outputDir = document.getElementById('outputDirPath').value; const outputDir = document.getElementById('outputDirPath').value;
const invrptOutputDir = document.getElementById('invrptOutputPath').value;
if (!inputDir || !outputDir) { if (!inputDir || !outputDir) {
alert('Bitte beide Ordner (Input & Output) angeben.'); alert('Bitte beide Ordner (Input & Output) angeben.');
return; return;
} }
const result = await this.watcher.start(inputDir, outputDir); const result = await this.watcher.start(inputDir, outputDir, invrptOutputDir);
if (result.error) { if (result.error) {
alert('Watcher-Fehler: ' + result.error); alert('Watcher-Fehler: ' + result.error);
} }

View File

@@ -40,7 +40,7 @@ class WatcherBridge {
} }
async _processDetectedFile(data) { async _processDetectedFile(data) {
const { filePath, fileName, content, outputDir } = data; const { filePath, fileName, content, outputDir, invrptOutputDir } = data;
this._addLog('info', fileName, 'Datei erkannt, starte Konvertierung...'); this._addLog('info', fileName, 'Datei erkannt, starte Konvertierung...');
let konvertierungsmodus = 'Unbekannt'; let konvertierungsmodus = 'Unbekannt';
@@ -71,7 +71,9 @@ class WatcherBridge {
const baseName = fileName.replace(/\.[^.]+$/, ''); const baseName = fileName.replace(/\.[^.]+$/, '');
const outExt = result.format === 'vda' ? '.vda' : (result.format === 'xml' ? '.xml' : '.edi'); const outExt = result.format === 'vda' ? '.vda' : (result.format === 'xml' ? '.xml' : '.edi');
outFileName = baseName + '_converted' + outExt; outFileName = baseName + '_converted' + outExt;
const outPath = outputDir + '\\' + outFileName; const isInvrpt = result.type && result.type.includes('INVRPT');
const effectiveOutputDir = (isInvrpt && invrptOutputDir) ? invrptOutputDir : outputDir;
const outPath = effectiveOutputDir + '\\' + outFileName;
// Write converted file // Write converted file
const writeResult = await window.electronAPI.writeFile(outPath, result.output); const writeResult = await window.electronAPI.writeFile(outPath, result.output);
@@ -275,11 +277,11 @@ class WatcherBridge {
if (this.onLogEntry) this.onLogEntry(entry); if (this.onLogEntry) this.onLogEntry(entry);
} }
async start(inputDir, outputDir) { async start(inputDir, outputDir, invrptOutputDir) {
if (!window.electronAPI) { if (!window.electronAPI) {
return { error: 'Electron API nicht verfügbar. App läuft im Browser-Modus.' }; return { error: 'Electron API nicht verfügbar. App läuft im Browser-Modus.' };
} }
const result = await window.electronAPI.startWatcher({ inputDir, outputDir }); const result = await window.electronAPI.startWatcher({ inputDir, outputDir, invrptOutputDir });
if (result.success) { if (result.success) {
this.status = 'running'; this.status = 'running';
this._addLog('info', '', `Watcher gestartet. Überwache: ${inputDir}`); this._addLog('info', '', `Watcher gestartet. Überwache: ${inputDir}`);

10
main.js
View File

@@ -15,7 +15,7 @@ const edifactValidator = require('./js/edifact-validator');
let mainWindow = null; let mainWindow = null;
let watcher = null; let watcher = null;
let watcherPaused = false; let watcherPaused = false;
let watcherConfig = { inputDir: '', outputDir: '', mode: 'auto' }; let watcherConfig = { inputDir: '', outputDir: '', invrptOutputDir: '', mode: 'auto' };
let outboundWatcher = null; let outboundWatcher = null;
let outboundWatcherPaused = false; let outboundWatcherPaused = false;
@@ -116,8 +116,8 @@ function loadSettings() {
} }
} catch (e) { console.error('Settings load error:', e); } } catch (e) { console.error('Settings load error:', e); }
return { return {
inputDir: '', outputDir: '', mode: 'auto', inputDir: '', outputDir: '', invrptOutputDir: '', mode: 'auto',
outboundInputDir: '', outboundOutputDir: '', mode: 'auto', outboundInputDir: '', outboundOutputDir: '',
werksInputDir: '', werksOutputDir: '' werksInputDir: '', werksOutputDir: ''
}; };
} }
@@ -219,6 +219,7 @@ ipcMain.handle('start-watcher', (_, config) => {
const inputDir = watcherConfig.inputDir; const inputDir = watcherConfig.inputDir;
const outputDir = watcherConfig.outputDir; const outputDir = watcherConfig.outputDir;
const invrptOutputDir = watcherConfig.invrptOutputDir || '';
if (!inputDir || !outputDir) { if (!inputDir || !outputDir) {
return { error: 'Input- und Output-Ordner müssen angegeben werden.' }; return { error: 'Input- und Output-Ordner müssen angegeben werden.' };
@@ -293,7 +294,8 @@ ipcMain.handle('start-watcher', (_, config) => {
filePath, filePath,
fileName, fileName,
content, content,
outputDir outputDir,
invrptOutputDir
}); });
console.log(`[Watcher] Sent to renderer: ${fileName} (${content.length} bytes)`); console.log(`[Watcher] Sent to renderer: ${fileName} (${content.length} bytes)`);