v4.13 — Notification History
Once you acknowledge a notification it used to vanish for good — now there's a dedicated place to look back.
Summary
Before this milestone, Objectuve's notification tray (NotificationsPanel.vue) cleared an item the moment a user acknowledged it — by design, to keep the tray itself short and current. That created a real gap: once acknowledged, a notification was gone with no way to revisit it, even though the underlying UserNotification record persisted server-side the whole time.
This milestone gave users a dedicated Notification History page at /notifications — a full, date-grouped record of everything the app has told them, acknowledged or not. It shipped in two phases: a data layer (a new paginated GraphQL query and composable, plus a fix for a latent bug where the tray's delete button was silently wired to the acknowledge mutation instead of the real delete) and a UI layer (an extracted, dual-mode notification row component, the history page itself, and a link from the tray). The tray's clear-on-acknowledge behavior was deliberately left untouched — the history page is a separate, additive surface, not a replacement.
Goal
Give users a dedicated Notification History page at
/notificationswhere they can review their full notification history — both acknowledged and unacknowledged — after the tray has cleared acked items. The page is date-grouped (New / Today / This Week / Earlier), renders per-kind icons + read/unread state like the tray, and offers per-item mark-read and delete actions, mirroring the attached Facebook / LinkedIn references. The notification tray keeps its clear-on-acknowledgement behavior and gains a "See all notifications" link to the page.
Scope — What Shipped
- New backend GraphQL query
notificationHistory(limit, offset)returning{ items, totalCount, hasMore }(rails_api/app/graphql/types/query_type.rb, resolverapp/graphql/resolvers/notification_queries.rb, interactionapp/interactions/social/build_notification_history.rb, typeapp/graphql/types/notification_history_type.rb) — ownership-guarded to the current user, additive and separate from the tray's existinguser.notifications(limit:)field. - New frontend
useNotificationHistory.tscomposable andNOTIFICATION_HISTORY_QUERYGraphQL constant, mirroring the offset-pagination pattern already used byuseUnifiedFeed.ts. - Fixed a latent bug:
useNotifications.ts'sdeleteNotificationwas wired to the acknowledge mutation instead of the real delete mutation — it now calls the actual delete mutation. - New standalone view
ionic_frontend/src/views/NotificationHistory.vueat route/notifications, with date-grouped sections (New / Today / This Week / Earlier), an All/Unread filter, per-item mark-read and delete, and pull-to-refresh. - Extracted
NotificationItem.vue(components/ui/) from the tray's previously-inline row markup, supporting both compact tray mode and full history mode;NotificationsPanel.vuenow consumes it directly, with no visual tray regression. - A "See all notifications" link added to the tray's footer, pointing to
/notifications. - Storybook stories for both
NotificationItemandNotificationHistory.
Phases
| Phase | Name | Status | Plans | Highlights |
|---|---|---|---|---|
| 1 | Notification history data layer | Shipped | 1 | New paginated notificationHistory query + useNotificationHistory composable; fixed the deleteNotification mutation-wiring bug |
| 2 | Notification history UI + docs | Shipped | 1 | Extracted NotificationItem, built the /notifications page, wired the tray's "See all notifications" link |
Key Decisions
- Standalone page at
/notifications, deliberately not folded into/feed— confirmed by Josh at kickoff. The unified feed (/feed) is a differently-shaped, blended activity stream (ally activity, community posts, own progress) that already ingests notifications as one source among several; folding full notification history into it would bury it and lose acknowledge/delete semantics specific to notifications. Both of the Facebook/LinkedIn references used to scope this feature are dedicated notification pages, not blended feeds. - No migration or model change needed —
UserNotificationalready persisted every acknowledged record (acknowledgedis a boolean flip; deletion is a separate hard-destroy mutation), so the full history already existed in the database. The only backend work was a new, additive read query — the existing tray query was never reshaped. - Fix the
deleteNotificationbugfix in the same milestone, not as a separate ticket — the history page's delete action would have inherited the same latent bug (silently acknowledging instead of deleting) had it not been caught and fixed in Phase 1, alongside the composable that both the tray and the new page depend on. NotificationItemextracted as a dual-mode component, not duplicated — rather than building a separate history-specific row component, the tray's inline markup was extracted into one component that serves both the compact tray and the full-detail history page, so the tray's visual behavior stayed byte-for-byte unchanged.
Requirements Coverage
5.5 / 6 deliverables satisfied (quoted from the MILESTONE-AUDIT) — all five implementation deliverables shipped clean; the sixth, NOTIF-DOCS-1 (GraphQL reference docs + CHANGELOG entry), only partially landed. This page and its accompanying audit are the retroactive completion of that documentation deliverable's milestone-close half; the narrower GraphQL-reference-regeneration and CHANGELOG-backfill work remains open as a follow-up (see the audit's Tech Debt section).
| Category | Count | Status |
|---|---|---|
| NOTIF-API / NOTIF-UISPEC (Phase 1 backend + design) | 2 | Satisfied |
| NOTIF-DATA (Phase 1 frontend + bugfix) | 1 | Satisfied |
| NOTIF-ITEM / NOTIF-PAGE (Phase 2 UI) | 2 | Satisfied |
| NOTIF-DOCS (Phase 2 docs) | 1 | Partial — see Tech Debt |
Full detail: v4.13-notification-history-MILESTONE-AUDIT.md on GitHub.
Outcomes
Users can now open /notifications from the tray's "See all notifications" link and see their complete notification history, grouped by New / Today / This Week / Earlier, filterable to unread-only, with the ability to mark individual items read or delete them — none of which was possible once the tray cleared an acknowledged item. The tray itself is unaffected: its clear-on-acknowledge behavior, its per-kind icon treatment, and its existing acknowledge mutation all continue to work exactly as before, now via the shared NotificationItem component instead of inline markup. The previously-latent deleteNotification bug (delete silently behaving like acknowledge) no longer affects either surface.
Tech Debt
- (Phase 2, NOTIF-DOCS-1) The
notificationHistoryGraphQL query andNotificationHistoryTypewere never added todocs/architecture/graphql/queries.md/types.md, and noCHANGELOG.mdentry exists for either shipping PR (#1740, #1899). This milestone's narrative and audit close the milestone-tracking gap; the GraphQL-reference regeneration and CHANGELOG backfill remain open as a follow-up. - (Standing, pre-existing)
docs/development/notification-surfaces.md's "Known fragmentation / hub direction" section still frames a unified/notificationsview as a future, out-of-scope idea — that view has shipped since 2026-07-30. Flagged for a doc-fix follow-up, not corrected in this close.
Related Artifacts
- Roadmap: v4.13-notification-history-ROADMAP.md
- Milestone Audit: v4.13-notification-history-MILESTONE-AUDIT.md
- Source issue: OBJ-1685
- Merge PRs: #1740, #1899
Related Commits
97285ec0e— [Codi] feat(notifications): add paginated history query + composable (OBJ-1689) (#1740)58a4b65ec— [Codi] feat(notifications): build /notifications history page (v4.13 Phase 2) (#1899)
Last updated: 2026-08-04