Wizard-Hoehe fix, Logout in Konto, Server-Reset, responsive Tabs, Set-Zeilen, Brand-Date
Image bauen und in die Registry schieben / build (push) Successful in 7s

- Wizard: feste Hoehe (600px, intern scrollbar), Schritt-Inhalt zentriert
  (.wizard-body) -> Schritte gleich gross, auch beim User anlegen
- Benutzer-Anlage: Bestaetigung 'Benutzer x angelegt.' (ohne 'Weiter mit'),
  Solo-Option nach User-Anlage deaktiviert (kein irrefuehrendes Umschalten)
- User-Chip + Abmelden aus der Topbar entfernt, 'Abmelden' in Konto-Sektion
- Topbar-Datum: 'Fr 02.10.2026' + aktive Session ('Push aktiv') statt
  redundantem 'Today'
- Tabs: flex-wrap statt Scrollen, auf Mobil volle Breite + kompakter
- Server-Reset (Owner): Passwort + 'RESET'-Eingabe, loescht alle Daten
- Benutzerliste: Querbalken vor dem Anlegen-Formular
- Tests: 163 Checks gruen (39+18+49+32+25)
This commit is contained in:
AI-Agent committed 2026-10-02 19:42:46 +00:00
1 parent 0ebaa8b132
commit 655316278a
6 files changed
+183 -52

No files matched your search

+19
View File
@@ -270,6 +270,25 @@ def main():
st, done_a = req("GET", "/api/sessions?status=done", token=token_a)
check("A-Daten nach Loeschung von B intakt", len(done_a) == 1, len(done_a))
# --- Server-Reset (doppelt gesichert) -----------------------------------
st, _ = req("POST", "/api/reset",
{"password": "falsch", "confirm": "RESET"}, token=token_a)
check("Reset: falsches Passwort -> 400", st == 400, st)
st, _ = req("POST", "/api/reset",
{"password": "neu123", "confirm": "NEIN"}, token=token_a)
check("Reset: falscher Bestaetigungstext -> 400", st == 400, st)
st, _ = req("POST", "/api/reset",
{"password": "neu123", "confirm": "RESET"}, token=token_a)
check("Reset: korrekt -> 200", st == 200, st)
st, meta = req("GET", "/api/meta")
check("Reset: offener Modus (kein Benutzer mehr)",
meta["users"] == 0 and meta["auth_required"] is False, meta)
st, me = req("GET", "/api/me", token=token_a)
check("Reset: im offenen Modus kein Benutzername",
st == 200 and me.get("username") is None, me)
st, _ = req("GET", "/api/sessions")
check("Reset: Sessions ohne Anmeldung wieder sichtbar (offen)", st == 200, st)
finally:
proc.terminate()
proc.wait(timeout=5)
+6 -8
View File
@@ -152,7 +152,7 @@ check("Setup: Sprache kommt zuerst",
break;
}
if (winNoToken.document.querySelectorAll(".act-card").length === 3
&& winNoToken.document.querySelector("#user-chip").textContent === "alex") {
&& winNoToken.document.querySelector("#logout-btn") === null) {
loggedIn = true;
break;
}
@@ -174,10 +174,7 @@ check("Setup: Sprache kommt zuerst",
}
check("Login: Onboarding abgeschlossen, Heute-Ansicht sichtbar",
ogate() && ogate().hidden
&& winNoToken.document.querySelectorAll(".act-card").length === 3
&& winNoToken.document.querySelector("#user-chip").textContent === "alex");
check("Login: Abmelden-Knopf sichtbar",
!winNoToken.document.querySelector("#logout-btn").hidden);
&& winNoToken.document.querySelectorAll(".act-card").length === 3);
check("Login: kein Auth-Gate mehr",
winNoToken.document.querySelector("#auth-gate").hidden);
@@ -186,8 +183,7 @@ check("Setup: Sprache kommt zuerst",
await sleep(1200);
let tokOk = false;
for (let i = 0; i < 50; i++) {
if (winTok.document.querySelectorAll(".act-card").length === 3
&& winTok.document.querySelector("#user-chip").textContent === "alex") {
if (winTok.document.querySelectorAll(".act-card").length === 3) {
tokOk = true;
break;
}
@@ -210,7 +206,9 @@ check("Setup: Sprache kommt zuerst",
&& Array.from(winTok.document.querySelectorAll(".data-section"))
.some(s => s.querySelector("h3").textContent === "Konto"
&& !!s.querySelector('input[placeholder="Aktuelles Kennwort"]')
&& !!s.querySelector('input[placeholder="Neues Kennwort"]')));
&& !!s.querySelector('input[placeholder="Neues Kennwort"]')
&& Array.from(s.querySelectorAll(".btn"))
.some(b => b.textContent === "Abmelden")));
check("Einstellungen: nur ein Benutzer -> Hinweis statt Liste", await (async () => {
for (let i = 0; i < 40; i++) {
if (Array.from(winTok.document.querySelectorAll(".user-row"))