10 KiB
quick_id, type, wave, autonomous, files_modified
| quick_id | type | wave | autonomous | files_modified | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 260924-h7x | quick | 1 | true |
|
Quick 260924-h7x — Proxmox-Seite: Status-Design mit Tiefe; Dashboard-Reiter in die Kopfzeile
Nutzerauftrag (24.09.): „Kennzeichnen als offline & verwaist. Das Proxmox-Modul scheint zu funktionieren, aber es gefällt mir optisch gar nicht. Benutze den Design-Skill und überarbeite etwas — mehr Tiefe, Farben nach Status etc. Die Reiter sind da, aber die müssen woanders hin, die nehmen zu viel Platz ein. Auch mit Design.“
Die frühere Sperre „KEIN Umbau der Proxmox-Modulseite“ (23.09.) ist damit durch den Nutzer selbst aufgehoben.
Design-Plan vom Orchestrator (frontend-design-Skill) — verbindlich, nicht neu erfinden.
Keine neuen Pakete. App-Texte deutsch in Sie-Form, alle Schlüssel in de.json UND en.json.
Keine Großbuchstaben-Etiketten (kein uppercase, kein tracking-widest), keine
Mittelpunkt-Ketten „A · B · C“ in neuen Texten, kein „→“ an Knöpfen.
Design-Tokens (in globals.css, :root und .dark)
Statusfarben als OKLCH-Variablen plus Tailwind-Abbildung in @theme inline
(--color-status-ok usw., damit bg-status-ok, text-status-ok, border-status-ok/40 gehen):
| Token | hell | dunkel | Bedeutung |
|---|---|---|---|
--status-ok |
oklch(0.62 0.15 152) |
oklch(0.72 0.15 152) |
in Ordnung |
--status-warn |
oklch(0.72 0.15 70) |
oklch(0.80 0.14 75) |
Warnung |
--status-down |
oklch(0.58 0.21 27) |
oklch(0.68 0.19 27) |
nicht erreichbar / Fehler |
--status-idle |
oklch(0.62 0.02 260) |
oklch(0.60 0.02 260) |
noch nicht abgefragt |
--status-orphan |
oklch(0.55 0.01 260) |
oklch(0.52 0.01 260) |
offline & verwaist |
--well |
oklch(0.975 0.003 260) |
oklch(0.235 0.01 260) |
eingelassene Messfelder |
Kontrast prüfen: Text in Statusfarbe auf --card muss ≥ 4.5:1 (Fließtext) bzw. ≥ 3:1
(große/fette Zahlen) erreichen — sonst Helligkeit anpassen und die gemessene Zahl in der
SUMMARY nennen.
Task 1 — Statuslogik als reine Funktionen (TDD)
Neue Datei components/proxmox-status.ts:
serverHealth(server): 'ok' | 'warn' | 'down' | 'idle' | 'orphan'!server.isActive→orphan(VORRANG vor allem anderen — „offline & verwaist“, auch wenn alte Messwerte im Zwischenlager liegen)- kein
statusoderstatus.lastPolledAt === null→idle !status.reachable→down- erreichbar + irgendein Messwert über Warnschwelle →
warn - sonst
ok
- Schwellen als EINE benannte Konstante
THRESHOLDS: Last/Arbeitsspeicher/Datenspeicher warn ≥ 0.80, kritisch ≥ 0.92; PBS letzte Sicherung älter als 26 h → warn;lastVerifyStateungleichok(und nicht null) → warn; PMGvirusCount > 0→ warn. meterLevel(fraction | null): 'ok' | 'warn' | 'crit' | 'unknown'für die Balken.formatAge(epochSeconds|iso, now)→ „vor 3 Min.“, „vor 5 Std.“, „vor 2 Tagen“ überIntl.RelativeTimeFormat('de')bzw. next-intl — keine neue Abhängigkeit.- Tests für jede Verzweigung inkl.
null-Werte (unbekannt ≠ 0, nie Warnung ausnull).
Task 2 — Proxmox-Seite und Karte neu gestalten
Seitenkopf: Titel „Proxmox“ links, darunter die Beschreibung. Rechts „Jetzt aktualisieren“
(nur Admins, wie heute) als richtiger Knopf mit Kreispfeil-Symbol (dreht sich während des Laufs;
motion-reduce:animate-none) und „Einstellungen“ als ruhiger Textlink. Breite max-w-5xl.
Gesundheitsbalken (das eine prägnante Element der Seite): direkt unter dem Kopf ein
waagrechter Balken, 8 px hoch, voll gerundet, anteilig in Segmente je Zustand geteilt
(Reihenfolge down, warn, ok, idle, orphan; leere Zustände entfallen). Darunter eine Zeile mit
Legende: farbiger Punkt + Zahl + Wort („2 in Ordnung“, „1 nicht erreichbar“, „1 offline &
verwaist“ …, ICU-Plural). Segmente role="img" mit aria-label, das die Zusammenfassung vorliest.
Keine Zahl-in-riesig-plus-Verlauf-Heldenkachel.
Kartenraster: grid gap-4 lg:grid-cols-2. Sortierung: down, warn, ok, idle, orphan, darin
position. (Die Einstellungsseite behält ihre Reihenfolge.)
Karte (Tiefe über Status, nicht Einheits-Schatten):
- Karte
rounded-xl bg-cardmit Randborder-border, links eine 4 px breite Statusleiste (absolut positioniert, volle Höhe, Farbe = Status). - Schatten zweischichtig und im Statuston getönt, z. B.
shadow-[0_1px_2px_oklch(0_0_0/0.06),0_12px_28px_-14px_var(--status-x)]— beiorphanKEIN farbiger Schatten, stattdessen gestrichelter Rand (border-dashed), Inhaltopacity-70 saturate-50. - Kopfzeile: Produktsymbol (kleines inline-SVG je Typ: PVE = Server-Einschübe, PBS =
Archivkiste/Datenträger, PMG = Briefumschlag) in einem 32 px Feld mit
bg-well, daneben Name (fett) und darunter Produktname ausgeschrieben („Virtualisierung“, „Datensicherung“, „Mail-Gateway“) plus Adresse klein und gedämpft. Rechts eine Statuspille: Punkt + Wort („In Ordnung“, „Warnung“, „Nicht erreichbar“, „Noch nicht abgefragt“, „Offline & verwaist“), Hintergrund Statusfarbe /12, Text in Statusfarbe. Beiokpulsiert der Punkt EINMAL beim Laden nicht — keine Dauer-Animation. - Fuß der Karte: „Letzte Abfrage vor 4 Min.“ (relativ,
titlemit exaktem Zeitpunkt).
Messbereich je Produkt, als eingelassene Felder (bg-well, rounded-lg,
shadow-[inset_0_1px_2px_oklch(0_0_0/0.06)]):
- PVE: oben zwei Kennzahlen nebeneinander: laufende Gäste (groß,
tabular-nums) und gestoppte Gäste (gedämpft), Knotenzahl klein. Darunter je Knoten ein „Einschub“: Knotenname links, rechts zwei schmale Balken „Prozessor“ und „Arbeitsspeicher“ mit Prozentzahl (tabular-nums) und bei Speicher „12,0 / 64,0 GB“ alstitle/kleine Zeile. Balkenfarbe nachmeterLevel. Unbekannter Wert: Balken schraffiert/leer + Text „unbekannt“, NIE 0 %. Deutsche Zahlformate (Komma) überIntl.NumberFormat('de-DE'). - PBS: je Datenspeicher ein Einschub: Name, Füllstandsbalken mit „1,2 / 4,0 TB“, darunter „Letzte Sicherung vor 5 Std.“ (warn-Farbe, wenn > 26 h; „noch keine Sicherung“ gedämpft) und Prüfstatus als kleine Pille (ok grün, sonst warn, null „unbekannt“ grau).
- PMG: vier Zahlfelder im 2×2-Raster: Eingehend, Ausgehend, Spam, Viren; Viren > 0 in
down-Farbe, sonst normal.
null→ „unbekannt“.
Zustände ohne Messwerte:
down: roter Hinweisblock im Well (bg-status-down/8, Rand links in Statusfarbe) mit der bekannten Fehlermeldung (errors.*) und darunter gedämpft „Zuletzt erreichbar: vor 2 Tagen“ bzw. nichts, wenn nie.errorDetailklein und gedämpft in eigener Zeile, nicht in Klammern an den Satz gehängt.idle: ruhiger Text wie heute (Admin-/Nicht-Admin-Variante bleibt, 260923-le6).orphan: Text „Dieser Server ist deaktiviert und wird nicht mehr abgefragt.“ plus für Admins der Hinweis, dass er in den Einstellungen wieder aktiviert werden kann (Link). Alte Messwerte werden beiorphanNICHT angezeigt.
Leer-, Lade-, Fehlerzustand der Seite: Leerzustand als Well mit Serversymbol und Satz +
Link (Admins); Laden als zwei Skelett-Karten (animate-pulse, motion-reduce:animate-none).
Tests: bestehende ServerCard-/Seitentests anpassen (Texte/Strukturen), neue Tests für orphan (Vorrang, keine alten Werte), Sortierung, Gesundheitsbalken-Zusammenfassung, unbekannte Werte als „unbekannt“. Die Nur-Admin-Regeln aus 260923-le6 müssen weiter getestet sein.
Task 3 — Dashboard-Reiter in die Kopfzeile
Heute belegt DashboardTabs eine eigene Zeile über dem Raster (app/(portal)/page.tsx), die
Kopfzeilenmitte (components/layout/header.tsx) zeigt nur den Text „Startseite“.
- Kopfzeile bekommt in der Mitte einen Einhängepunkt
<div id="header-center-slot">. Auf der Startseite (pathname === '/') entfällt der Text „Startseite“; auf allen anderen Seiten bleibt alles wie heute. DashboardTabsrendert percreatePortalin diesen Einhängepunkt (sobald er im DOM ist —useEffect+ State; Rückfall: solange kein Einhängepunkt da ist, nichts rendern). Die eigene Zeile über dem Raster entfällt ersatzlos.- Gestaltung als kompakter Umschalter mit Tiefe: eine eingelassene Spur (
bg-muted,rounded-lg,p-0.5,shadow-[inset_0_1px_2px_oklch(0_0_0/0.08)], Höhe 32 px), darin die Reiter als Textknöpfe (text-sm,px-3,h-7); der aktive Reiter liegt erhaben darauf (bg-card,shadow-sm,font-medium, Textforeground), inaktive gedämpft mit Hover. Keine Unterstreichung, kein Gelb-Flächen-Reiter. - Viele Reiter: Spur höchstens
max-w-[min(56vw,720px)], waagrecht scrollbar ohne sichtbare Leiste, an den Rändern weich ausgeblendet (mask-imagenur wenn überläuft), aktiver Reiter wird ins Bild gescrollt. - Bearbeitungsmodus: Umbenennen/Löschen/Ziehen/Anlegen bleiben funktional gleich (alle bestehenden Tests grün halten bzw. nur Selektoren anpassen). „+“ als 28-px-Rundknopf am Ende der Spur (immer sichtbar, wie heute der Anlegen-Knopf sichtbar ist — Verhalten beibehalten). Löschen-Kreuz erscheint im Bearbeitungsmodus klein im Reiter.
- Genau EIN Reiter: Umschalter trotzdem zeigen (sonst weiß niemand, dass es Reiter gibt), aber nur mit „+“ daneben.
- Mobil (< md): die Spur darf die Kopfzeilenmitte füllen; Logo-Schriftzug bleibt, Aktionen rechts bleiben erreichbar — nichts darf die Kopfzeile sprengen (overflow prüfen).
- Tastatur: Pfeiltasten links/rechts zwischen Reitern (
role="tablist"/tab,aria-selected), sichtbarer Fokusring. navigation "Dashboard-Reiter"-Beschriftung bleibt alsaria-label.
Tests: dashboard-tabs.test.tsx an Portal anpassen (Einhängepunkt im Test anlegen), neuer Test:
Kopfzeile zeigt „Startseite“ nicht auf /, aber auf anderen Pfaden; Pfeiltasten.
Tore
pnpm --filter web exec vitest runkomplett grünpnpm turbo run type-check lintgrün, Biome-Warnungen web nicht mehr als 53- CHANGELOG „Unveröffentlicht“: je ein Eintrag unter „Neu“/„Geändert“ in Nutzersprache
- Browser-Nachweis macht der Orchestrator (hell UND dunkel, 1400 px und 390 px Breite)