diff --git a/README.md b/README.md index 0ffa2ec..1f84c50 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ Alternativ: installiertes Paket mit Entry-Point in der Gruppe ```python from fastapi import Depends, Request from redaktionskern.auth.deps import require_user -from redaktionskern.contracts import BasePlugin, Migration, NavEntry +from redaktionskern.contracts import BasePlugin, DashboardKarte, Migration, NavEntry class MeinPlugin(BasePlugin): name = "meinplugin" # eindeutig, = Ordnername @@ -174,6 +174,12 @@ class MeinPlugin(BasePlugin): def navigation(self): # Einträge in der Hauptnavigation (optional) return [NavEntry(label=self.title, url="/meinplugin")] + def dashboard_karten(self, user): # Dashboard-Karten (optional, leer = keine) + return [DashboardKarte(titel="…", wert="…", link_url="/meinplugin")] + + def nav_badges(self, user_id): # Zähler-Badges in der Navigation + return {"/meinplugin": 3} # (optional; Werte <= 0 werden ignoriert) + def on_load(self, context): # Lifecycle-Hook beim Start super().on_load(context) # context.engine/.session_factory/.templates/ # .settings/.registry (Plugin-Registry für @@ -187,7 +193,10 @@ plugin = MeinPlugin() Der Kern stellt jedem Plugin über `context.templates` eine gemeinsame Jinja- Umgebung bereit (Plugin-Templates erben `base.html`), dazu Engine und -Session-Fabrik. Migrationen laufen transaktional und werden pro Plugin in +Session-Fabrik. Zusätzlich stehen allen Templates die Kern-Makros zur +Verfügung: `icons.html` (Inline-SVG-Icons), `status.html` (`status_badge` — +einheitliche Status-Farben) und `seitennavigation.html` (klassische +Seitennavigation). Migrationen laufen transaktional und werden pro Plugin in `schema_migrations` protokolliert; die `up`-Funktionen bekommen eine SQLAlchemy-Connection und können bei Dialekt-Unterschieden verzweigen. @@ -664,10 +673,11 @@ geschrieben. ## Oberfläche: Coverbilder & responsives Layout **Coverbilder:** Die Listen (Neuheiten, Planung, Archiv) zeigen je Eintrag -eine kleine Cover-Vorschau (40×56 px, `loading="lazy"`, `decoding="async"`, +eine kleine Cover-Vorschau (48×68 px, `loading="lazy"`, `decoding="async"`, Alt-Text = Spieltitel); die Detail-/Prüf-Ansichten der Planung zeigen das Cover großformatig (max. 200 px Breite). Fehlt ein Bild, erscheint ein -dezenter CSS-Platzhalter mit Spielicon-Zeichen. Eingebettet wird per +dezenter Platzhalter mit SVG-Würfel (in der Großansicht zusätzlich mit dem +Hinweis „Kein Cover"). Eingebettet wird per Hotlink direkt von BGG bzw. der jeweiligen Quelle — es werden keine Bilder heruntergeladen oder lokal gespeichert. @@ -686,6 +696,34 @@ heruntergeladen oder lokal gespeichert. Getestet gegen 375 px (Smartphone), 768 px (Tablet) und Desktop. +**Bedienung & Konsistenz (UI/UX-Runde):** + +- **Dashboard:** rollenbasierte Karten statt Technik-Liste — Rezensenten + sehen ihre offenen/in-Bearbeitung-Einträge, Redaktionsschlüsse und + ungelesene Benachrichtigungen; Redaktion zusätzlich Neuheiten-Stand, + Planungs-Stats und offene Dedup-Konflikte; Admins zusätzlich + Benutzer-Anzahl, letzte Audit-Einträge und System-Status + (BGG-Token/Sync). Karten kommen per `dashboard_karten`-Hook aus den + Plugins; die Plugin-Liste steckt in einem aufklappbaren Admin-Bereich. +- **Icons:** Alle Emojis sind durch Inline-SVGs ersetzt + (`icons.html`-Makros, `currentColor`, `aria-hidden`). +- **Status-Badges:** einheitliches Farbsystem über `status_badge` + (neu/abgeschlossen = emerald, offen = slate, in Bearbeitung = sky, + Warnung/Konflikt/Prüfung = amber mit Warn-Icon, Fehler = red, + deaktiviert/archiviert = slate). +- **Löschen mit Bestätigung:** Alpine-Dialog „Eintrag löschen?" in Planung + und Erinnerungen (ohne JavaScript sendet das Formular direkt). +- **Pagination:** klassische Seitennavigation (Zurück/Weiter + + Seitenzahlen) für Neuheiten, Planung und Audit-Log — funktioniert ohne + JavaScript. +- **Tabellen:** Sticky-Header in den langen Desktop-Listen; Audit-Log + JSON-Details per `
` einklappbar. +- **Accessibility:** `[x-cloak]` gegen Alpine-Flackern, aktiver Nav-Eintrag + mit `aria-current`, Ungelesen-Badge am Nav-Eintrag „Benachrichtigungen", + einheitliche Fokus-Ringe (`.focus-ring` + `:focus-visible`-Fallback), + Fehlerboxen mit `role="alert"`, Pflichtfelder mit `aria-required`. +- **Login:** gruppierte Karte mit „Passwort anzeigen"-Toggle (Alpine). + ## Projekt-Fortschritt > Diese Tabelle ist der Live-Status. Sie wird bei jedem Push aktualisiert. @@ -703,6 +741,7 @@ Getestet gegen 375 px (Smartphone), 768 px (Tablet) und Desktop. | 9 | Plugin `export` (CSV + PDF via WeasyPrint) | ✅ fertig | | 10 | Integrationstests über alle Plugins | ✅ 316 Tests grün | | 11 | Deployment auf swen.henry.insight-it.de (Compose + Traefik, Live-Check) | ✅ live | +| 12 | UI/UX-Verbesserungen (Dashboard-Karten, SVG-Icons, Status-Farben, Pagination, A11y) | ✅ 323 Tests grün | Legende: ✅ fertig · 🔄 in Arbeit · ⏳ offen · ⚠️ fertig mit offenen Punkten