Repository navigation
feat(alerts): full-page escalation chain editor - #2436
Conversation
- Kit: rightSheet over the Dialog Submodel (672px form size, scrolling body, sticky footer, slide dropped under reduced motion) with followUrl/isDismissed; page/kit/sheet-param holds the ?sheet= helpers (push to open, replace to close). - Sidebar group labels fold their rows (sidebarGroupToggle, aria-expanded), saved to localStorage; the group holding the current page and the collapsed rail always show every row. - Footer on-call pill from the schedules list's on_call_now and the session user: on call until the handoff, not on call, or hidden without schedules. Re-read at each handoff; a dot with a tooltip on the rail. - /lab/shell shows all three, with a demo form in the sheet.
- Sheet: opening pushes a history entry marked as this tab's; dismissing goes back past it, and only a deep link replaces the param. Kit renamed to sidePanelSheet, footer receives close; sheet-param tests sit beside it. - On-call pill: a shift past its end reads as unknown; reads again at the handoff, hourly while off call, on focus and visibility, and with backoff (60s doubling, capped) after a stale or failed answer, keeping the last good data. Schedule and override writes announce a re-read. - An org with no schedules is cached per org for a day and skips the request; a schedule write clears it. - "until" uses the viewer's time zone with a short zone name. - Sidebar: the collapsed rail renders plain labels (no tab stops); the group holding the current page can fold and keeps only that row. The pill uses aria-label on the rail instead of a title.
… side panel
- Each hub section has its own path (/alerts/rules, /alerts/uptime, /alerts/slos,
/alerts/silences, /alerts/maintenance, /alerts/on-call, /alerts/routing); /alerts
stays the Inbox. One page instance serves them all, so a section change reads
nothing it already has.
- Old /alerts?tab= links replace themselves with the section's path and keep
their other params ("oncall" and "settings" map to on-call and routing).
- The sidebar's Alerts row lists the sections when active and replaces the hub's
own section rail. Sub-item aria-current now follows the most specific match.
- New silence opens in a URL-held side panel (?sheet=silence) with a sticky
Cancel / Save footer; Back, Cancel, Escape and a save close it.
sidePanelSheet gains onSubmit so the panel is a form.
- The silence panel clears ?sheet= in the model as soon as it closes itself, so a clock tick before the URL change can't reopen it. It opens only on the Silences section, and a viewer who can't manage loses a linked ?sheet= once the grants load (replaced away). - A rule lives at /alerts/rules/<ruleId>; /alerts/<ruleId> (notifications, the apps) replaces itself with it, keeping its tab and window. The rule page and editor go back to Rules and their crumbs go through it. - Settings automation and setup health link to the new section paths. - The sidebar reveals the open section, every sub-item past the edge fades, on each route change; sub-rows are tighter, thin rules split the former groups, and the Inbox shows its unacknowledged count from the alert_incidents collection, read only while an alerts page is open. - One AlertsTab schema next to AlertsSection; the sheet commands answer with a clock read instead of a no-op message.
Escalation chains move out of the Routing dialog into /alerts/escalation-chains/new and /alerts/escalation-chains/:chainId. The chain reads as a column of sentence cards (start, steps, repeat) with a + between cards to insert a step and a per-step menu to move, duplicate or remove it. The aside holds the name, notes, a one-line preview, the rules that use the chain, and delete, whose confirm lists those rules. Validation moved from the dialog into a shared form module; the data model and API are unchanged. Routing and the rule editor link to the new pages and the dialog is deleted.
/lab/escalation-editor renders the editor page over fixtures: new, populated, a step inserted, invalid, and the delete confirm.
Safety and state: - Drop returnTo and its helper: no caller passed it, and it could be steered off-site. - Ask before leaving with unsaved edits (link, Back or Cancel). A clean form, or one put back to how it was, leaves at once. - Save and Create go back to Routing with the toast, so the list shows the saved name and rules. - A chain deleted elsewhere reads as not found with the way back, and a save that hits it says the chain no longer exists. - A delete the API refuses reads the chain again, so the dialog names the rule that took it and holds its Delete. - Viewers without alerts:manage read the chain and who uses it; nothing can be edited, saved or deleted. Nothing renders until the session answers. - Step edits move focus: a new or duplicated step to its Add button, a removed step to the one before it or the leading +. - Remove the unused step messages. Layout: - A step is two lines: "Notify" with its targets as inline chips and an Add chip, then the wait. A three-step chain fits in 800px. - Targets draw their own mark: the destination's logo, a person's avatar, a schedule's calendar with who is on call now. - The last step of a chain that does not repeat reads "then stop". - The picker says what is still loading and where to make a destination; someone removed from the org reads "Unavailable member". - The connector is a 24px line whose + shows on hover, focus and touch. - Delete is a quiet destructive button under the details; a paused rule says so in Used by. Kit: pickChips, chainConnector, and a destructive-ghost button variant.
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
This comment has been minimized.
This comment has been minimized.
…size - A `scrim-panel` token (12% black, 24% in dark) with no blur sits beside a side panel, so the page it edits stays readable. Dialogs and other sheets keep `scrim`. - `sidePanelSheet` takes `size`: `compact` (28rem) for a few short fields, `form` (42rem, the default) or `wide`.
- The on-call pill is one 32px row of the footer list: a status dot and "On call until Mon 09:00" in the viewer's zone (the date instead of the weekday once the handoff is over six days out), or a muted "Not on call". The zone, date and schedules are its tooltip and accessible name. On the collapsed rail it is a calendar glyph badged with the dot. - Group chevrons show faintly at rest; the toggle is 28px tall. - A folded group holding the current page shows that page's parent row alone, highlighted, without its sub-items. - Hover is a neutral wash. When a sub-item is the current page only it is tinted; its parent keeps the medium weight on a plain background. - Sub-item rows are 28px on desktop and 36px in the mobile sheet. - /lab/shell gains Services and Logs pages, a far handoff and both panel sizes.
… the silence panel
- Each section's header has one primary action: New rule (split) on the Inbox
and Rules, New monitor, New SLO, New silence, New window, New schedule and
Add destination on their own sections. A section whose empty state already
offers it shows none until it has rows.
- The Alerts sub-list sets its groups apart with a 4px gap instead of rules,
and its rows take the kit's height again.
- The silence panel's Services, Environments and Tags are chips inputs that
suggest what the org's rules name (and the services Uptime listed); a typed
name can still be added. Its labels share one style.
- A picked end is on the viewer's clock and the field names the zone
("Ends, CET"); a scheduled row names its day once. The lab reads the
viewer's zone instead of UTC.
- The duration choice uses the larger segmented size.
# Conflicts: # apps/web/src/shell/oncall.scene.test.ts # apps/web/src/shell/view-nav.ts
This comment has been minimized.
This comment has been minimized.
|
F1 fixed in 503f89f: the chain name link is |
…ople read is said
This comment has been minimized.
This comment has been minimized.
# Conflicts: # apps/web/src/shell/command.ts # apps/web/src/shell/flags.ts
…in, not New escalation chain
This comment has been minimized.
This comment has been minimized.
Preview testTested on the combined preview of the whole stack (#2466, app-pr-2466.maple.dev) by a separate test agent in a real browser: happy paths, break attempts, light and dark, and a 390x844 viewport. No uncaught page errors. Passed: Found and fixed in this push:
Still open: after Back then "Discard changes", the next Back returns to a blank new-chain page. The guard is shared with the dashboard widget editor and behaves the same there, so it wants its own change. Traces (preview environment |
…n tab finds the first one
…read within the hour whoever holds it
# Conflicts: # apps/web/src/shell/view-nav.ts
This comment has been minimized.
This comment has been minimized.
# Conflicts: # apps/web/src/shell/message.ts # apps/web/src/shell/model.ts # apps/web/src/shell/oncall.scene.test.ts # apps/web/src/shell/update.ts # apps/web/src/shell/view-nav.ts # packages/views/src/ui/sheet.ts
This comment has been minimized.
This comment has been minimized.
# Conflicts: # apps/web/src/page/alerts/editor/editor-chains.scene.test.ts # apps/web/src/page/alerts/shared/escalation-chains.ts # apps/web/src/route/route.test.ts # apps/web/src/shell/nav.ts # packages/views/src/ui/INDEX.md
This comment has been minimized.
This comment has been minimized.
… notes error names the notes
|
Both notes are fixed in
|
Maple review🟢 Confidence 8/10 · likely safe to merge. Held at 8 because 2 reviewed files were not read. Moves escalation chains from a dialog to a full page (
Fixed since the last review
Production impactOpen errors in the changed files (2)
After this merges, Maple checks whether they stop. Files not reviewed (2)The review ended before it read these diffs, so nothing above vouches for them.
|
Maple: after this shipped✅ Shipped clean. Nothing this change touches got worse in the hour after it deployed. Deployed to Errors in the changed files:
Maple looks once, an hour after the first deploy that carries the merge. |


Stacked on #2426. Escalation chains move out of the dialog into a full page that reads as a sentence.
What changed
/alerts/escalation-chains/newand/alerts/escalation-chains/:chainId. Breadcrumb Alerts > Routing > chain name; the Routing sidebar item stays lit; Cancel and Save stay pinned in the header.alerts:manageget the page read-only.escalation-chain/form.ts). New page-kit piecespickChipsandchainConnector; adestructive-ghostbutton variant.Before / after
Lab:
/lab/escalation-editor?state=new|populated|inserted|invalid|delete.Verification
apps/web:bunx vitest run src/page/alerts src/route src/shell src/lab src/page/kit736 pass, rootsrc/*.test.ts134 pass;packages/viewssrc/ui166 pass. The page has 25 tests: create (add, set targets and waits, insert between, reorder, remove, save), edit, validation, delete confirm and the in-use refusal, the unsaved-changes guard, not found, read-only, focus targets.@maple/web);oxlint -c .oxlintrc.effect.jsonclean on changed files;ui:index,ui:patterns:checkpass.returnToparam, now removed; no unsaved-changes guard; stale title after save; retry loop on a deleted chain; viewers hitting a dead end); all fixed.Not verified: a live API (the not-found and in-use codes are matched by string), and the browser's own Back and tab close through the unsaved-changes guard.
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by CodeRabbit
New Features
Bug Fixes