Files
HiveGrid-Wireframes/hivegrid-cloud/docs/boilerplate-mapping/M20-dashboard.md
T

15 KiB
Raw Blame History

Boilerplate-Abgleich — M20 Dashboard / Reporting

Feld Wert
Modul-ID M20
Name Dashboard / Reporting (Geschäftsführer-Dashboard)
Milestones M147 (Layout + Widget-Engine), M148 (7 Rollen-Standard-Layouts), M149 (Drill-Down + Custom-Widget-Konfig), M150 (Export + Report-Versand)
Pflichtenheft-Block Block 6 · Modul 20 (_bmad-output/pflichtenheft/blocks/block6.md §§20.1–20.10)
Detail-Spec _bmad-output/specs/M20-dashboard.md
Reuse-Level medium

Kurz-Verdict

Die Boilerplate liefert ein solides Fundament für ein fixes Stat-Dashboard, aber keine konfigurierbare Widget-/Layout-Engine, wie M20 sie verlangt. Konkret vorhanden und stark nutzbar:

  • Ein funktionierendes Tenant-Dashboard-Route-Pattern mit Permission-Gate, Period-Filter, Server-Timing-Metrics und i18n.
  • Ein Dashboard-Modul-Registry-Pattern (dashboard-registry) mit Feature-Flag-/Plan-Gating — ideale Vorlage für den permissions-aware Widget-Katalog (Block C/F).
  • Ein Stat-/Drill-Down-Pattern (Stat-DTO mit path/entity.slug, DashboardStats-Komponente mit <Link>) — direkte Vorlage für die Kern-Anforderung Drill-Down (§20.4).
  • Eine vollständige Export-Infrastruktur (packages/exports: PDF via @react-pdf/renderer, CSV, XLSX, S3-Sinks) für M150.
  • Ein Realtime-/SSE-Fundament (packages/realtime) mit Reconnect/Backoff für Live-Updates (§20.7).
  • Recharts + Chart-UI-Primitive für Visualisierungen.

Was komplett fehlt: das Datenmodell (Dashboard, DashboardLayout, WidgetInstance), die Drag-&-Drop-Grid-Engine (kein react-grid-layout; nur @dnd-kit als Baustein vorhanden), die Per-Widget-Caching-/Aggregat-Schicht, der konkrete Widget-Katalog (Sales/Projekt/HR/… aus den Modulen) und die HiveGrid-Layer-Split-Packages (ui-hivegrid, gefüllte view-models, Subframe-Adapter).

Wichtiger Hinweis zur „packages/metrics + Widget-Engine"-Annahme aus dem Auftrag: packages/metrics ist Prometheus/prom-client (Ops-Observability: Histogramme, AI-Cost-Counter, Metrics-Token-Auth) — NICHT eine Business-KPI- oder Widget-Engine. Das Widget-Modell in core.prisma ist ein generisches Legacy-UI-Widget (name/appearance/metadata als Strings) und deckt das M20-Widget-Modell nicht ab.


Übernehmbar aus Boilerplate

Pfade beziehen sich auf /Users/raffaelsheikh/Documents/GitHub/boilerplate. Der Boilerplate-Code lebt in der Legacy-ToolCTRL-Struktur (apps/web/app/..., ~/utils/...), nicht im HiveGrid-Ziel-Layer-Split. Übernahme bedeutet daher fast überall „als-vorlage" + Umbau in app/routes + packages/view-models + packages/ui-hivegrid.

