fix: onthoud gesloten startwizard
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 6m7s
All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 6m7s
This commit is contained in:
parent
6c84def759
commit
75eb24741f
6 changed files with 60 additions and 8 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -1,3 +1,18 @@
|
||||||
|
# v0.8.16-beta — De startwizard blijft gesloten
|
||||||
|
|
||||||
|
**De knop Sluiten verborg de optionele startwizard alleen tijdelijk.** De
|
||||||
|
server kreeg daardoor nooit door dat de gebruiker de wizard had overgeslagen en
|
||||||
|
opende hem bij iedere nieuwe paginalading opnieuw.
|
||||||
|
|
||||||
|
- **Sluiten wordt blijvend onthouden.** De knop markeert de wizard nu via de API
|
||||||
|
als afgerond en sluit pas nadat de server dit heeft opgeslagen.
|
||||||
|
- **Een ontbrekende appmap reset de wizard niet meer.** Een nog niet gemounte of
|
||||||
|
tijdelijk onbereikbare library wordt als padprobleem behandeld en overschrijft
|
||||||
|
niet langer een expliciete keuze van de gebruiker.
|
||||||
|
- **Bewust opnieuw starten blijft mogelijk.** De knop “Opnieuw uitvoeren” in
|
||||||
|
Instellingen wist de voltooiingsstatus en opent de wizard weer vanaf het
|
||||||
|
begin.
|
||||||
|
|
||||||
# v0.8.15-beta — Apps verwijderen en mobiele schermen werken weer
|
# v0.8.15-beta — Apps verwijderen en mobiele schermen werken weer
|
||||||
|
|
||||||
**De verwijderknop stopte containers en verwijderde volumes, maar liet de
|
**De verwijderknop stopte containers en verwijderde volumes, maar liet de
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.8.15-beta
|
0.8.16-beta
|
||||||
|
|
|
||||||
|
|
@ -325,9 +325,6 @@ def load() -> dict:
|
||||||
val = cfg.get(key, "").rstrip("/")
|
val = cfg.get(key, "").rstrip("/")
|
||||||
if val in _unsafe or not val.startswith("/"):
|
if val in _unsafe or not val.startswith("/"):
|
||||||
cfg[key] = DEFAULTS[key]
|
cfg[key] = DEFAULTS[key]
|
||||||
# Auto-reset wizard als LIBRARY_DIR niet bestaat (verse installatie met oud volume)
|
|
||||||
if cfg.get("WIZARD_DONE") and not Path(cfg["LIBRARY_DIR"]).exists():
|
|
||||||
cfg["WIZARD_DONE"] = False
|
|
||||||
# Env-overrides gelden alleen voor eenvoudige waarden; lijsten en objecten
|
# Env-overrides gelden alleen voor eenvoudige waarden; lijsten en objecten
|
||||||
# (APP_REPOS, AUTH, NETWORKS, …) zouden anders een kale string worden.
|
# (APP_REPOS, AUTH, NETWORKS, …) zouden anders een kale string worden.
|
||||||
for k, default in DEFAULTS.items():
|
for k, default in DEFAULTS.items():
|
||||||
|
|
|
||||||
|
|
@ -2477,7 +2477,7 @@ tailwind.config = {
|
||||||
<div x-show="wizardStapId() === 'klaar'"><p class="text-sm">We synchroniseren nu de repos en zijn klaar voor gebruik.</p></div>
|
<div x-show="wizardStapId() === 'klaar'"><p class="text-sm">We synchroniseren nu de repos en zijn klaar voor gebruik.</p></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-foot !px-5 sm:!px-7">
|
<div class="modal-foot !px-5 sm:!px-7">
|
||||||
<button class="btn" @click="wizard.open = false" x-text="t('close')">Sluiten</button>
|
<button class="btn" @click="dismissWizard()" x-text="t('close')">Sluiten</button>
|
||||||
<button class="btn" @click="wizard.step = Math.max(0, wizard.step-1)" :disabled="wizard.step===0" x-text="t('prev')">Terug</button>
|
<button class="btn" @click="wizard.step = Math.max(0, wizard.step-1)" :disabled="wizard.step===0" x-text="t('prev')">Terug</button>
|
||||||
<button class="btn btn-primary" @click="wizardNext()"><span x-text="wizard.step < wizard.steps.length-1 ? 'Volgende' : 'Klaar'"></span></button>
|
<button class="btn btn-primary" @click="wizardNext()"><span x-text="wizard.step < wizard.steps.length-1 ? 'Volgende' : 'Klaar'"></span></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -4236,6 +4236,17 @@ function app() {
|
||||||
this.wizard.BACKUP_DIR = d.defaults?.BACKUP_DIR || '/opt/serverup/backups';
|
this.wizard.BACKUP_DIR = d.defaults?.BACKUP_DIR || '/opt/serverup/backups';
|
||||||
this.wizard.open = true;
|
this.wizard.open = true;
|
||||||
},
|
},
|
||||||
|
// De wizard is volledig optioneel. Ook voortijdig sluiten wordt op
|
||||||
|
// de server onthouden, zodat hij niet na elke paginalading terugkomt.
|
||||||
|
async dismissWizard() {
|
||||||
|
const d = await this.rpc('/api/wizard/complete', {});
|
||||||
|
if (!d.ok) {
|
||||||
|
this.toast(d.msg || d.error || this.t('error'), 'er');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.wizard.open = false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
// Opnieuw uitvoeren: markeer als niet-afgerond en open hem.
|
// Opnieuw uitvoeren: markeer als niet-afgerond en open hem.
|
||||||
async resetWizard() {
|
async resetWizard() {
|
||||||
await this.rpc('/api/wizard/reset', {});
|
await this.rpc('/api/wizard/reset', {});
|
||||||
|
|
@ -4296,9 +4307,7 @@ function app() {
|
||||||
} else {
|
} else {
|
||||||
const d = await this.rpc('/api/wizard/sync', {});
|
const d = await this.rpc('/api/wizard/sync', {});
|
||||||
if (d.job_id) this.pollJob(d.job_id, async () => {
|
if (d.job_id) this.pollJob(d.job_id, async () => {
|
||||||
await this.rpc('/api/wizard/complete', {});
|
if (await this.dismissWizard()) this.loadDashboard();
|
||||||
this.wizard.open = false;
|
|
||||||
this.loadDashboard();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,19 @@ check('balk staat halverwege', c.job.progress.pct === 50);
|
||||||
// De poortcontrole praat met de backend, dus die checks zijn asynchroon.
|
// De poortcontrole praat met de backend, dus die checks zijn asynchroon.
|
||||||
// Top-level await kan niet in een CommonJS-script; vandaar deze afsluiting.
|
// Top-level await kan niet in een CommonJS-script; vandaar deze afsluiting.
|
||||||
(async () => {
|
(async () => {
|
||||||
|
// De wizard is optioneel. Ook "Sluiten" moet daarom blijvend onthouden dat
|
||||||
|
// de gebruiker hem niet bij iedere paginalading opnieuw wil zien.
|
||||||
|
let wizardVerzoek = null;
|
||||||
|
c.wizard.open = true;
|
||||||
|
c.rpc = async (url, body) => {
|
||||||
|
wizardVerzoek = {url, body};
|
||||||
|
return {ok: true};
|
||||||
|
};
|
||||||
|
await c.dismissWizard();
|
||||||
|
check('wizard sluiten wordt op de server bewaard',
|
||||||
|
wizardVerzoek.url === '/api/wizard/complete' &&
|
||||||
|
c.wizard.open === false);
|
||||||
|
|
||||||
// ── App verwijderen ───────────────────────────────────────────────────────
|
// ── App verwijderen ───────────────────────────────────────────────────────
|
||||||
// De veilige keuze hoort de appconfiguratie weg te halen en data te bewaren.
|
// De veilige keuze hoort de appconfiguratie weg te halen en data te bewaren.
|
||||||
let verwijderVerzoek = null;
|
let verwijderVerzoek = null;
|
||||||
|
|
|
||||||
18
tests/test_wizard.py
Normal file
18
tests/test_wizard.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
"""De startwizard blijft gesloten nadat de gebruiker hem heeft afgerond."""
|
||||||
|
|
||||||
|
from conftest import login
|
||||||
|
|
||||||
|
|
||||||
|
def test_voltooide_wizard_blijft_voltooid_als_library_niet_bestaat(
|
||||||
|
client, env):
|
||||||
|
login(client)
|
||||||
|
ontbrekend = env["tmp"] / "nog-niet-gemounte-library"
|
||||||
|
env["core"].patch({
|
||||||
|
"LIBRARY_DIR": str(ontbrekend),
|
||||||
|
"WIZARD_DONE": True,
|
||||||
|
})
|
||||||
|
|
||||||
|
antwoord = client.get("/api/wizard")
|
||||||
|
|
||||||
|
assert antwoord.status_code == 200
|
||||||
|
assert antwoord.get_json()["done"] is True
|
||||||
Loading…
Reference in a new issue