mitai-jinkendo/.claude/docs/jinkendo-foundation/design-principles/DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md
Lars 532e17c4cd
All checks were successful
Deploy Development / deploy (push) Successful in 1m5s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 24s
feat: add Jinkendo Foundation design principles documentation
- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family.
- Updated README files to include references to the new design principles documentation.
- Enhanced the overall documentation structure to improve navigation and accessibility of design resources.
- Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
2026-07-22 11:11:07 +02:00

17 KiB
Raw Blame History

Dashboard Widgets Designprinzipien (Extraktion)

Status: Analyse / Arbeitspapier
Stand: 2026-07-04
Geltungsbereich: Konfigurierbare Übersicht (Widget-Katalog, Layout, Entitlements, Frontend-Registry) — keine Chart-/Metrik-Berechnung

Serie: Designprinzipien für Produktfamilie · Dokument 7 von n
Vorgänger: UNIVERSAL_IMPORT_DESIGN_PRINCIPLES.md

Kernkomponenten:

Bereich Pfade
Katalog (SSoT) backend/widget_catalog.py
Layout-Schema backend/dashboard_layout_schema.py
Config-Validierung backend/dashboard_widget_config.py
Entitlements backend/dashboard_widget_entitlements.py, widget_feature_requirements_db.py
Produkt-Standard backend/system_dashboard_product_default.py
HTTP backend/routers/app_dashboard.py
Frontend-Registry frontend/src/widgetSystem/dashboardWidgetRegistry.jsx
Registrierung frontend/src/widgetSystem/registerDashboardWidgets.js
Layout-Editor frontend/src/pages/DashboardConfigurePage.jsx
Fehler-Isolation frontend/src/widgetSystem/WidgetErrorBoundary.jsx
Leitfaden DASHBOARD_WIDGETS_AGENT_GUIDE.md
Registry-Meta REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md

Modul

Dashboard Widgets

Erweiterbares System für konfigurierbare Startübersicht: Backend-Katalog definiert erlaubte Widget-IDs; Nutzer speichern Reihenfolge, Ein/Aus und optionale config pro Profil; Frontend rendert über eine lokale Komponenten-Registry.


Fachliche Verantwortung

Das Modul übernimmt:

  1. Widget-Katalog — IDs, Titel, Beschreibung, optionale Feature-Anforderung (requires_feature).
  2. Layout-Persistenzprofiles.dashboard_layout (JSON v1: { version, widgets[] }).
  3. Validierung — Erlaubte IDs, keine Duplikate, max. 32 Widgets, mindestens eines aktiv.
  4. Pro-Widget-Config — Whitelist pro Widget-ID; Normalisierung beim Speichern.
  5. Standard-Layouts — Code-Fallback (DEFAULT_PRODUCT_DASHBOARD_WIDGET_IDS), Admin-Override (system_config), Lab-Template (DEFAULT_LAB_WIDGET_IDS).
  6. Entitlementsallowed im Katalog; Layout bereinigt bei fehlender Berechtigung.
  7. Frontend-Rendering — Registry mappt Katalog-ID → React-Komponente + Props aus layoutEntry.config.
  8. Nutzer-Konfigurator — „Übersicht anpassen“ (Sortieren, Toggle, Config-Editoren).

Es übernimmt nicht:

Datenfluss (Happy Path)

WIDGET_CATALOG (Backend)
  → GET /api/app/widgets/catalog (+ allowed via check_feature_access)
  → GET /api/app/dashboard-layout
      → coalesce_effective_layout (Profil oder Standard)
      → merge_missing_catalog_widgets (neue IDs anhängen)
      → apply_entitlements_to_layout_dict
  → Frontend: ensureDashboardWidgetsRegistered()
  → WidgetRenderer: enabled widgets → mapProps(layoutEntry.config) → Component
  → PUT /api/app/dashboard-layout (Pydantic + Entitlements + speichern)

Layout-Eintrag (Struktur)

Feld Bedeutung
id Muss in WIDGET_CATALOG existieren
enabled Sichtbar auf der Übersicht
config Optional; nur für whitelisted Widgets mit Inhalt erlaubt

Administrierte vs. code-definierte Konfiguration

