Skip to content

feat(#233): timeline UX rework#242

Open
NickMonrad wants to merge 12 commits into
mainfrom
feature/timeline-ux-rework
Open

feat(#233): timeline UX rework#242
NickMonrad wants to merge 12 commits into
mainfrom
feature/timeline-ux-rework

Conversation

@NickMonrad

@NickMonrad NickMonrad commented May 7, 2026

Copy link
Copy Markdown
Owner

Summary

Reworks the timeline experience and related optimiser flows, including new planning drawers, scheduling logic, and supporting timeline/resource UI updates.

Related issue

Closes #233

Changes

  • Rework timeline/Gantt UX and supporting client-side planning flows
  • Add optimiser and scheduler backend/frontend changes used by the new timeline workflows
  • Stabilise planner demand allocation, named-resource assignment visibility, and resource profile exports
  • Address PR review fixes and align Playwright coverage with the renamed Timeline UX

E2E Tests

Tests added/modified:

  • e2e/tests/timeline.spec.ts - updated Timeline and Starting Team Finder selectors/copy for the current UX
  • e2e/tests/gantt.spec.ts - updated Quick schedule flow selectors
  • e2e/tests/helpers.ts - added shared quickSchedule() and openStartingTeamFinder() helpers
  • e2e/TESTS.md - updated test inventory/documentation for the renamed Timeline UX

E2E test results (npm run test:e2e):

Targeted local rerun of the affected Timeline/Gantt specs was partially blocked by local auth rate limiting.
PR CI rerun is the source of truth for this selector update.

Testing

  • npm test passes in /server
  • npx tsc --noEmit passes in /server
  • npx tsc --noEmit passes in /client
  • npm run test:e2e passes (Playwright - requires dev servers on :3001 and :5173)
  • e2e/TESTS.md updated to reflect any test additions or changes

Manual testing

  • Expired session recovery: log in, expire or clear the token, refresh, and confirm the app returns cleanly to Login instead of getting stuck in 401/reload loops.
  • Reset password: complete the reset flow, then immediately log in with the new password and confirm rate limiting does not block the first successful login.
  • Timeline named-resource histogram: open the affected timeline and confirm named resources now show allocation beyond week 1 and match the visible demand span.
  • Timeline -> Resource Profile / Commercial sync: change allocation mode, counts, or named-resource settings on Timeline, then navigate straight to Resource Profile and Commercial and confirm the new values appear without stale data.
  • Resource Profile allocation consistency: for roles such as Senior Engineer - Data, AI & IoT, confirm row-level allocated days and timing agree with the per-person actual allocation and histogram coverage.
  • Parallel warning edge case: recheck the project that previously showed 19.5 needed, 19.5 available and confirm that false-positive warning is gone, while a real over-capacity case still warns.
  • Capacity-plan exit: switch a resource type out of CAPACITY_PLAN into manual/timeline-style editing and confirm both the resource type and its named resources transition consistently with no mixed-mode leftovers.

Notes

  • Review findings were addressed in follow-up commits on this branch.
  • Latest CI-triggering fix updates Playwright selectors to the current Timeline wording: Quick schedule and Starting Team Finder.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@NickMonrad

Copy link
Copy Markdown
Owner Author

Review findings ordered by fix priority:

  1. P1 — cross-project resource mutation in optimiser apply
    server/src/routes/optimiser.ts:147-163 updates resourceType by bare { id: rtId } and namedResource.updateMany({ where: { resourceTypeId: rtId } }) after only checking ownedProject(projectId) for the URL project. Because ResourceType / NamedResource IDs are global rather than project-scoped (server/prisma/schema.prisma:91-113, 347-363), a user who knows another project's resource type ID can mutate that other project's counts/start weeks.

  2. P1 — dependency arrows are painted underneath the chart background
    client/src/components/timeline/GanttChart.tsx:351-366 renders dependency arrows before the opaque background <rect>, so SVG paint order hides them entirely. On main, the arrows render after the background.

  3. P1 — Team Finder settings reset while the drawer is open
    client/src/components/timeline/TimelineOptimiserDrawer.tsx:353-380 makes resetSettings depend on resourceTypes, and the open-state effect depends on resetSettings. client/src/pages/TimelinePage.tsx:467-472 passes a fresh mapped resourceTypes array every render, so parent re-renders while open reset in-progress Team Finder settings.

  4. P1 — Squad Planner edits are overwritten while the drawer is open
    client/src/components/timeline/SquadPlannerDrawer.tsx:217-247 has the same unstable resourceTypes dependency problem. Re-renders retrigger the restore effect and can reload localStorage over unsaved in-progress edits.

  5. P2 — invalid count ranges can produce divide-by-zero scheduling output
    server/src/routes/optimiser.ts:327-333 accepts caller-supplied countRanges without enforcing min >= 1. server/src/lib/scheduler.ts:420-421 then divides by count, so min: 0 can propagate Infinity / NaN through scenario scoring.

  6. P2 — over-allocation dot becomes stale while dragging
    client/src/components/timeline/GanttBar.tsx:111-117,135-137 determines dot visibility from committed entry.startWeek but positions it from live effectiveStart. During drag, the indicator can show the wrong state.

  7. P2 — named-resource bars can overflow the chart with onboarding weeks
    client/src/pages/TimelinePage.tsx:108,182-199 defaults named-resource endWeek to totalWeeks - 1, then bar positioning also adds weekOffset. With onboarding weeks and no explicit end week, the bar extends past the chart width.

  8. P3 — duplicate epic-dependency query in schedule route
    server/src/routes/timeline.ts:478-481 and 549-552 fetch the same dependency set twice in one request. Low risk, but wasted DB work on every schedule call.

NickMonrad and others added 6 commits May 7, 2026 13:45
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NickMonrad and others added 2 commits May 29, 2026 10:30
- resourceTypes DELETE: scope deleteMany to projectId and 404 when no row
  matches, preventing cross-tenant resource type deletion (IDOR)
- timeline PUT /:featureId: verify the feature belongs to the owned project
  before upserting, preventing cross-tenant timeline overwrites (IDOR)
- namedResources POST/DELETE: wrap capacity-plan exit, create/delete and
  count re-sync in a single transaction to avoid count desync under
  concurrent requests

Adds cross-tenant 404 tests for the resourceTypes DELETE and timeline PUT
routes and updates mocks for the transactional named-resource flow.

Note: the IPv6 rate-limit hardening (ipKeyGenerator) is deferred — the
installed express-rate-limit@7.5.1 does not export that helper.

Co-authored-by: NickMonrad <NickMonrad@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resource Optimisation feature — find optimal resource counts and ramp-up dates for Timeline

1 participant