Boilerplate-Pfad Was Wie nutzbar
apps/web/app/routes/app.$tenant/dashboard.tsx Tenant-Dashboard-Route: Permission-Gate (app.dashboard.view), Period-Filter (PeriodHelper), Server-Timing-Metrics, i18n-Title, Empty/Permission-Handling, Modul-Gating-Verdrahtung als-vorlage (Loader-/VM-Struktur übernehmen, in HiveGrid-Layer-Split überführen)
apps/web/app/services/dashboard-registry/registry.server.ts Dashboard-Modul-Registry als Code-Konstante (id, titleKey, descriptionKey, featureFlagKey, planFeatureKey), Object.freeze-Pattern als-vorlage — direkte Blaupause für WidgetCatalog (Code-Registry, Block A/C)
apps/web/app/services/dashboard-registry/gating.server.ts Gating-Engine: pro Modul Feature-Flag + Plan-/Entitlement-Check → allowed + Diagnostic + Redirect als-vorlage — Vorlage für permissions-aware Widget-Sichtbarkeit (§20.8 / Block F); Permission-Check ersetzt/ergänzt Plan-Check
apps/web/app/application/dtos/stats/Stat.ts (+ StatChange.ts) Stat-DTO mit name, stat, previousStat, change, changeType, path, entity.slug anpassen — path/entity.slug sind die Drill-Down-Hooks (§20.4); ins VM überführen
apps/web/app/components/ui/stats/DashboardStats.tsx Stat-Grid-Komponente, rendert klickbare Stat-Kacheln via <Link to={item.path}> als-vorlage — Drill-Down-Verlinkung; nach packages/ui-hivegrid portieren (VM-only, kein Loader-Zugriff)
apps/web/app/utils/services/appDashboardService.ts Aggregat-Service: zählt Entity-Rows seit gte, berechnet change%/changeType, baut Stat[] als-vorlage — Muster für serverseitige Aggregat-Berechnung (§20.7.1); pro HiveGrid-Widget eigener Builder
apps/web/app/utils/app/DashboardUtils.ts (getStatChangePercentage, getStatChangeType) Reine Change-Berechnungs-Helfer 1:1 (pure functions, in VM-Builder nutzbar)
packages/exports/src/pdf/ + packages/exports/src/index.ts PDF-Export (@react-pdf/renderer), Streaming, S3-Multipart-Sink; audit-pdf.ts als konkretes PDF-Beispiel anpassen — Dashboard-PDF-Snapshot (M150)
packages/exports/src/csv/ + packages/exports/src/xlsx/ CSV-/XLSX-Export mit Streaming + Spreadsheet-Safety (spreadsheet-safety.ts), format-caps.ts, limits.ts anpassen — Widget-CSV-Export (M150); ersetzt json2csv (nicht in BP)
packages/realtime/src/server.ts (serializeRealtimeEvent, SSE) SSE-Event-Serialisierung (id/event/data + retry), Sanitizing anpassen — Live-Update-Push-Kanal (§20.7.3); neue Event-Typen für Dashboard nötig
packages/realtime/src/client.ts SSE-Subscriber mit Reconnect/Backoff, Status-Diagnostics, EventSource-Abstraktion anpassen — Client-Side Live-Update-Empfang inkl. „Live-Updates pausieren"-Opt-Out (§20.7.4)
packages/realtime/src/events.ts Event-Schema-Registry (REALTIME_EVENT_NAMES) + Validierung anpassen — derzeit nur Notification-Events; Dashboard-Events (deal.won, lead.received, defect.accepted) ergänzen
apps/web/app/components/ui/chart.tsx shadcn-Chart-Wrapper um Recharts (ChartConfig, Theming, Locale-Formatters) 1:1 / anpassen — Visualisierungs-Primitive für Trend-/Conversion-Widgets (§20.1)
apps/web/app/components/analytics/AnalyticsOverview.tsx (+ AnalyticsOverviewChart.tsx) Echtes Chart-Dashboard-Pattern: MetricCards + lazy-geladener Chart, klickbare Metriken via <Link> als-vorlage — Muster für klickbare KPI-Karten + Lazy-Loading (§20.7.5)
packages/view-models/src/index.ts VM-Foundation: VMState, ActionCallbacks, SidebarRegistryItem, RegistryGate (permission/flag), I18nLabel 1:1 — Pflicht-Basis für alle M20-VMs (AGENTS.md M013/M014)
packages/feature-flags/ Feature-Flag-Querschnitt (M006) für Dashboard- und Widget-Toggles 1:1
packages/entitlements/ Plan-/Entitlement-Checks (im gating.server.ts bereits verdrahtet) 1:1 (für general.tenant_health-Widget + Gating)
packages/db/src/client.server.ts (getReadDbClient/getExtendedDbClient) Read-/Tenant-scoped Prisma-Clients, Outbox/Audit-Middleware 1:1 — read-heavy Dashboard-Queries
packages/db/src/kpi.server.ts Admin-Plattform-KPIs (Tenant-Counts, Active-User via log.groupBy) als-vorlage (nur Plattform-Admin-Scope; Muster für Count-/GroupBy-Aggregate, nicht der Tenant-Widget-Katalog)
infra/grafana/business-kpi.json Vorgefertigtes Grafana-Business-KPI-Dashboard Referenz — Ops-Sicht, kein In-App-Widget; als Inspiration für KPI-Auswahl

Vorhandene Daten-Modelle (Prisma)

Verifiziert in /Users/raffaelsheikh/Documents/GitHub/boilerplate/prisma/schema/.

