docs(05-01): complete dashboard grid + clock widget plan
This commit is contained in:
@@ -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 |
|
||||
|
||||
@@ -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
@@ -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.
|
||||
Reference in New Issue
Block a user