Konfiguration Speicherort Wer pflegt?
Widget-IDs, Metadaten, Default-Aktivierung widget_catalog.py Entwickler
Produkt-Standard-Layout (live) system_config.dashboard_product_default Admin
Produkt-Standard (Fallback) DEFAULT_PRODUCT_DASHBOARD_WIDGET_IDS Entwickler
Lab-/Editor-Standard DEFAULT_LAB_WIDGET_IDS Entwickler
Nutzer-Layout profiles.dashboard_layout Nutzer
Feature-Gate (Katalog) requires_feature pro Eintrag Entwickler
Feature-Gate (Override) widget_feature_requirements + Marker Admin
Config-Schema pro Widget dashboard_widget_config.py Entwickler
React-Komponente registerDashboardWidgets.js Entwickler

Designprinzipien

1. Backend-Katalog als Single Source of Truth für IDs

Prinzip WIDGET_CATALOG ist die einzige autoritative Liste erlaubter Widget-IDs; ALLOWED_WIDGET_IDS wird daraus abgeleitet — nicht manuell duplizieren.
Begründung Layout-Validator, API und Default-Layouts bleiben synchron; unbekannte IDs werden beim PUT abgewiesen.
Quelle widget_catalog.py; Agent-Guide §4
Tragfähigkeit hoch
Einschränkung Frontend-Registry ist zweite manuelle Bindung (kein Build-Time-Gate).

2. Dual Registry: Backend-Kanon + Frontend-Komponentenbindung

Prinzip Jede Katalog-ID braucht einen Eintrag in registerDashboardWidget({ id, Component, mapProps }); idempotent via ensureDashboardWidgetsRegistered().
Begründung React-Komponenten können nicht im Python-Katalog leben; explizite Zuordnung hält Bundle tree-shakeable.
Quelle registerDashboardWidgets.js, dashboardWidgetRegistry.jsx
Tragfähigkeit hoch
Einschränkung Fehlende Registrierung → Laufzeit „Unbekanntes Widget“, kein CI-Fail.

3. Layout als versioniertes Profil-JSON

Prinzip Nutzer-Layout in profiles.dashboard_layout; Schema version: 1, Liste { id, enabled, config? }.
Begründung Pro Profil anpassbar; Reset auf NULL → System-Standard.
Quelle DashboardLayoutPayload, app_dashboard.py
Tragfähigkeit hoch
Einschränkung Nur v1; Schema-Evolution braucht Migrationspfad.

4. Validierung an der API-Grenze (Pydantic)

Prinzip Jeder GET/PUT-Pfad normalisiert über DashboardLayoutPayload: Duplikat-IDs, unbekannte IDs, leeres Layout (kein enabled) → Fehler.
Begründung Keine korrupten Layouts in der DB; Frontend kann auf gültige Struktur vertrauen.
Quelle dashboard_layout_schema.py
Tragfähigkeit hoch
Einschränkung Ungültiges gespeichertes Layout → Fallback auf Standard (coalesce_effective_layout).

5. Config nur für explizit whitelisted Widgets

Prinzip WIDGETS_ALLOWING_CONFIG: Widgets ohne Eintrag dürfen nur leere config haben; sonst Validierungsfehler.
Begründung Verhindert unkontrollierte JSON-Blobs und stille Ignorierung unbekannter Keys.
Quelle dashboard_widget_config.py
Tragfähigkeit hoch
Einschränkung Pro Widget heterogene Schemas (chart_days vs. KPI-Tiles vs. show_*-Booleans).

6. Strikte Config-Keys (Whitelist, Normalisierung)

Prinzip Unbekannte Keys in config werden abgelehnt; bekannte Keys typgeprüft und normalisiert (z. B. chart_days 790, KPI max. 9 Kacheln).
Begründung Vorhersagbares Verhalten; Editor und Backend stimmen überein.
Quelle _validate_chart_days_only, _validate_kpi_board_config, History-Viz-Defaults
Tragfähigkeit hoch
Einschränkung Frontend-Normalizer (bodyChartDays.js, *VizConfig.js) teils parallel — Abweichungsrisiko.

7. Config-Größenlimit

Prinzip MAX_WIDGET_CONFIG_JSON_BYTES (3072) — keine großen Blobs in Layout-JSON.
Begründung DB-Spalte und API-Payload bleiben schlank; Config = Präferenzen, nicht Datenspeicher.
Quelle dashboard_widget_config.py
Tragfähigkeit hoch
Einschränkung

8. Katalog-Erweiterung ohne Layout-Reset

Prinzip merge_missing_catalog_widgets hängt neue Katalog-IDs ans bestehende Layout an (enabled: false).
Begründung Nutzer müssen nach Deploy nicht resetten; „Übersicht anpassen“ zeigt neue Optionen.
Quelle dashboard_layout_schema.py; Agent-Guide
Tragfähigkeit hoch
Einschränkung Reihenfolge neuer Widgets immer am Ende.