Modell Pfad Relevanz für M20
Widget prisma/schema/core.prisma:267 Deckt M20 NICHT ab. Generisches Legacy-UI-Widget: id, tenantId?, name, appearance (String), metadata (String), @@unique([tenantId, name]). Keine Layout-/Instanz-/Config-/Position-Struktur. Reader: packages/db/src/widgets.server.ts (findLegacyWidgetById). Allenfalls als Namens-Squatter zu beachten (Kollision mit neuem WidgetInstance).
MetricLog prisma/schema/core.prisma:180 Request-Performance-Log (route/duration/userId/tenantId) — Ops-Metrik, nicht Business-Aggregat.
AnalyticsSettings, AnalyticsUniqueVisitor, AnalyticsPageView, AnalyticsEvent prisma/schema/analytics.prisma First-Party-Web-Analytics (Visitor/PageView/Event, UTM, Geo, Device), portal-zentriert. Quelle für ein evtl. „Web-Traffic"-Widget, aber kein CRM-/Sales-/HR-Aggregat.
FeatureFlag (+ Filter) prisma/schema/featureFlags.prisma Für Dashboard-/Widget-Feature-Gating (M006).
CollabDoc prisma/schema/collabDocs.prisma Yjs-Realtime-Docs — nicht Dashboard-relevant (nur falls geteilte Layout-Editing-Sessions gewünscht; Phase-1 nicht gefordert).

Fazit Daten-Layer: Die vier M20-Kernmodelle (Dashboard, DashboardLayout, WidgetInstance; WidgetCatalog als Code-Registry) existieren nicht und müssen neu gebaut werden. Tenant-/User-Relationen und das Tenant-Scoping-Muster sind vorhanden und wiederverwendbar.


