docs(plans): design for Notifications nav group
This commit is contained in:
143
docs/plans/2026-05-19-notifications-nav-group-design.md
Normal file
143
docs/plans/2026-05-19-notifications-nav-group-design.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Notifications Nav Group — Design
|
||||
|
||||
**Date:** 2026-05-19
|
||||
|
||||
**Goal:** Consolidate all notification-related Central UI pages into a dedicated
|
||||
**Notifications** left-menu section, split the combined Outbox page into a report
|
||||
and a KPIs page, give Notification Lists a proper home, and add a per-source-site
|
||||
KPI breakdown.
|
||||
|
||||
## Background
|
||||
|
||||
Notification-related UI is currently scattered:
|
||||
|
||||
| Page | Route | Nav section | Policy |
|
||||
|---|---|---|---|
|
||||
| SMTP Configuration | `/admin/smtp` | Admin | RequireAdmin |
|
||||
| Notification Outbox (KPI tiles **+** filterable table) | `/monitoring/notification-outbox` | Monitoring | RequireDeployment |
|
||||
| Notification Lists | `/design/notification-lists/...` (form only) | none — table embedded in the External Systems page | RequireDesign |
|
||||
|
||||
The Outbox page mixes KPI tiles and the filterable `Notifications`-table report on
|
||||
one page. Notification Lists has no list page of its own — its table is bolted
|
||||
onto `ExternalSystems.razor`. KPI infrastructure
|
||||
(`NotificationKpiRequest`/`Response`, `INotificationOutboxRepository.ComputeKpisAsync`)
|
||||
is global-only, despite CLAUDE.md stating KPIs are "global + per-source-site".
|
||||
|
||||
## Architecture
|
||||
|
||||
A new **Notifications** left-menu section consolidates these pages. Routes move
|
||||
to a consistent `/notifications/*` prefix. The combined Outbox page is split into
|
||||
two. Notification Lists gets a dedicated page. A bounded backend addition supplies
|
||||
per-source-site KPIs. No actor topology, persistence, or message-evolution rules
|
||||
change beyond the additive KPI contracts.
|
||||
|
||||
## 1. Nav menu
|
||||
|
||||
New `Notifications` section in `NavMenu.razor`, placed **between Deployment and
|
||||
Monitoring**. Final section order: Dashboard, Admin, Design, Deployment,
|
||||
Notifications, Monitoring, Audit Log.
|
||||
|
||||
| Menu item | Route | Policy |
|
||||
|---|---|---|
|
||||
| SMTP Configuration | `/notifications/smtp` | RequireAdmin |
|
||||
| Notification Lists | `/notifications/lists` | RequireDesign |
|
||||
| Notification Report | `/notifications/report` | RequireDeployment |
|
||||
| Notification KPIs | `/notifications/kpis` | RequireDeployment |
|
||||
|
||||
Each item is wrapped in its own per-item `AuthorizeView` policy (same pattern the
|
||||
Monitoring section already uses for its mixed-role items). The section header is a
|
||||
plain `div` — every authenticated user holds at least one of Admin/Design/Deployment,
|
||||
so the header always has ≥1 visible child and cannot be orphaned.
|
||||
|
||||
SMTP Configuration is **removed** from the Admin section; Notification Outbox is
|
||||
**removed** from the Monitoring section.
|
||||
|
||||
## 2. SMTP Configuration
|
||||
|
||||
Move `Components/Pages/Admin/SmtpConfiguration.razor` →
|
||||
`Components/Pages/Notifications/SmtpConfiguration.razor`. Route `/admin/smtp` →
|
||||
`/notifications/smtp`. Page content, `RequireAdmin` policy, and the
|
||||
`SmtpConfiguration` namespace alias are unchanged.
|
||||
|
||||
## 3. Notification Lists (new page)
|
||||
|
||||
New `Components/Pages/Notifications/NotificationLists.razor`
|
||||
(`/notifications/lists`, RequireDesign): a `DataTable` of notification lists with
|
||||
Add and per-row Edit actions, plus an empty state — extracted verbatim from the
|
||||
notification-lists block currently in `ExternalSystems.razor`.
|
||||
|
||||
- `NotificationListForm.razor` routes move:
|
||||
`/design/notification-lists/create` → `/notifications/lists/create`,
|
||||
`/design/notification-lists/{Id:int}/edit` → `/notifications/lists/{Id:int}/edit`.
|
||||
Its "Back" navigation targets `/notifications/lists`.
|
||||
- The notification-lists section is **removed** from `ExternalSystems.razor`,
|
||||
leaving that page purely external systems. The three `/design/notification-lists/...`
|
||||
navigate-links in `ExternalSystems.razor` are removed with it.
|
||||
|
||||
## 4. Notification Report
|
||||
|
||||
New `Components/Pages/Notifications/NotificationReport.razor`
|
||||
(`/notifications/report`, RequireDeployment), split from the existing
|
||||
`Monitoring/NotificationOutbox.razor`. Retains the full filter bar, the paginated
|
||||
`Notifications`-table query (`NotificationOutboxQueryRequest`), and the per-row
|
||||
Retry/Discard actions. The **KPI tile row is removed** from this page.
|
||||
|
||||
`Components/Pages/Monitoring/NotificationOutbox.razor` and its Monitoring nav entry
|
||||
are **deleted**.
|
||||
|
||||
## 5. Notification KPIs
|
||||
|
||||
New `Components/Pages/Notifications/NotificationKpis.razor`
|
||||
(`/notifications/kpis`, RequireDeployment) with a manual Refresh button. Two parts:
|
||||
|
||||
1. **Global tiles** — the existing 5: Queue Depth, Stuck, Parked, Delivered Last
|
||||
Interval, Oldest Pending Age.
|
||||
2. **Per-source-site breakdown table** — one row per site with the same five
|
||||
metrics, so operators can see which site is backing up.
|
||||
|
||||
### Backend addition for per-site KPIs
|
||||
|
||||
Bounded, additive, follows the existing global-KPI pattern:
|
||||
|
||||
- `INotificationOutboxRepository.ComputePerSiteKpisAsync(...)` → returns a
|
||||
per-site collection (a new `SiteNotificationKpiSnapshot` record carrying the
|
||||
source site id plus the five metrics). Implemented in
|
||||
`NotificationOutboxRepository`.
|
||||
- New message pair in `Messages/Notification/NotificationOutboxQueries.cs`:
|
||||
`PerSiteNotificationKpiRequest` / `PerSiteNotificationKpiResponse` (additive —
|
||||
honors message-evolution rules).
|
||||
- A handler in `NotificationOutboxActor` for the new request, mirroring the
|
||||
existing `NotificationKpiRequest` handler.
|
||||
- A `CommunicationService.GetPerSiteNotificationKpisAsync(...)` method mirroring
|
||||
`GetNotificationKpisAsync`.
|
||||
|
||||
Per CLAUDE.md, KPIs remain point-in-time computed from the `Notifications` table —
|
||||
no time-series store, no historical charts (YAGNI).
|
||||
|
||||
## 6. Health dashboard
|
||||
|
||||
`Monitoring/Health.razor` keeps its KPI tile row unchanged. A "View details →"
|
||||
link is added from that tile row to `/notifications/kpis`.
|
||||
|
||||
## Error handling
|
||||
|
||||
Unchanged from the current Outbox page: KPI/query faults surface as an inline
|
||||
warning alert (`Success == false` → `ErrorMessage`); the site-name lookup degrades
|
||||
gracefully to raw site ids. Per-site KPI faults are reported the same way.
|
||||
|
||||
## Testing
|
||||
|
||||
- bUnit component tests for `NotificationLists`, `NotificationReport`,
|
||||
`NotificationKpis`, and the moved `SmtpConfiguration` page.
|
||||
- A `NavMenu` test asserting the Notifications section renders and that per-item
|
||||
visibility honors Admin/Design/Deployment roles.
|
||||
- Repository tests for `ComputePerSiteKpisAsync`.
|
||||
- Actor test for the `PerSiteNotificationKpiRequest` handler.
|
||||
- `CommunicationService` test for `GetPerSiteNotificationKpisAsync`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Historical/trend KPI charts (no time-series store).
|
||||
- Any change to notification delivery, store-and-forward, or the `Notifications`
|
||||
table schema.
|
||||
- Renaming the Notification Outbox **component** (#21) — only the UI page names change.
|
||||
Reference in New Issue
Block a user