9. Mehrere Standard-Layouts (Produkt vs. Lab vs. Admin)

Prinzip Produkt: get_product_default_base_dict (DB-Override oder DEFAULT_PRODUCT_DASHBOARD_WIDGET_IDS). Lab: lab_default_layout_dict für Editor/Reset. Nutzer: eigenes JSON oder NULL.
Begründung Onboarding-Default getrennt von Entwickler-/Lab-Template; Admin kann Produkt-Standard ohne Deploy ändern.
Quelle system_dashboard_product_default.py, widget_catalog.py
Tragfähigkeit hoch
Einschränkung Feldname lab_default_layout historisch irreführend (Servertemplate, nicht nur Lab).

10. Entitlements zentral, Widgets konsumieren nur allowed

Prinzip Sichtbarkeit über check_feature_access in widget_id_allowed; Katalog liefert allowed pro Zeile. Widgets/React duplizieren keine Tier-Logik.
Begründung Eine Wahrheit für „darf angezeigt werden“; spätere Feature-Cluster ohne Widget-Refactor.
Quelle dashboard_widget_entitlements.py; Agent-Guide §0
Tragfähigkeit hoch
Einschränkung Inhalts-Endpoints (Charts, KI) brauchen eigenes Feature-Gate (Defense in Depth).

11. Layout-Persistenz bereinigt nicht erlaubte Widgets

Prinzip apply_entitlements_to_layout_dict: bei fehlender Berechtigung enabled: false; mindestens welcome bleibt aktiv. GET und PUT wenden an.
Begründung Keine „gespeichert aber nie sichtbar“-Zombies; Downgrade/Tier-Wechsel degradieren gracefully.
Quelle dashboard_widget_entitlements.py, app_dashboard.py
Tragfähigkeit hoch
Einschränkung Policy ist deaktivieren, nicht entfernen — IDs bleiben im JSON.

12. DB-Override für Widget-Feature-Anforderungen

Prinzip Katalog-requires_feature ist Default; Admin kann per dashboard_widget_requirement_custom + widget_feature_requirements überschreiben (AND-Semantik).
Begründung Runtime-Anpassung ohne Code-Deploy; Marker-Zeile trennt Custom von Fallback.
Quelle widget_feature_requirements_db.py, Migration 041
Tragfähigkeit mittelhoch
Einschränkung Zwei Quellen (Code + DB) — Dokumentation und Admin-UI nötig.

13. mapProps: Layout-Config → Komponenten-Props

Prinzip Registry-Eintrag mappt ctx.layoutEntry.config auf typisierte Props (chartDays, kpiConfig, bodyHistoryVizConfig, …).
Begründung Widget-Komponenten bleiben layout-agnostisch; Normalisierung an einer Stelle pro ID.
Quelle registerDashboardWidgets.js
Tragfähigkeit hoch
Einschränkung Teilweise Normalisierung in Widget statt in mapProps (inkonsistent, aber dokumentiert).

14. Refresh-Koordination über Context

Prinzip refreshTick + requestRefresh() im Render-Context; Widgets laden Daten bei Tick-Änderung neu; Aktionen (z. B. Schnelleingabe) rufen requestRefresh.
Begründung Kein globales State-Monster; gezielte Invalidierung nach Capture.
Quelle dashboardWidgetRegistry.jsx, Widget-Implementierungen
Tragfähigkeit hoch
Einschränkung Kein feingranulares Cache pro Widget.

15. Fehler-Isolation pro Widget

Prinzip WidgetErrorBoundary um jede Instanz — Render-Fehler crashen nicht die ganze Übersicht.
Begründung Robuste PWA; ein defektes Chart blockiert nicht Gewicht-Eingabe.
Quelle WidgetErrorBoundary.jsx
Tragfähigkeit hoch
Einschränkung Kein automatisches Retry/Reporting.

16. Konfigurator filtert nach allowed

Prinzip DashboardConfigurePage blendet Widgets mit allowed === false aus der bearbeitbaren Liste aus.
Begründung Nutzer sehen keine Optionen, die sie nicht nutzen dürfen (Agent-Guide A2).
Quelle DashboardConfigurePage.jsx
Tragfähigkeit hoch
Einschränkung Bereits gespeicherte disabled Einträge können im JSON verbleiben.

17. Widgets konsumieren Data Layer, duplizieren keine Logik