Lücken / komplett neu zu bauen

  1. Datenmodell M20 — neue Prisma-Modelle Dashboard, DashboardLayout, WidgetInstance (Spec Block A). Forward-Only-Migration mit Inverse-SQL (DoD). Achtung: Widget ist als Modellname belegt → WidgetInstance + WidgetCatalogKey verwenden.
  2. WidgetCatalog (Code-Registry) — die konkrete Liste aus Block C (sales.*, projects.*, tasks.*, activity.*, comms.*, hr.*, ai.*, general.*) mit Default-Config-Schema, Render-Komponente, Datenquelle + Quellen-Modul-Permission. Das dashboard-registry-Pattern ist die Vorlage, der Inhalt ist komplett neu und modul-abhängig (M3/M4/M26/M1/M9/M12/M14/M18).
  3. Drag-&-Drop-Grid-Engine — react-grid-layout ist NICHT in den Deps (entgegen PLAN-Hinweis); nur @dnd-kit/core + @dnd-kit/sortable vorhanden. Entweder Grid-Library hinzufügen oder Grid auf @dnd-kit selbst bauen (Resize ist mit dnd-kit nicht out-of-the-box). Layout-Persistenz (layout_data JSON) neu.
  4. Per-Widget-Aggregat-/Caching-Schicht — Cache-Key tenant_id + widget_key + config_hash + user_id, TTL 60 s, Invalidierung (§20.7). Kein generischer Widget-Cache vorhanden; appDashboardService zählt direkt ohne Cache. Pre-Calc-Aggregat-Tables + Cron (§20.7.2) neu — apps/worker + BullMQ als Fundament vorhanden.
  5. 7 Rollen-Default-Layouts als deklaratives Branchen-Template (M148, §20.5, LP-3/AV#3) — Seed-Daten beim Tenant-Anlegen. Seed-Infra (packages/db/src/seed.server.ts, entitlements-seed, permissions-seed) vorhanden, die Layout-Templates selbst neu.
  6. Widget-Datenquellen — jeder Widget-Builder hängt an einem anderen Modul (Sales-Pipeline-KPIs, Forecast, Vertriebler-Performance, Projekt-Auslastung/Plantafel, offene Mängel, HR „wer ist heute da", ungelesene Mails, Anrufe heute, KI-Vorschläge). Diese Quell-Module sind im Boilerplate noch nicht als HiveGrid-Module gebaut → harte Abhängigkeit zu M01/M03/M04/M09/M12/M14/M18/M26.
  7. Drill-Down-Filter-Ableitung (§20.4, Kern-Anforderung) — aus Widget-Config den vorgefilterten Listen-Link bauen, permissions-aware. Stat.path/entity.slug ist der Hook, die Filter-Serialisierung je Widget neu.
  8. Dashboard-Permissions (dashboard.read/customize/create/share/admin + Bundles, Block F) — neue Permission-Keys. Boilerplate hat nur app.dashboard.view / admin.dashboard.view (packages/db/src/permissions-seed.server.ts). Permission-Definition gehört nach packages/entitlements/src/permissions.ts (Integration-Contract §10).
  9. Dashboard-Live-Events — packages/realtime kennt nur Notification-Events; Dashboard-Events (deal.won, lead.received, defect.accepted) + Server-Push-Verdrahtung + „Live-Updates pausieren"-Opt-Out neu.
  10. HiveGrid-Layer-Split — packages/ui-hivegrid, gefüllte packages/view-models/src/dashboard/*.vm.ts, Subframe-Adapter existieren noch nicht. Der Boilerplate-Dashboard-Code liegt monolithisch in apps/web mit useLoaderData/~/db-Nähe und verletzt die HiveGrid-Anti-Patterns → bei Übernahme zwingend umbauen.
  11. Sidebar-/Shell-Wiring — packages/ui-hivegrid/src/app-shell/sidebar.config.ts (Integration-Contract §2) existiert nicht; Boilerplate nutzt eine andere Shell. Sidebar-Eintrag „Dashboard" (Gruppe ARBEITEN) neu zu registrieren. SidebarRegistryItem-Typ aus packages/view-models ist die Basis.
  12. Mobile-First Monteur-Dashboard (LP-2, §20.5.7) — Mobile-Tab-Bar-Eintrag (M169) + reduziertes Layout neu.
  13. Klartext-States — Empty/Loading/Error pro Widget aus M002-Catalog + M003-i18n. Boilerplate-Dashboard hat i18n-Keys (app.dashboard.*), die konkreten Widget-Texte (§20.10) neu.
  14. Report-Versand-Trigger (M150) — manuelle Generierung via vorhandene exports-Infra; geplante Email-Reports sind explizit Phase 2 (§20.9.2, Out-of-Scope).

Empfohlenes Vorgehen

Phase 0 — Layer-Fundament & Übernahme der Patterns (vor M147):

  1. packages/view-models-Foundation (VMState, ActionCallbacks, SidebarRegistryItem) ist bereits da → 1:1 nutzen, dashboard-VM-Ordner anlegen.
  2. Stat-DTO + getStatChangePercentage/getStatChangeType (pure) nach packages/view-models/app/domain portieren (1:1).
  3. DashboardStats- und AnalyticsOverview-Komponente als Vorlage nach packages/ui-hivegrid übernehmen (VM-only, Drill-Down via <Link> beibehalten).
  4. dashboard-registry-Pattern (registry.server.ts + gating.server.ts) als Blaupause kopieren → daraus den WidgetCatalog + permissions-aware Gating formen (Permission-Check statt Plan-Check).

M147 — Layout + Widget-Engine: 5. Neue Prisma-Modelle Dashboard/DashboardLayout/WidgetInstance + Migration. Tenant-Scoping-Muster aus packages/db nutzen. 6. Grid-Engine: Entscheidung react-grid-layout hinzufügen oder auf vorhandenem @dnd-kit bauen (Resize-Aufwand einplanen). 7. Per-Widget-Aggregat-Builder nach Muster appDashboardService (serverseitig, im Loader → VM). Caching-Schicht (TTL 60 s, Cache-Key per Spec) neu; getReadDbClient() für read-heavy Queries. 8. Recharts/chart.tsx-Primitive für Trend-/Conversion-Widgets 1:1 übernehmen. 9. Realtime: packages/realtime Server/Client übernehmen, Dashboard-Event-Typen ergänzen, Lazy-Loading (lazy-Chart wie AnalyticsOverviewChart).

M148 — 7 Rollen-Default-Layouts: 10. Deklarative Layout-Templates als Seed-Daten (Seed-Infra aus packages/db/src/seed.server.ts vorhanden); permissions-aware Widget-Filter aus dem Gating-Pattern.

M149 — Drill-Down + Custom-Konfig: 11. Drill-Down-Filter-Ableitung je Widget (Stat.path/entity.slug als Hook), permissions-aware. Widget-Picker mit Catalog-Gating (ausgegraut bei fehlender Permission).

M150 — Export: 12. packages/exports (PDF @react-pdf/renderer + CSV/XLSX) direkt anbinden: Dashboard-PDF-Snapshot + Widget-CSV. Geplante Email-Reports bleiben Phase 2.

Querschnitt durchgehend: Permission-Keys in packages/entitlements, Feature-Flags (M006), i18n (M003), Audit (M001 auto) für Layout-Änderungen an shared Dashboards (AV#6), Sidebar-Eintrag (§2), Smoke-Test + Hot-Swap-Drill + Visual-Regression (DoD D).