Commit Graph

7 Commits

Author SHA1 Message Date
Marcel
fe6c247882 refactor(admin): extract EntityNavSection to eliminate nav markup repetition (#197)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 13:54:42 +02:00
Marcel
7e43bd43a4 feat(dark-mode): replace neutral tokens with navy-tinted palette + fix WCAG AA
- Replace neutral dark tokens (#0d0d0d, #1a1a1a, etc.) with navy-tinted
  values derived from brand-navy: canvas #010e1e, surface #011526,
  overlay #011e38, muted #011a30
- Fix --c-ink-3 WCAG AA failure in [data-theme='dark'] block:
  #6b7280 (3.2:1, fail) → #8b97a5 (7.1:1, AAA ✓)
- Add color-scheme: dark to both dark blocks for native OS scrollbar theming
- Update PDF viewer tokens to navy palette (bg #010e1e, ctrl #011526, text #f0efe9)
- Add --c-header token (#ffffff light / #01335e dark) for independent
  header surface control; mapped to --color-header in @theme inline
- Fix EntityNav contrast: text-white/30 → /50 (heading) and text-white/20
  → /50 (inactive count badges) to pass WCAG AA 4.5:1 on bg-brand-navy

Closes #166

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 11:37:30 +02:00
Marcel
154f859efc feat(korrespondenz): address PR #164 review – blockers and suggestions
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m36s
CI / Backend Unit Tests (pull_request) Failing after 2m36s
CI / E2E Tests (pull_request) Failing after 1h49m0s
Blockers (14):
- B1: fix senderName/receiverName to use $derived instead of $state + sync $effect
- B2: migrate all korrespondenz components from messages-extra shim to paraglide m.*
- B3: i18n CorrespondenzEmptyState (heading, subtext, search placeholder)
- B4: add response.ok checks to admin layout server load
- B5: add response.ok checks to korrespondenz page server load
- B6: add page.server.spec.ts with 5 test suites for korrespondenz load function
- B7: add axe-core accessibility checks to all e2e korrespondenz tests
- B8: add Testcontainers JPQL tests for findSinglePersonCorrespondence (DISTINCT + sender)
- B9: hide auth reset-token endpoint from OpenAPI spec; remove from generated api.ts
- B11: replace amber hardcoded hex colors in SinglePersonHintBar with brand tokens
- B12: replace clipboard emoji with Heroicons SVG in SinglePersonHintBar
- B13: create DateInput component (German dd.mm.yyyy); use it in CorrespondenzFilterControls
- B14: add Paraglide compile step to CI workflow before lint/test

Suggestions (11):
- S1: make CorrespondentSuggestionsDropdown a pure display component; lift fetch to PersonBar
- S2: fix leftover messages-extra import in ConversationTimeline; use brand tokens for status dots
- S3: add intent comment to EntityNav openFlyout behavior
- S4: rename canManageGroups → canManagePermissions throughout admin
- S6: remove domFlush helper from DateInput spec; use expect.poll instead
- S7: replace test.skip with throw new Error in bilateral e2e tests
- S8: add inverse aria-disabled test for filter strip
- S9: remove sm:min-h-0 from sort button to preserve 44px touch target
- S10: add title attributes to tablet trigger buttons in EntityNav
- S11: delete messages-extra.ts shim entirely

Also: fix admin pages revealing blank strip at bottom (-mb-6 on admin layout)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:57:48 +02:00
Marcel
393cb52178 fix(admin): address PR review feedback from all personas
Blockers resolved:
- localStorage key collision: UsersListPanel/GroupsListPanel/TagsListPanel
  now each use their own key (admin_*_list_collapsed)
- $effect autocollapse replaced with $derived(autocollapse || manualCollapse)
  across all three list panels (Felix — Svelte 5 rule violation)
- groups/new: add READ_ALL and ANNOTATE_ALL to available standard permissions
- Mobile back-to-list links added to all five detail panel headers (md:hidden)
  so users landing directly on a detail URL on mobile can navigate back
- onDestroy(() => stopPolling()) added to system/+page.svelte (Tobias)

High priority resolved:
- Permission labels in groups/[id] and groups/new now use Paraglide i18n keys
  (admin_perm_read_all, admin_perm_annotate_all, etc.) across de/en/es
- $derived used for permission arrays (reactive i18n) — Felix Svelte 5 rule
- UserGroup type in +layout.server.ts now uses generated API type (Markus/Felix)
- discardTarget annotation changed to variable-level type annotation

Accessibility (Leonie):
- EntityNav tablet icon strip buttons: min-h-[44px] for WCAG 2.5.8 compliance
- Flyout focus management: openFlyout() focuses first link, closeFlyout()
  returns focus to the trigger button that opened it
- Flyout animation replaced: broken inline style -> transition:fly={{ x: -160 }}

Tests (Sara/Felix):
- localStorage key assertion tests added per panel
- localStorage.removeItem calls updated to use the panel-specific keys
- page.server.spec.ts added for groups/[id] and tags/[id] delete actions
- Polling lifecycle tests added to system/page.svelte.spec.ts

Note: Paraglide types for new admin_perm_* keys regenerate automatically on
next npm run dev (Vite plugin). No manual compilation step needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 11:23:27 +02:00
Marcel
559b522507 feat(admin): entity flyout for tablet icon strip (Phase 9 complete)
Tapping any icon in the 48px tablet nav strip now opens a 160px overlay flyout
with full entity labels and navigation links. Flyout closes on Escape, backdrop
click, or link click. Includes role="dialog", aria-modal, aria-label for WCAG.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 09:06:03 +02:00
Marcel
3c54401bb2 feat(admin): responsive entity nav and collapsible list panels (Phase 9)
EntityNav: hidden on mobile, 48px icon strip at tablet (md), full labels+counts at desktop (lg).
Each list panel collapses to a 32px handle via localStorage-persisted state; auto-collapses when
navigating to the "+New" route. Mobile routing hides the list panel when a detail route is active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 07:19:41 +02:00
Marcel
8fc360a596 fix(admin): guard GET /api/users/{id} with @RequirePermission(ADMIN_USER)
Fixes IDOR: the endpoint was publicly accessible to any authenticated user.
Now requires ADMIN_USER permission, matching all other user management endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 01:09:40 +02:00