Commit Graph

1116 Commits

Author SHA1 Message Date
schalli 37e09dc66f fix(05): add dev default for CALENDAR_ENCRYPTION_KEY in docker-compose
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:37:48 +02:00
schalli 6965e52bf7 docs(05-04): complete calendar frontend plan 2026-06-24 15:28:24 +02:00
schalli 24de136b9b feat(05-04): calendar settings page with source management and visibility toggle
- calendar-settings-panel.tsx: source list with color dots, type badges, visibility toggle (CAL-02), edit/delete actions, connection test auto-run, delete confirmation dialog
- calendar-source-form.tsx: add/edit form with name/type/URL/credentials/color; Exchange-mode select for exchange type; username/password hidden for ICS; client-side https-only validation (T-05-14)
- settings/dashboard/calendar/page.tsx: route page rendering CalendarSettingsPanel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:26:06 +02:00
schalli f99ff9a498 test(05-04): add failing tests for calendar settings panel
- Three test cases: source list with name/type/visibility, visibility toggle calls updateSource, form validation
- Mocks calendar-api functions following existing test patterns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:24:09 +02:00
schalli c0f2f4ca51 feat(05-04): calendar API client, calendar widget, registry wiring
- calendar-api.ts: fetchSources/addSource/updateSource/deleteSource/testSource/fetchEvents with credentials:'include'
- calendar-widget.tsx: upcoming-events list with source color dots, three empty states (no sources/no events/loading)
- widget-registry.tsx: wireCalendarWidget() replaces placeholder with real CalendarWidget
- page.tsx: wires CalendarWidget into registry on mount
- i18n: added calendar.loading key to de.json and en.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:23:27 +02:00
schalli 2d8699e45c test(05-04): add failing tests for calendar widget
- Three test cases: event rendering with color dots, no-events empty state, no-sources empty state
- Mocks calendar-api and next-intl following existing test patterns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:21:37 +02:00
schalli 694bcff4a4 docs(05-03): complete calendar backend plan
- Create 05-03-SUMMARY.md with full execution documentation
- Update STATE.md: advance to plan 4/5, add decisions, record metrics
- Update ROADMAP.md: mark 05-03 complete, 3/5 plans done
- Update REQUIREMENTS.md: CAL-01/02/03 + DASH-05 backend complete
2026-06-24 15:19:27 +02:00
schalli bb8990ca66 chore(05-03): Prisma schema push + encryption key configuration
- Add CALENDAR_ENCRYPTION_KEY env var to docker-compose api service
- Push CalendarSource table to live PostgreSQL (16 columns verified)
- Regenerate Prisma client with CalendarSource model
- DB reports in sync on second push (no drift)
2026-06-24 15:15:59 +02:00
schalli 0cd8efe157 feat(05-03): event aggregation + caching backend
- Implement aggregateEvents with Promise.allSettled across visible sources
- Dispatch to ICS/CalDAV/Exchange providers by source.type with credential decryption
- In-memory per-user event cache with 5-minute TTL (Pitfall 4)
- Background cache refresh when close to expiry
- Implement testConnection with lastSyncAt/lastSyncError updates
- Default window: now to now+30 days
- Events sorted by start ascending with source color included
2026-06-24 15:14:44 +02:00
schalli 389ac9b692 feat(05-03): calendar providers (CalDAV, ICS, Exchange)
- Implement ICSProvider with fetch + node-ical parsing + RRULE expansion
- Implement CalDAVProvider with tsdav DAVClient + time-range filtering
- Implement ExchangeProvider dispatching on exchangeMode (graph vs ews)
- Graph mode uses @microsoft/microsoft-graph-client /me/calendarView
- EWS mode uses ews-javascript-api FindAppointments
- Exchange gracefully degrades: returns empty array on failure (D-08)
- No provider logs decrypted passwords (T-05-13)
2026-06-24 15:13:34 +02:00
schalli 9ec6313f4d feat(05-03): calendar backend — model, crypto, source CRUD module
- Add CalendarSource Prisma model with encrypted credentials (AES-256-GCM)
- Create CalendarCryptoService with encrypt/decrypt using CALENDAR_ENCRYPTION_KEY
- Create CalendarController with source CRUD endpoints (GET/POST/PATCH/DELETE)
- Create CalendarService with ownership checks and SSRF URL validation
- Add DTOs with https-only URL validation and class-validator decorators
- Register CalendarModule in AppModule
- Install tsdav, node-ical, ews-javascript-api, @microsoft/microsoft-graph-client
- Stub provider files for Task 2 compilation
2026-06-24 15:09:03 +02:00
schalli 7616365cbe docs(05-02): complete search + notes widgets + settings plan 2026-06-24 15:03:55 +02:00
schalli 7e2592b2af feat(05-02): add widget settings panel with search provider form
- Settings > Dashboard page with per-widget-instance config
- Clock config: timezone select (IANA list) + date toggle (D-12/D-13)
- Note config: editable title field (D-17)
- Search config: SearchProviderForm with add/delete and {query} validation (D-15)
- Calendar config: link to calendar-specific settings
- i18n keys for search provider management (en + de)
- Fix useRef initialization for React 19 strict mode (note-widget)
- Fix unknown type narrowing in widget title display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 14:58:42 +02:00
schalli 38dcfdfa6d feat(05-02): add SearchProvider backend with model, CRUD, and defaults
- Prisma model SearchProvider with userId/tenantId scoping
- Three default providers (Google/Bing/DuckDuckGo) as constants, always returned without DB seed
- GET/POST/DELETE search-providers endpoints on DashboardController
- Ownership verification on delete (T-05-07), default providers cannot be deleted
- CreateSearchProviderDto with class-validator: urlTemplate must contain {query} (T-05-08)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:34:45 +02:00
schalli dd0209898b feat(05-02): add search and note widgets with tests
- SearchWidget: provider dropdown, text input, button; opens search in new tab via window.open (D-14/D-15)
- NoteWidget: MDEditor with compact toolbar, debounced autosave (1500ms), AbortController for in-flight cancellation (D-16/D-17/D-18)
- rehype-sanitize enabled for Markdown XSS prevention (T-05-05)
- Widget registry updated with wireSearchWidget/wireNoteWidget (no more placeholders)
- dashboard-api.ts: added fetchSearchProviders, addSearchProvider, removeSearchProvider, signal support on updateWidgetConfig
- 9 new tests passing (search: 5, note: 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:33:01 +02:00
schalli 97c13809f5 test(05-02): add failing tests for search and note widgets
- SearchWidget: provider selection, window.open with encoded query, Enter key trigger
- NoteWidget: debounced autosave, rapid typing collapse, AbortController usage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:30:45 +02:00
schalli afc555b18d docs(05-01): complete dashboard grid + clock widget plan 2026-06-24 11:27:59 +02:00
schalli 8a9c1ae6a9 feat(05-01): settings shell, header link, and i18n keys for dashboard phase
- Create settings/layout.tsx with SettingsSidebar and back-to-dashboard link
- Create settings/page.tsx with redirect to /settings/dashboard
- Create settings-sidebar.tsx with Widgets and Calendar nav items, aria-current
- Add Settings link in header user dropdown (gear icon, before logout)
- Add settings namespace (DE+EN) with all category and action keys
- Add widgets namespace (DE+EN) with all widget names, descriptions, error states
- Add header.settings key ("Einstellungen"/"Settings")

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:23:47 +02:00
schalli d5e1c42e64 feat(05-01): dashboard grid, clock widget, widget registry, store, and tests
- Install react-grid-layout@2.2.3 and react-resizable
- Create widget-registry.tsx with all 4 widget types, WIDGET_CONSTRAINTS, WidgetProps
- Create dashboard-api.ts with fetch/save layout and widget CRUD functions
- Create dashboard-store.ts (Zustand, NO persist — D-05) with edit mode and auto-save on exit
- Create DashboardGrid with react-grid-layout v2 Responsive, ResizeObserver width
- Create ClockWidget using Intl.DateTimeFormat (no manual UTC offsets)
- Create WidgetWrapper with drag handle and delete button in edit mode
- Create EditModeToggle (pencil/checkmark), WidgetCatalogModal (2x2 grid)
- Rewrite portal page.tsx as dashboard with grid, edit toggle, widget catalog
- Add ResizeObserver polyfill in test setup, CSS mock support in vitest config
- All 5 tests green (dashboard grid + clock widget)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:21:43 +02:00
schalli 792b7661d8 test(05-01): add failing tests for dashboard grid and clock widget
- DashboardGrid test: empty state, widget rendering, edit mode affordances
- ClockWidget test: timezone rendering, showDate toggle behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:15:18 +02:00
schalli 950eebbc15 feat(05-01): dashboard backend — Prisma models, CRUD API, module wiring
- Add DashboardLayout and WidgetInstance Prisma models with userId/tenantId scoping
- Create DashboardController with 6 endpoints (layout CRUD + widget CRUD)
- Create DashboardService with ownership verification on all widget mutations (T-05-01)
- Add SaveLayoutDto, CreateWidgetDto, UpdateWidgetConfigDto with class-validator
- Register DashboardModule in app.module.ts imports

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:14:03 +02:00
schalli f925fd3654 docs(05): complete phase plan (5 plans, 5 waves, 10/10 coverage) 2026-06-24 10:13:22 +02:00
schalli 114edcf89b docs(05): complete phase plan (5 plans, 4 waves, 32/32 coverage)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 10:08:01 +02:00
schalli 6e99ccc2a1 fix(05): clean must_haves, trailing XML, update ROADMAP to 5 plans
- Remove frontend artifacts from 05-03 must_haves (belong to 05-04)
- Remove trailing XML generation artifacts from 05-04 and 05-05
- Update ROADMAP Phase 5: 5 plans across 4 waves

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 10:07:35 +02:00
schalli 271e71f901 fix(05): remove duplicate frontend tasks from 05-03, add requirements field
05-03 now backend-only (4 tasks/13 files): model+crypto+CRUD, providers,
aggregation, prisma push. Frontend tasks moved exclusively to 05-04.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 10:03:37 +02:00
schalli e60d34dc28 wip: phase 05 plan-phase paused at revision verify (checker v2 pending)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:54:43 +02:00
schalli c8852d2014 docs(05): create dashboard & calendar phase plan
4 plans across 4 waves covering DASH-01..07 + CAL-01..03.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:42:11 +02:00
schalli b5ab2c806e docs(05): research phase domain - dashboard calendar 2026-06-23 14:29:14 +02:00
schalli 2005448c51 fix(05): resolve UI-SPEC typography and copywriting checker issues
Reduce typography to 4 sizes (12/14/18/28) and 2 weights (400/600).
Clock scaling declared as responsive exception, not standalone size.
Destructive CTAs now include noun (Quelle loeschen / Delete source).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:12:40 +02:00
schalli cd9f74531a docs(05): UI design contract for dashboard-calendar phase
Defines visual and interaction contracts for Phase 05 including
dashboard grid, 4 widget types, settings page, and calendar integration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:09:56 +02:00
schalli 0331d54e9a docs(state): record phase 05 context session 2026-06-23 14:01:18 +02:00
schalli b1101712df docs(05): capture phase context 2026-06-23 14:01:12 +02:00
schalli 7c35c17a07 docs(04-04): complete Phase 04 verification, close phase
Human verified marketplace features on localhost. 26 tests green.
Reverse proxy API URL config deferred. Phase 04 done, ready for Phase 05.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 12:26:33 +02:00
schalli a39322e7a6 wip: phase 04-04 paused at human verification (task 2/2)
Plans 04-01 through 04-03 complete. 26 tests green, stack running.
Awaiting human sign-off on 12-step verification checklist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 11:04:28 +02:00
schalli 191135bae8 docs(04-03): complete plan summary, update STATE
Plan 04-03 done — sidebar migrated, 5 new tests (26 total).
Ready for Plan 04-04 (navigation polish).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:22:04 +02:00
schalli e967ea9660 feat(04-03): migrate sidebar to Link/usePathname, add search and refresh signal
Replace all raw <a> with Next.js Link. Add usePathname-based active
highlighting, SidebarSearch with category/module filtering, and
sidebarRefreshKey subscription for live activation updates. 26 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:21:27 +02:00
schalli 9e705ab13a docs(04-02): complete plan summary, update STATE
Plan 04-02 done — 3 tasks, 12 tests added (21 total), 8 files.
Filters, tenant context, dialog, toast, detail page all operational.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:25:56 +02:00
schalli fdf2c38f67 feat(04-02): add module detail page at /marketplace/[slug]
Compact detail view with back link, full description (no line-clamp),
status indicator, and activation controls. Reuses ActivationDialog for
deactivation. 3 tests pass, 21 total green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:25:00 +02:00
schalli 0f3379f263 feat(04-02): add TenantContextSelector, ActivationDialog, and asymmetric toggle UX
Super-Admin tenant dropdown fetches /tenants, sets selectedTenantId for
per-tenant activation. Deactivation gated by confirmation dialog;
activation immediate with toast. 18 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:23:04 +02:00
schalli 06fb52da82 feat(04-02): add search, status tabs, category chips, toast, and client-side filtering
Build MarketplaceSearch (debounced 300ms), StatusFilter (3 tabs with
counts), CategoryFilter (horizontal chip row), and Toast (Zustand store
+ container). Wire useMemo filtering into page with filtered-empty state.
All 14 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:20:08 +02:00
schalli 00a01b5b19 docs(04-01): complete plan summary, update STATE, clean handoff
Plan 04-01 (marketplace browse + activate) done — 3 tasks, 9 tests,
10 files. Remove HANDOFF.json and .continue-here.md, advance to 04-02.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:52:56 +02:00
schalli fb6a340799 feat(04-01): implement marketplace page and marketplace-store
Create marketplace-store (Zustand) with sidebarRefreshKey signal and
tenant context. Build /marketplace page with parallel fetch, activation
Map, role gate, empty state, and responsive card grid. All 9 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:51:54 +02:00
schalli 2c526fccf6 wip: phase 04-01 paused at task 3/3 (RED done, GREEN pending) 2026-06-23 08:19:04 +02:00
schalli 0b7cf66abb test(04-01): add failing tests for marketplace page
- 4 tests: card grid rendering, activation status display,
  access-denied for non-admin, empty state
- Tests fail as expected (RED phase) - page and store not yet implemented
2026-06-22 14:48:39 +02:00
schalli 1e494b36ea feat(04-01): implement MarketplaceCard component and marketplace i18n namespace
- Add marketplace namespace to de.json and en.json with all copywriting contract strings
- Add sidebar.search and sidebar.noResults i18n keys
- Create MarketplaceCard with icon, name, localized description, category badge,
  status badge (role="status"), and activate/deactivate button
- All 5 unit tests pass (GREEN phase)
2026-06-22 14:47:53 +02:00
schalli a64f889251 test(04-01): add failing tests for MarketplaceCard component
- 5 tests: name+description rendering, category badge, activate button,
  activated status badge, onToggle callback
- Tests fail as expected (RED phase) - component not yet implemented
2026-06-22 14:46:30 +02:00
schalli e50b3c76c5 chore(04-01): install and configure Vitest test infrastructure for apps/web
- Add vitest, @testing-library/react, @testing-library/jest-dom, jsdom, @vitejs/plugin-react as dev deps
- Create vitest.config.ts with jsdom environment and @ path alias
- Create test setup file importing jest-dom/vitest matchers
- Add test scripts to apps/web and root package.json
- Add test task to turbo.json pipeline
2026-06-22 14:45:54 +02:00
schalli fb6e90d78e docs(04): create phase plan 2026-06-22 14:20:01 +02:00
schalli 0470d500b2 docs(04): create phase plan — marketplace & portal navigation (4 plans, 3 waves)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 14:17:02 +02:00
schalli 670fe088a4 docs(04): research phase domain — marketplace & portal navigation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 14:06:42 +02:00