This commit is contained in:
@@ -6,6 +6,7 @@ Multi-Hoster-Upload ist eine Electron-Desktopanwendung für Windows, die große
|
|||||||
|
|
||||||
## Aktueller Zustand
|
## Aktueller Zustand
|
||||||
|
|
||||||
|
- Log-Einstellungen nach `2.1.49`: Logpfad und Log-Datei-Modus teilen ein Beschriftungsraster; native Modusauswahl auf 240 px begrenzt, 40 px hoch, Pfeil mit 14 px Innenabstand. Hinweis unter dem Dropdown ohne zusätzliche Einrückung. Ordner-/Öffnen-Buttons bleiben neben dem Pfad; schmale Container wechseln auf gestapelte Felder. IDs, Optionen und Logfunktion unverändert. Electron-Regression mit tatsächlichem Template bei drei Breiten und Screenshotprüfung; noch kein Release.
|
||||||
- Automatik-Abstand nach `2.1.49`: zusätzlicher 22-px-Unterabstand der Statuskarte vor dem neuen Formularcontainer entfernt. Abstand zur ersten Abschnittsüberschrift entspricht jetzt dem folgenden Abschnitt: jeweils 28 px. Electron-Regression misst beide Abstände bei 1000/760/360 px direkt am echten Template; gezielter Test und Lint erfolgreich. Entwicklerversion wird automatisch neu gestartet; noch kein Release.
|
- Automatik-Abstand nach `2.1.49`: zusätzlicher 22-px-Unterabstand der Statuskarte vor dem neuen Formularcontainer entfernt. Abstand zur ersten Abschnittsüberschrift entspricht jetzt dem folgenden Abschnitt: jeweils 28 px. Electron-Regression misst beide Abstände bei 1000/760/360 px direkt am echten Template; gezielter Test und Lint erfolgreich. Entwicklerversion wird automatisch neu gestartet; noch kein Release.
|
||||||
- Ordnerüberwachungstest nach `2.1.49`: IPC verwendet gespeicherte Ordnerregeln in einer isolierten FolderMonitor-Instanz statt der möglicherweise unkonfigurierten laufenden Überwachung. Funktioniert bei deaktivierter, aktiver und pausierter Überwachung; kein Watcher-/Timerstart, keine neuen Dateien/Statusereignisse am produktiven Monitor, keine Änderung seiner Generation oder Duplikatreservierungen. Fehlender Pfad, unerreichbarer Ordner und Scanfehler werden über feste, übersetzte Fehlermeldungen angezeigt; unbekannte Fehler bleiben bereinigt. Regressionen für die drei Betriebszustände, parallele Tests, Fehlerfälle und IPC-Verdrahtung ergänzt; Entwicklung automatisch neu gestartet.
|
- Ordnerüberwachungstest nach `2.1.49`: IPC verwendet gespeicherte Ordnerregeln in einer isolierten FolderMonitor-Instanz statt der möglicherweise unkonfigurierten laufenden Überwachung. Funktioniert bei deaktivierter, aktiver und pausierter Überwachung; kein Watcher-/Timerstart, keine neuen Dateien/Statusereignisse am produktiven Monitor, keine Änderung seiner Generation oder Duplikatreservierungen. Fehlender Pfad, unerreichbarer Ordner und Scanfehler werden über feste, übersetzte Fehlermeldungen angezeigt; unbekannte Fehler bleiben bereinigt. Regressionen für die drei Betriebszustände, parallele Tests, Fehlerfälle und IPC-Verdrahtung ergänzt; Entwicklung automatisch neu gestartet.
|
||||||
- Automatik-Einstellungen nach `2.1.49`: gemeinsames 210-px-Beschriftungsraster für Wiederholungen, Ordnerpfad, Queue-Limit, Abgleichintervall, Dateifilter und Verzögerung. Felder 40 px hoch, Zahlenfelder 120 px breit, Dropdowns auf passende Breiten begrenzt und Pfeile 14 px nach innen versetzt. Hinweise stehen unter ihrem jeweiligen Feld; Container-Abfragen schalten bei schmalem Inhalt auf einspaltige Darstellung. Ordnerüberwachungstest steht nach Verhalten/Hoster-Vorauswahl als Abschlussaktion. IDs und Speicherlogik unverändert. Electron-Regression mit echtem Template bei 1000/760/360 px, Screenshot visuell geprüft; noch kein Release.
|
- Automatik-Einstellungen nach `2.1.49`: gemeinsames 210-px-Beschriftungsraster für Wiederholungen, Ordnerpfad, Queue-Limit, Abgleichintervall, Dateifilter und Verzögerung. Felder 40 px hoch, Zahlenfelder 120 px breit, Dropdowns auf passende Breiten begrenzt und Pfeile 14 px nach innen versetzt. Hinweise stehen unter ihrem jeweiligen Feld; Container-Abfragen schalten bei schmalem Inhalt auf einspaltige Darstellung. Ordnerüberwachungstest steht nach Verhalten/Hoster-Vorauswahl als Abschlussaktion. IDs und Speicherlogik unverändert. Electron-Regression mit echtem Template bei 1000/760/360 px, Screenshot visuell geprüft; noch kein Release.
|
||||||
@@ -95,6 +96,7 @@ npm audit --omit=dev
|
|||||||
|
|
||||||
## Zuletzt verifiziert
|
## Zuletzt verifiziert
|
||||||
|
|
||||||
|
- Log-Layout: 47 Startup-/Electron- und Logmodus-Tests sowie Lint erfolgreich. Gemeinsame Feldkante, Feldhöhe, Dropdownbreite, Pfeil-Innenabstand, Hinweise und unveränderte Modusoptionen bei 1000/760/360 px geprüft. Entwicklerversion automatisch neu gestartet; nicht veröffentlicht.
|
||||||
- Automatik-Abstand: alle 26 Startup-/Electron-Tests und Lint erfolgreich. Gleiche Abschnittsabstände von 28 px bei drei Breiten bestätigt; automatischer Entwicklungsneustart im Watcher-Log nachgewiesen. Kein Release.
|
- Automatik-Abstand: alle 26 Startup-/Electron-Tests und Lint erfolgreich. Gleiche Abschnittsabstände von 28 px bei drei Breiten bestätigt; automatischer Entwicklungsneustart im Watcher-Log nachgewiesen. Kein Release.
|
||||||
- Test bei deaktivierter Ordnerüberwachung: 844 Haupttests, 18 Servertests und Lint erfolgreich. Watcher-Neustart bestätigt. Read-only-Test bleibt unabhängig vom Produktivzustand, bekannte Fehler werden konkret angezeigt. Noch nicht veröffentlicht.
|
- Test bei deaktivierter Ordnerüberwachung: 844 Haupttests, 18 Servertests und Lint erfolgreich. Watcher-Neustart bestätigt. Read-only-Test bleibt unabhängig vom Produktivzustand, bekannte Fehler werden konkret angezeigt. Noch nicht veröffentlicht.
|
||||||
- Automatik-Layout: 840 Haupttests, 18 Servertests und Lint erfolgreich. Feldhöhen, gemeinsame linke Kante, Label-/Hinweispositionen, Dropdownbreiten/Pfeilabstand und Abschlussposition der Testaktion über echte Electron-DOM-Messungen geprüft. Watcher-Neustart und sichtbare Entwicklungsinstanz bestätigt. Noch nicht veröffentlicht.
|
- Automatik-Layout: 840 Haupttests, 18 Servertests und Lint erfolgreich. Feldhöhen, gemeinsame linke Kante, Label-/Hinweispositionen, Dropdownbreiten/Pfeilabstand und Abschlussposition der Testaktion über echte Electron-DOM-Messungen geprüft. Watcher-Neustart und sichtbare Entwicklungsinstanz bestätigt. Noch nicht veröffentlicht.
|
||||||
|
|||||||
+12
-4
@@ -6505,21 +6505,29 @@ function renderSettings() {
|
|||||||
pages.logs.innerHTML = `
|
pages.logs.innerHTML = `
|
||||||
${pageHeader('Logs & Support', 'Protokollierung verwalten, Log-Dateien öffnen und ein bereinigtes Support-Paket erstellen.')}
|
${pageHeader('Logs & Support', 'Protokollierung verwalten, Log-Dateien öffnen und ein bereinigtes Support-Paket erstellen.')}
|
||||||
<div class="settings-section-label">Log</div>
|
<div class="settings-section-label">Log</div>
|
||||||
<div class="settings-row log-file-path-row">
|
<div class="log-config-fields">
|
||||||
<label>FileUploader Log</label>
|
<div class="settings-row log-file-path-row log-config-row">
|
||||||
|
<label for="logFilePathInput">FileUploader Log</label>
|
||||||
|
<div class="log-path-controls">
|
||||||
<input type="text" class="key-input settings-autosave" id="logFilePathInput" value="${escapeAttr(globalSettings.logFilePath || '')}" placeholder="Standardpfad verwenden">
|
<input type="text" class="key-input settings-autosave" id="logFilePathInput" value="${escapeAttr(globalSettings.logFilePath || '')}" placeholder="Standardpfad verwenden">
|
||||||
<button class="btn btn-xs btn-secondary" id="chooseLogFilePathBtn">Ordner wählen</button>
|
<button class="btn btn-xs btn-secondary" id="chooseLogFilePathBtn">Ordner wählen</button>
|
||||||
<button class="btn btn-xs btn-secondary" id="openLogFolderBtn" title="Log-Ordner im Explorer öffnen">Öffnen</button>
|
<button class="btn btn-xs btn-secondary" id="openLogFolderBtn" title="Log-Ordner im Explorer öffnen">Öffnen</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-row">
|
</div>
|
||||||
<label>Log-Datei-Modus</label>
|
<div class="settings-row log-config-row">
|
||||||
|
<label for="logModeInput">Log-Datei-Modus</label>
|
||||||
|
<div class="log-mode-controls">
|
||||||
|
<span class="settings-select-control">
|
||||||
<select class="hs-input settings-autosave" id="logModeInput">
|
<select class="hs-input settings-autosave" id="logModeInput">
|
||||||
<option value="single" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'single' ? 'selected' : ''}>Eine Datei</option>
|
<option value="single" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'single' ? 'selected' : ''}>Eine Datei</option>
|
||||||
<option value="daily" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'daily' ? 'selected' : ''}>Pro Tag</option>
|
<option value="daily" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'daily' ? 'selected' : ''}>Pro Tag</option>
|
||||||
<option value="session" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'session' ? 'selected' : ''}>Pro Session</option>
|
<option value="session" ${(window.LogMode ? window.LogMode.normalizeLogMode(globalSettings) : (globalSettings.logMode || 'single')) === 'session' ? 'selected' : ''}>Pro Session</option>
|
||||||
</select>
|
</select>
|
||||||
|
</span>
|
||||||
<span class="hint">Pro Session = neue Datei bei jedem App-Start; nach komplettem Schließen + erneutem Öffnen beginnt eine neue Session.</span>
|
<span class="hint">Pro Session = neue Datei bei jedem App-Start; nach komplettem Schließen + erneutem Öffnen beginnt eine neue Session.</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="settings-option verbose-logging-option">
|
<div class="settings-option verbose-logging-option">
|
||||||
<div class="settings-option-copy">
|
<div class="settings-option-copy">
|
||||||
<label for="logVerboseInput">Verbose Logging</label>
|
<label for="logVerboseInput">Verbose Logging</label>
|
||||||
|
|||||||
+68
-22
@@ -3926,25 +3926,6 @@ input[type="checkbox"] {
|
|||||||
background: #3c3b6e;
|
background: #3c3b6e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-file-path-row {
|
|
||||||
display: flex !important;
|
|
||||||
align-items: center !important;
|
|
||||||
flex-wrap: wrap !important;
|
|
||||||
gap: 8px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.log-file-path-row > label {
|
|
||||||
min-width: 140px !important;
|
|
||||||
flex: 1 1 190px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.log-file-path-row > .key-input {
|
|
||||||
width: auto;
|
|
||||||
min-width: 180px !important;
|
|
||||||
max-width: 100%;
|
|
||||||
flex: 999 1 260px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.log-file-path-row .btn {
|
.log-file-path-row .btn {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -4953,7 +4934,8 @@ input[type="checkbox"] {
|
|||||||
grid-template-columns: minmax(0, 180px) minmax(0, 1fr);
|
grid-template-columns: minmax(0, 180px) minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.automation-select-control {
|
.automation-select-control,
|
||||||
|
.settings-select-control {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -4961,7 +4943,8 @@ input[type="checkbox"] {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.automation-select-control::after {
|
.automation-select-control::after,
|
||||||
|
.settings-select-control::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -4974,7 +4957,8 @@ input[type="checkbox"] {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-subpage .automation-select-control > select {
|
.settings-subpage .automation-select-control > select,
|
||||||
|
.settings-subpage .settings-select-control > select {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
padding-right: 38px;
|
padding-right: 38px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -5000,3 +4984,65 @@ input[type="checkbox"] {
|
|||||||
grid-template-columns: minmax(0, 1fr);
|
grid-template-columns: minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.log-config-fields {
|
||||||
|
container: log-fields / inline-size;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-subpage .settings-row.log-config-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 210px minmax(0, 1fr);
|
||||||
|
align-items: start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-subpage .settings-row.log-config-row > label {
|
||||||
|
min-width: 0;
|
||||||
|
padding-top: 9px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-path-controls {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-mode-controls {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-subpage .log-config-fields :is(.key-input, .hs-input) {
|
||||||
|
min-width: 0;
|
||||||
|
max-width: none;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 40px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@container log-fields (max-width: 620px) {
|
||||||
|
.settings-subpage .settings-row.log-config-row {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-subpage .settings-row.log-config-row > label {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@container log-fields (max-width: 380px) {
|
||||||
|
.log-path-controls {
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
justify-content: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-path-controls > input {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ app.whenReady().then(async () => {
|
|||||||
assert.equal(data.ok, true);
|
assert.equal(data.ok, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('automation fields share a responsive grid and leave hints below their controls', { skip: process.platform !== 'win32' }, t => {
|
test('automation and log fields share responsive grids and aligned hints', { skip: process.platform !== 'win32' }, t => {
|
||||||
const root = path.resolve(__dirname, '..');
|
const root = path.resolve(__dirname, '..');
|
||||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'mhu-automation-layout-'));
|
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'mhu-automation-layout-'));
|
||||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
||||||
@@ -261,6 +261,23 @@ app.whenReady().then(async()=>{
|
|||||||
for(const select of data.selects){assert.ok(select.width<=240);assert.equal(select.arrow,'14px')}
|
for(const select of data.selects){assert.ok(select.width<=240);assert.equal(select.arrow,'14px')}
|
||||||
if(process.env.MHU_AUTOMATION_SCREENSHOT && width===1000){await new Promise(resolve=>setTimeout(resolve,500));fs.writeFileSync(process.env.MHU_AUTOMATION_SCREENSHOT,(await wc.capturePage()).toPNG())}
|
if(process.env.MHU_AUTOMATION_SCREENSHOT && width===1000){await new Promise(resolve=>setTimeout(resolve,500));fs.writeFileSync(process.env.MHU_AUTOMATION_SCREENSHOT,(await wc.capturePage()).toPNG())}
|
||||||
}
|
}
|
||||||
|
context.pages.logs={};context.window={};
|
||||||
|
vm.runInNewContext(source.slice(source.indexOf('pages.logs.innerHTML ='),source.indexOf('pages.remote.innerHTML =')),context);
|
||||||
|
for(const width of [1000,760,360]){
|
||||||
|
win.setContentSize(width,700);
|
||||||
|
await wc.loadURL('data:text/html;charset=utf-8,'+encodeURIComponent('<style>'+css+'</style><main id="settings-view" style="display:block;padding:16px;width:100%"><div class="settings-subpage" style="display:block;width:100%">'+context.pages.logs.innerHTML+'</div></main>'));
|
||||||
|
const layout=await wc.executeJavaScript('(() => {const rect=e=>{const r=e.getBoundingClientRect();return {left:r.left,right:r.right,top:r.top,bottom:r.bottom,width:r.width,height:r.height}};const select=document.getElementById("logModeInput");return {input:rect(document.getElementById("logFilePathInput")),select:rect(select),hint:rect(document.querySelector(".log-mode-controls .hint")),arrow:getComputedStyle(select.parentElement,"::after").right,overflow:document.documentElement.scrollWidth>innerWidth,options:Array.from(select.options).map(o=>o.value)};})()');
|
||||||
|
assert.equal(layout.input.left,layout.select.left);
|
||||||
|
assert.equal(layout.input.height,40);
|
||||||
|
assert.equal(layout.select.height,40);
|
||||||
|
assert.ok(layout.select.width<=240);
|
||||||
|
assert.equal(layout.hint.left,layout.select.left);
|
||||||
|
assert.ok(layout.hint.top>=layout.select.bottom+6);
|
||||||
|
assert.equal(layout.arrow,'14px');
|
||||||
|
assert.equal(layout.overflow,false);
|
||||||
|
assert.deepEqual(layout.options,['single','daily','session']);
|
||||||
|
if(process.env.MHU_LOG_SCREENSHOT && width===1000){await new Promise(resolve=>setTimeout(resolve,500));fs.writeFileSync(process.env.MHU_LOG_SCREENSHOT,(await wc.capturePage()).toPNG())}
|
||||||
|
}
|
||||||
win.destroy();fs.writeFileSync(process.env.MHU_AUTOMATION_RESULT,JSON.stringify({ok:true}));app.exit(0);
|
win.destroy();fs.writeFileSync(process.env.MHU_AUTOMATION_RESULT,JSON.stringify({ok:true}));app.exit(0);
|
||||||
}).catch(error=>{fs.writeFileSync(process.env.MHU_AUTOMATION_RESULT,JSON.stringify({error:error.stack}));app.exit(1)});
|
}).catch(error=>{fs.writeFileSync(process.env.MHU_AUTOMATION_RESULT,JSON.stringify({error:error.stack}));app.exit(1)});
|
||||||
`);
|
`);
|
||||||
|
|||||||
Reference in New Issue
Block a user