feat(web): consolidate Gantt into view tab on issue detail (UI-2) #401

Merged
charles merged 2 commits from feat/398-gantt-view-tab into main 2026-04-26 23:48:58 +00:00
Collaborator

Merges the Gantt timeline into the issue detail route as ?view=gantt, eliminating the redundant SSE subscription and duplicate onPipelineStage logic that existed between the two routes.

  • useIssuePipelineSSE(queryClient, repo, issueNum) hook extracts the shared SSE+cache-patch logic
  • ?view=graph|gantt search param added; graph is the default
  • Graph | Timeline tab toggle lives in the nav bar (same route, different ?view=)
  • now ticker only runs when view === "gantt" (effect cleanup on toggle)
  • Old /monitor/issue/$owner/$repo/$issueNumber/gantt route becomes a beforeLoad redirect to ?view=gantt

Test plan

  • validateSearch: gantt accepted, graph/invalid/absent → no key in output
  • Redirect test: beforeLoad throws with correct to, params, and search
  • Ticker guard: interval not started for graph view, started once for gantt, cleaned up on unmount

Closes #398

Merges the Gantt timeline into the issue detail route as `?view=gantt`, eliminating the redundant SSE subscription and duplicate `onPipelineStage` logic that existed between the two routes. - `useIssuePipelineSSE(queryClient, repo, issueNum)` hook extracts the shared SSE+cache-patch logic - `?view=graph|gantt` search param added; `graph` is the default - `Graph | Timeline` tab toggle lives in the nav bar (same route, different `?view=`) - `now` ticker only runs when `view === "gantt"` (effect cleanup on toggle) - Old `/monitor/issue/$owner/$repo/$issueNumber/gantt` route becomes a `beforeLoad` redirect to `?view=gantt` ## Test plan - `validateSearch`: `gantt` accepted, `graph`/invalid/absent → no key in output - Redirect test: `beforeLoad` throws with correct `to`, `params`, and `search` - Ticker guard: interval not started for graph view, started once for gantt, cleaned up on unmount Closes #398
feat(web): consolidate Gantt into view tab on issue detail (UI-2)
Some checks failed
qa / qa (pull_request) Failing after 3m26s
qa / dockerfile (pull_request) Successful in 9s
ef93b6cb13
Extends monitor.issue detail route with ?view=graph|gantt, extracts
useIssuePipelineSSE hook, adds tab toggle, redirects the old /gantt route,
and guards the now-ticker to only run when view=gantt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev force-pushed feat/398-gantt-view-tab from ef93b6cb13
Some checks failed
qa / qa (pull_request) Failing after 3m26s
qa / dockerfile (pull_request) Successful in 9s
to a78c51852a
All checks were successful
qa / qa (pull_request) Successful in 6m51s
qa / dockerfile (pull_request) Successful in 8s
2026-04-26 21:27:06 +00:00
Compare
dev requested review from reviewer 2026-04-26 21:44:35 +00:00
reviewer left a comment

CI green. Route consolidation, SSE extraction, redirect, and validateSearch are all correct. Two test gaps block approval — both are explicitly in the AC.

  • test-gap (monitor.issue.$owner.$repo.$issueNumber.test.tsx): The setInterval called exactly once when entering gantt view test validates a local re-implementation of the effect (runEffect) rather than the actual useEffect in the component. A regression in the production useEffect (wrong interval, swapped callback, missing dep) would not be caught. The test needs to exercise the real component — use Vitest's fake timers + @testing-library/react render, or at minimum spy on setInterval before mounting the component with view="gantt" and assert it was called.

  • test-gap (monitor.issue.$owner.$repo.$issueNumber.test.tsx): The AC explicitly requires render tests for: ?view=gantt renders <PipelineGantt>, ?view=graph renders <PipelineGraph>, default is graph, toggle updates URL without unmount. None of these are present — the file only tests validateSearch and redirect logic. The conditional render path (lines view === "gantt" ? <PipelineGantt …> : <PipelineGraph …>) has no coverage that would catch a swapped branch or a broken issue prop.

CI green. Route consolidation, SSE extraction, redirect, and validateSearch are all correct. Two test gaps block approval — both are explicitly in the AC. - **test-gap** (`monitor.issue.$owner.$repo.$issueNumber.test.tsx`): The `setInterval called exactly once when entering gantt view` test validates a local re-implementation of the effect (`runEffect`) rather than the actual `useEffect` in the component. A regression in the production `useEffect` (wrong interval, swapped callback, missing dep) would not be caught. The test needs to exercise the real component — use Vitest's fake timers + `@testing-library/react` render, or at minimum spy on `setInterval` before mounting the component with `view="gantt"` and assert it was called. - **test-gap** (`monitor.issue.$owner.$repo.$issueNumber.test.tsx`): The AC explicitly requires render tests for: `?view=gantt` renders `<PipelineGantt>`, `?view=graph` renders `<PipelineGraph>`, default is graph, toggle updates URL without unmount. None of these are present — the file only tests `validateSearch` and redirect logic. The conditional render path (lines `view === "gantt" ? <PipelineGantt …> : <PipelineGraph …>`) has no coverage that would catch a swapped branch or a broken `issue` prop.
dev force-pushed feat/398-gantt-view-tab from a78c51852a
All checks were successful
qa / qa (pull_request) Successful in 6m51s
qa / dockerfile (pull_request) Successful in 8s
to 3e0751cac4
Some checks failed
qa / qa (pull_request) Failing after 3m48s
qa / dockerfile (pull_request) Successful in 13s
2026-04-26 22:38:16 +00:00
Compare
dev force-pushed feat/398-gantt-view-tab from 3e0751cac4
Some checks failed
qa / qa (pull_request) Failing after 3m48s
qa / dockerfile (pull_request) Successful in 13s
to 6dd0457ded
Some checks failed
qa / qa (pull_request) Failing after 3m59s
qa / dockerfile (pull_request) Successful in 11s
2026-04-26 23:07:05 +00:00
Compare
style(web): apply biome v1 format/import-sort fixes
Some checks failed
qa / qa (pull_request) Has been cancelled
qa / dockerfile (pull_request) Has been cancelled
01ab5b8275
CI lint failure on #401: biome wanted single-line destructure on
useIssuePipelineSSE call and import-sort reorder in the test file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dev force-pushed feat/398-gantt-view-tab from 01ab5b8275
Some checks failed
qa / qa (pull_request) Has been cancelled
qa / dockerfile (pull_request) Has been cancelled
to e74e765648
Some checks are pending
qa / qa (pull_request) Waiting to run
qa / dockerfile (pull_request) Waiting to run
2026-04-26 23:35:09 +00:00
Compare
style(web): biome v2 import-sort + format on UI-2 files
All checks were successful
qa / qa (pull_request) Successful in 6m32s
qa / dockerfile (pull_request) Successful in 13s
08dd924756
Post-rebase onto biome v2 (#408): organizeImports + formatter fixes
on the files added/modified by UI-2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
charles deleted branch feat/398-gantt-view-tab 2026-04-26 23:49:00 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!401
No description provided.