docs(05-01): complete dashboard grid + clock widget plan

This commit is contained in:
2026-06-24 11:27:59 +02:00
parent 8a9c1ae6a9
commit afc555b18d
4 changed files with 159 additions and 23 deletions
+8 -8
View File
@@ -39,13 +39,13 @@ Requirements for initial release. Each maps to roadmap phases.
### Dashboard
- [ ] **DASH-01**: Konfigurierbares Dashboard als Startseite mit Drag & Drop Grid
- [ ] **DASH-02**: Widgets koennen frei positioniert und in der Groesse geaendert werden
- [ ] **DASH-03**: Uhr-Widget (analog oder digital)
- [x] **DASH-01**: Konfigurierbares Dashboard als Startseite mit Drag & Drop Grid
- [x] **DASH-02**: Widgets koennen frei positioniert und in der Groesse geaendert werden
- [x] **DASH-03**: Uhr-Widget (analog oder digital)
- [ ] **DASH-04**: Suchleiste-Widget (oeffnet Google/Suchmaschine im Browser)
- [ ] **DASH-05**: Kalender-Widget mit Terminvorschau
- [ ] **DASH-06**: Notiz-Widget (Freitext-Kachel)
- [ ] **DASH-07**: Dashboard-Layout wird pro Benutzer gespeichert
- [x] **DASH-07**: Dashboard-Layout wird pro Benutzer gespeichert
### Kalender-Integration
@@ -143,13 +143,13 @@ Which phases cover which requirements. Updated during roadmap creation.
| MRKT-02 | Phase 4 | Pending |
| MRKT-03 | Phase 4 | Pending |
| MRKT-04 | Phase 4 | Pending |
| DASH-01 | Phase 5 | Pending |
| DASH-02 | Phase 5 | Pending |
| DASH-03 | Phase 5 | Pending |
| DASH-01 | Phase 5 | Complete |
| DASH-02 | Phase 5 | Complete |
| DASH-03 | Phase 5 | Complete |
| DASH-04 | Phase 5 | Pending |
| DASH-05 | Phase 5 | Pending |
| DASH-06 | Phase 5 | Pending |
| DASH-07 | Phase 5 | Pending |
| DASH-07 | Phase 5 | Complete |
| CAL-01 | Phase 5 | Pending |
| CAL-02 | Phase 5 | Pending |
| CAL-03 | Phase 5 | Pending |
+2 -2
View File
@@ -165,7 +165,7 @@ Decimal phases appear between their surrounding integers in numeric order.
**Wave 1**
- [ ] 05-01-PLAN.md -- Dashboard foundation: Prisma models, CRUD API, grid, edit-mode, clock widget, settings shell, header link, i18n (DASH-01/02/03/07)
- [x] 05-01-PLAN.md -- Dashboard foundation: Prisma models, CRUD API, grid, edit-mode, clock widget, settings shell, header link, i18n (DASH-01/02/03/07)
**Wave 2** *(blocked on Wave 1 completion)*
@@ -210,5 +210,5 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6
| 2. Authentication & Multi-Tenancy | 2/5 | In Progress| |
| 3. Module System & Domaincheck | 3/4 | In Progress| |
| 4. Marketplace & Portal Navigation | 0/4 | Not started | - |
| 5. Dashboard & Calendar | 0/5 | Planned | - |
| 5. Dashboard & Calendar | 1/5 | In Progress| |
| 6. Desktop Client & CI/CD | 0/TBD | Not started | - |
+15 -13
View File
@@ -2,15 +2,15 @@
gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: completed
stopped_at: context exhaustion at 76% (2026-06-24)
last_updated: "2026-06-24T08:12:35.458Z"
last_activity: 2026-06-23 -- Plan 04-03 completed (sidebar enhancement)
status: executing
stopped_at: Completed 05-01-PLAN.md
last_updated: "2026-06-24T09:27:38.939Z"
last_activity: 2026-06-24 -- Phase 05 execution started
progress:
total_phases: 6
completed_phases: 3
total_plans: 21
completed_plans: 15
completed_plans: 16
percent: 50
---
@@ -21,14 +21,14 @@ progress:
See: .planning/PROJECT.md (updated 2026-06-18)
**Core value:** Eine zentrale Plattform, in der beliebige Workflow-Tools als Module lizenziert, aktiviert und genutzt werden koennen -- ohne zwischen verschiedenen Anwendungen wechseln zu muessen.
**Current focus:** Phase 04 — marketplace-portal-navigation
**Current focus:** Phase 05 — dashboard-calendar
## Current Position
Phase: 04 (marketplace-portal-navigation) — EXECUTING
Plan: 4 of 4
Status: Plan 04-03 complete, ready for 04-04
Last activity: 2026-06-23 -- Plan 04-03 completed (sidebar enhancement)
Phase: 05 (dashboard-calendar) — EXECUTING
Plan: 2 of 5
Status: Ready to execute
Last activity: 2026-06-24 -- Phase 05 execution started
Progress: [██▓░░░░░░░] 25%
@@ -54,6 +54,7 @@ Progress: [██▓░░░░░░░] 25%
*Updated after each plan completion*
| Phase 02-authentication-multi-tenancy P02 | 8min | 3 tasks | 26 files |
| Phase 02-authentication-multi-tenancy P03 | 5min | 2 tasks | 20 files |
| Phase 05-dashboard-calendar P01 | 14min | 4 tasks | 28 files |
## Accumulated Context
@@ -74,6 +75,7 @@ Recent decisions affecting current work:
- [Phase ?]: Route groups (auth)/(portal) for layout separation: auth pages standalone, portal pages wrapped in AppShell
- [Phase ?]: Controller-level tenant isolation for ADMIN role as defense-in-depth alongside RLS
- [Phase ?]: Remember-me controls cookie maxAge (30d session vs browser-session) not separate token type
- [Phase ?]: react-grid-layout v2 uses dragConfig/resizeConfig instead of isDraggable/isResizable
### Pending Todos
@@ -93,6 +95,6 @@ Items acknowledged and carried forward from previous milestone close:
## Session Continuity
Last session: 2026-06-24T08:03:21.832Z
Stopped at: context exhaustion at 76% (2026-06-24)
Resume file: .planning/phases/05-dashboard-calendar/05-CONTEXT.md
Last session: 2026-06-24T09:27:38.933Z
Stopped at: Completed 05-01-PLAN.md
Resume file: None
@@ -0,0 +1,134 @@
---
phase: 05-dashboard-calendar
plan: 01
subsystem: dashboard
tags: [dashboard, widgets, grid, settings, prisma, nestjs, react-grid-layout]
dependency_graph:
requires: []
provides: [DashboardModule, DashboardGrid, ClockWidget, WidgetRegistry, SettingsLayout]
affects: [apps/api/prisma/schema.prisma, apps/api/src/app.module.ts, apps/web/src/app/(portal)/page.tsx, apps/web/src/components/layout/header.tsx]
tech_stack:
added: [react-grid-layout@2.2.3, react-resizable]
patterns: [Zustand store without persist, react-grid-layout v2 Responsive API, widget-registry pattern, dragConfig/resizeConfig v2 API]
key_files:
created:
- apps/api/src/dashboard/dashboard.module.ts
- apps/api/src/dashboard/dashboard.controller.ts
- apps/api/src/dashboard/dashboard.service.ts
- apps/api/src/dashboard/dto/save-layout.dto.ts
- apps/api/src/dashboard/dto/create-widget.dto.ts
- apps/api/src/dashboard/dto/update-widget-config.dto.ts
- apps/web/src/components/dashboard/dashboard-grid.tsx
- apps/web/src/components/dashboard/edit-mode-toggle.tsx
- apps/web/src/components/dashboard/widget-catalog-modal.tsx
- apps/web/src/components/dashboard/widget-registry.tsx
- apps/web/src/components/dashboard/widgets/clock-widget.tsx
- apps/web/src/components/dashboard/widgets/widget-wrapper.tsx
- apps/web/src/lib/dashboard-api.ts
- apps/web/src/lib/stores/dashboard-store.ts
- apps/web/src/app/(portal)/settings/layout.tsx
- apps/web/src/app/(portal)/settings/page.tsx
- apps/web/src/components/settings/settings-sidebar.tsx
- apps/web/src/components/dashboard/dashboard-grid.test.tsx
- apps/web/src/components/dashboard/widgets/clock-widget.test.tsx
modified:
- apps/api/prisma/schema.prisma
- apps/api/src/app.module.ts
- apps/web/package.json
- apps/web/src/app/(portal)/page.tsx
- apps/web/src/components/layout/header.tsx
- apps/web/src/messages/de.json
- apps/web/src/messages/en.json
- apps/web/vitest.config.ts
- apps/web/src/test/setup.ts
decisions:
- "react-grid-layout v2 uses dragConfig/resizeConfig instead of isDraggable/isResizable"
- "react-resizable installed as direct dependency (pnpm strict isolation requires it)"
- "widget-registry.tsx uses wireClockWidget() deferred wiring to avoid circular deps"
- "ResizeObserver polyfill added to test setup for jsdom compatibility"
- "Prisma JSON fields cast via unknown to InputJsonValue for type safety"
metrics:
duration: 14min
completed: 2026-06-24T09:25:00Z
tasks: 4
files_created: 19
files_modified: 9
---
# Phase 05 Plan 01: Dashboard Grid + Clock Widget + Settings Shell Summary
Full vertical stack for dashboard: Prisma models (DashboardLayout, WidgetInstance), NestJS CRUD API with userId ownership verification, react-grid-layout v2 Responsive grid with 4-widget registry, clock widget using Intl.DateTimeFormat, Zustand store without persist (D-05), settings page shell with sub-sidebar, and all phase i18n keys.
## Tasks Completed
| Task | Name | Commit | Key Files |
|------|------|--------|-----------|
| 1 | Dashboard backend | 950eebb | schema.prisma, dashboard.controller.ts, dashboard.service.ts |
| 2 | Dashboard grid + clock widget + store | d5e1c42 | dashboard-grid.tsx, clock-widget.tsx, widget-registry.tsx, dashboard-store.ts |
| 2 (RED) | Failing tests | 792b766 | dashboard-grid.test.tsx, clock-widget.test.tsx |
| 3 | Settings shell + header link + i18n | 8a9c1ae | settings/layout.tsx, settings-sidebar.tsx, de.json, en.json |
| 4 | Prisma schema push | (no code change) | Database tables created |
## Verification Results
- `prisma validate`: PASS
- `tsc --noEmit` (apps/api): PASS
- `tsc --noEmit` (apps/web): PASS
- `vitest run src/components/dashboard`: 5/5 PASS
- `vitest run` (all tests): 31/31 PASS
- JSON parse (de.json, en.json): PASS
- `prisma db push`: "database is already in sync"
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] react-grid-layout v2 API changes**
- **Found during:** Task 2
- **Issue:** react-grid-layout v2 uses `dragConfig`/`resizeConfig` objects instead of `isDraggable`/`isResizable` props. The type `Layouts` is renamed to `ResponsiveLayouts`.
- **Fix:** Rewrote grid component to use v2 API: `dragConfig: { enabled, handle }` and `resizeConfig: { enabled }`.
- **Files modified:** apps/web/src/components/dashboard/dashboard-grid.tsx
**2. [Rule 3 - Blocking] pnpm strict isolation for react-resizable CSS**
- **Found during:** Task 2
- **Issue:** `react-resizable/css/styles.css` import failed in tests because react-resizable is a transitive dep of react-grid-layout, not directly installed. pnpm strict isolation blocks resolution.
- **Fix:** Added `react-resizable` as direct dependency in apps/web/package.json.
- **Files modified:** apps/web/package.json
**3. [Rule 3 - Blocking] ResizeObserver not available in jsdom**
- **Found during:** Task 2
- **Issue:** DashboardGrid uses ResizeObserver for container width measurement, which jsdom doesn't provide.
- **Fix:** Added ResizeObserver polyfill to apps/web/src/test/setup.ts that fires immediately with mock dimensions.
- **Files modified:** apps/web/src/test/setup.ts
**4. [Rule 3 - Blocking] widget-registry.ts JSX in .ts file**
- **Found during:** Task 2
- **Issue:** PlaceholderWidget component uses JSX but file was `.ts` extension.
- **Fix:** Renamed to `widget-registry.tsx`.
- **Files modified:** apps/web/src/components/dashboard/widget-registry.tsx
**5. [Rule 1 - Bug] Prisma JSON type mismatch**
- **Found during:** Task 1
- **Issue:** `Record<string, unknown>` not assignable to Prisma's `InputJsonValue` type.
- **Fix:** Cast JSON fields via `as unknown as Prisma.InputJsonValue`.
- **Files modified:** apps/api/src/dashboard/dashboard.service.ts
## Decisions Made
| Decision | Context | Outcome |
|----------|---------|---------|
| react-grid-layout v2 Responsive API | v2 is a complete TypeScript rewrite with different prop names | Used `dragConfig`/`resizeConfig` objects instead of boolean props |
| react-resizable as direct dep | pnpm strict isolation prevents resolving transitive CSS imports | Added as explicit dependency in apps/web |
| wireClockWidget() pattern | Avoid circular deps between widget-registry and clock-widget | Deferred wiring function called from page.tsx at mount time |
| Prisma db push via docker exec | DB port not exposed to host | Copied schema into API container and ran prisma db push from there |
## Known Stubs
| File | Line | Stub | Reason |
|------|------|------|--------|
| widget-registry.tsx | search/calendar/note entries | PlaceholderWidget component | Implemented in plans 05-02 (search/note) and 05-03 (calendar) |
| settings-sidebar.tsx | /settings/dashboard, /settings/dashboard/calendar links | Links to pages not yet created | Created in plans 05-02 and 05-03 |
## Self-Check: PASSED
All 19 created files verified present. All 4 commit hashes found in git log.