feat(#153): notification history page (/notifications) #155
Reference in New Issue
Block a user
Delete Branch "feature/153-notification-history"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #153
Summary
GET /api/notifications?read=falsewith notypeparam silently returned all notifications. AddedfindByRecipientIdAndReadFalseOrderByCreatedAtDesctoNotificationRepositoryand the missing branch inNotificationService.@Min(1) @Max(100)on thesizeparam and@Validatedon the controller. AddedConstraintViolationException → 400toGlobalExceptionHandler. Addedspring-boot-starter-validationdependency.documentTitlein DTO: NewDocumentService.findTitlesByIds(Collection<UUID>)fetches all titles in one query.NotificationService.getNotifications()populatesdocumentTitleper page — null when document is deleted.$lib/utils/notifications.ts—NotificationItemtype,relativeTime(ts, now?)(deterministic, testable),parseNotificationEvent()(SSE payload shape validation, NullX Finding 3).NotificationBell.svelteupdated to import from there./notificationspage: Filter pills (role="radiogroup"/role="radio"/aria-checkedbound to URL params via$derived), notification rows with border+dot unread indicators (WCAG 1.4.1), "Alle als gelesen markieren" form action (only whenunreadCount > 0), "Ältere laden" client-side append, empty state.de.json,en.json,es.json.Screenshots
Empty state
List view (~20 items, first page)
Load-more view (~40 items after clicking "Ältere laden")
Test plan
./mvnw test -Dtest="NotificationServiceTest,NotificationControllerTest"— 52 tests pass (3 new service tests, 3 new controller tests)npx vitest run --project=server— 114 tests pass (7 new page server tests, 15 new utility tests)GET /api/notifications?read=falsereturns only unread notifications (previously returned all)GET /api/notifications?size=200returns 400documentTitlefield/notificationsrenders with filter pills, rows show document titles, "Alle anzeigen →" in bell dropdown links here/profileshows "Benachrichtigungsverlauf ansehen →" link below notification prefsSecurity checklist (NullX findings)
NotificationServiceTestsize: clamped to 100, covered byNotificationControllerTestparseNotificationEvent()guards shape, covered bynotifications.spec.ts{@html}on any notification field/api/*proxied with auth token injectionOut of scope
🤖 Generated with Claude Code
Adding the link div after the {#each} broke last:border-0 — the last mention item was no longer the last child, so it kept its border-b, creating a double line with the link's border-t. Wrapping the each in its own div restores correct last:border-0 targeting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>