Prinzip Chart-/KPI-Widgets rufen Chart-Endpoints bzw. API-Fassaden auf; Berechnungen leben in data_layer/, nicht in Widget-JS.
Begründung Gleiche Zahlen wie Verlauf, KI-Platzhalter und Export.
Quelle Layer-2b *_history_viz-Widgets; DATA_LAYER_DESIGN_PRINCIPLES.md
Tragfähigkeit hoch
Einschränkung Legacy-Widgets unter dashboard-widgets-legacy/ teils ältere Fetch-Pfade.

18. Dedizierte Config-Editoren für komplexe Widgets

Prinzip Einfache chart_days: Set CHART_DAYS_WIDGET_IDS im Layout-Editor; komplexe Config: eigene Editor-Komponenten (KpiBoardConfigEditor, *VizConfigEditor).
Begründung UX skaliert mit Config-Komplexität; Backend-Schema und Editor bleiben parallel pflegbar.
Quelle widgetSystem/*ConfigEditor.jsx, Agent-Guide §3.4
Tragfähigkeit hoch
Einschränkung Jedes neue komplexe Widget = Editor + Validator + Tests.

Nicht übernehmen

  1. Tier-Logik in React-Widgets — nur allowed aus API; keine hardcodierten Plan-Namen.

  2. ALLOWED_WIDGET_IDS manuell pflegen — immer aus Katalog ableiten.

  3. Config ohne Backend-Whitelist — stille Ignorierung unbekannter Keys in Widgets.

  4. Nur UI-Gating ohne API-Absicherung — Chart-/KI-/Export-Endpoints weiterhin check_feature_access (403).

  5. Frontend-Registry vergessen — Katalog-Eintrag ohne registerDashboardWidget → Laufzeitfehler statt Build-Fail.

  6. Große Daten in config — Layout ist Präferenzspeicher, kein Blob-Store (>3072 Bytes).

  7. Doppelte Widget-IDs im Layout — Validator verbietet; Editor muss dasselbe erzwingen.

  8. Neue Katalog-IDs ohne merge_missing_catalog_widgets-Pfad — Nutzer-Layouts veralten unsichtbar.

  9. Kompletter Katalog nur in DB — schwer testbar; Code-Katalog + optionale Feature-Overrides ist das Muster.

  10. Evidence-Pflicht à la Placeholder-Registry — 22 Metadatenfelder pro Widget wären Overkill; Tiefe an Risiko anpassen (REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md).

  11. Ein Default für alles — Produkt-Onboarding, Lab-Template und Admin-Override haben unterschiedliche Zwecke; nicht vermischen.

  12. Fehlender Cross-Check Backend ↔ Frontend IDs — empfohener Test/Gate fehlt im Ist-Stand; nicht als „optional“ ignorieren.

  13. Berechnungslogik im Widget — KPIs/Scores gehören in Data Layer, nicht in useEffect-Mathe.

  14. Entitlements beim Speichern ablehnen statt deaktivieren — Mitai wählt deaktivieren; Policy bewusst festlegen und dokumentieren.


Modul-Inventar (Ist-Stand)

backend/
├── widget_catalog.py                 # WIDGET_CATALOG, DEFAULT_*_IDS
├── dashboard_layout_schema.py        # Pydantic, merge_missing, defaults
├── dashboard_widget_config.py        # WIDGETS_ALLOWING_CONFIG, Validatoren
├── dashboard_widget_entitlements.py  # allowed, layout cleanup
├── widget_feature_requirements_db.py # Admin-Override
├── system_dashboard_product_default.py
└── routers/app_dashboard.py

frontend/src/
├── widgetSystem/
│   ├── dashboardWidgetRegistry.jsx
│   ├── registerDashboardWidgets.js
│   ├── layoutEditor.js
│   ├── bodyChartDays.js, *VizConfig.js
│   └── *ConfigEditor.jsx
├── components/dashboard-widgets/       # Produkt-Widgets
├── components/dashboard-widgets-legacy/  # ältere Kern-Widgets
└── pages/DashboardConfigurePage.jsx

DB:
├── profiles.dashboard_layout
├── system_config.dashboard_product_default
├── dashboard_widget_requirement_custom
└── widget_feature_requirements

Katalog-Umfang: ~24 Widget-IDs (Stand widget_catalog.py); ~13 mit konfigurierbarer config.


Verwandte Dokumentation


Geplante Folgedokumente (Serie)

# Modul Status
16
7 Dashboard Widgets dieses Dokument
8 Navigation / IA
9 Migration & Deploy