Live wall: selected incident loads its own calls, resolved deep links, scrubber marks unloaded time (#239) #272

Merged
logan merged 2 commits from fix/239-call-window into main 2026-10-05 03:33:28 -04:00
Owner

Finishes #239. The spine "N of M" part already shipped in #253.

What changed

  • Selected incident loads its own calls. LiveView merges useCallsByIncident(link.inc) into the calls passed to IncidentPanel and MapView, deduped by call_id. The query uses the existing org_id + incident_ids CONTAINS index with no orderBy/limit, so no new index is needed. An incident whose early calls fell out of the 500-call window now shows its full path and spine. The hook keeps the previous incident's rows until the new snapshot lands, so each row is checked against the current id before it is merged.
  • Resolved deep links. If #inc= isn't in the active set, the incident is fetched with useIncident.
    • Resolved: it is selected, drawn on the map, and shown under a "Resolved HH:MM" banner (from resolved_at; the date is added if it wasn't today).
    • Missing, or org_id doesn't match the viewer's org: the panel shows "Incident not found" with a Back to region button. The org check is client-side as well as in the rules, because the rules may not be deployed (server-26#13).
    • Auto-tour still uses active incidents only.
  • Scrubber marks time it didn't load. TimeScrubber has a new loadedSince prop: the oldest call's started_at when the window came back full, otherwise null. The axis before that point is hatched and labelled "not loaded", with a tooltip, and those buckets are drawn blank instead of as zero-height bars.
  • Two small hook changes, both needed:
    • useCalls now returns hasMore (snap.size >= limit). calls.length can't tell whether the window was full, because the duplicate_of filter removes rows from a full page.
    • useIncident resets loading when the id changes. Without that, the not-found state flashed before each lookup finished.

Files I didn't touch: MapView, WallPanels, liveWall and types (#236), plus c2api and the discord files.

Verification

  • tsc --noEmit (fresh scratch copy): exit 0, no errors.
  • c2-core pytest: 923 passed, 4 warnings. No Python changed.
  • I have not checked any of this in a browser against live data.

Closes #239

🤖 Generated with Claude Code

Finishes #239. The spine "N of M" part already shipped in #253. **What changed** - **Selected incident loads its own calls.** `LiveView` merges `useCallsByIncident(link.inc)` into the calls passed to `IncidentPanel` and `MapView`, deduped by `call_id`. The query uses the existing `org_id + incident_ids CONTAINS` index with no `orderBy`/`limit`, so no new index is needed. An incident whose early calls fell out of the 500-call window now shows its full path and spine. The hook keeps the previous incident's rows until the new snapshot lands, so each row is checked against the current id before it is merged. - **Resolved deep links.** If `#inc=` isn't in the active set, the incident is fetched with `useIncident`. - Resolved: it is selected, drawn on the map, and shown under a "Resolved HH:MM" banner (from `resolved_at`; the date is added if it wasn't today). - Missing, or `org_id` doesn't match the viewer's org: the panel shows "Incident not found" with a Back to region button. The org check is client-side as well as in the rules, because the rules may not be deployed (server-26#13). - Auto-tour still uses active incidents only. - **Scrubber marks time it didn't load.** `TimeScrubber` has a new `loadedSince` prop: the oldest call's `started_at` when the window came back full, otherwise null. The axis before that point is hatched and labelled "not loaded", with a tooltip, and those buckets are drawn blank instead of as zero-height bars. - **Two small hook changes, both needed:** - `useCalls` now returns `hasMore` (`snap.size >= limit`). `calls.length` can't tell whether the window was full, because the `duplicate_of` filter removes rows from a full page. - `useIncident` resets `loading` when the id changes. Without that, the not-found state flashed before each lookup finished. Files I didn't touch: MapView, WallPanels, liveWall and types (#236), plus c2api and the discord files. **Verification** - `tsc --noEmit` (fresh scratch copy): exit 0, no errors. - c2-core pytest: 923 passed, 4 warnings. No Python changed. - I have not checked any of this in a browser against live data. Closes #239 🤖 Generated with [Claude Code](https://claude.com/claude-code)
logan added 1 commit 2026-10-05 03:25:40 -04:00
- LiveView: the selected incident merges useCallsByIncident (org_id +
  incident_ids CONTAINS, existing index, no orderBy/limit) into the calls fed
  to IncidentPanel and MapView, so a long incident keeps its full path and
  spine past the 500-call window. Stale rows from the previous selection are
  re-checked against the current id before merging.
- #inc= not in the active set is fetched with useIncident: a resolved one is
  selected, drawn on the map and shown under a "Resolved HH:MM" banner; a
  missing or other-org id shows "Incident not found". Auto-tour stays on
  active incidents.
- TimeScrubber: new loadedSince prop (oldest call when the window came back
  full). The axis before it is hatched and labelled "not loaded" instead of
  reading as a quiet stretch.
- useCalls returns hasMore (full page, counted before the duplicate_of
  filter); useIncident resets loading on a new id so a lookup doesn't flash
  "not found".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logan added 1 commit 2026-10-05 03:30:17 -04:00
useIncident reports loading until its answer belongs to the current id
(the render before the effect read the previous id's loading=false), and
clears a stale doc on a denied read. LiveView holds the last selected doc
for the same id while the by-id lookup is pending, so a watched incident
resolving no longer deselects (fly to region) and reselects (fly back).

Follow-up for the panel's 'active'/elapsed copy on resolved incidents: #275.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logan merged commit 1d6e79ba25 into main 2026-10-05 03:33:28 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/server-26#272