feat(#221,#229): Timeline scale/year view, allocation editing, CSV TemplateSize, Gantt UX polish#231
Merged
NickMonrad merged 15 commits intomainfrom Apr 29, 2026
Merged
Conversation
…and on import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…g levels Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… example rows Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… epic - Scheduler: after Kahn's topological sort, features with unresolvable inDegrees (stuck in cycles) are now scheduled at a fallback start week derived from their epic's position in the sequential chain. Previously they were silently dropped, causing 222/228 features to never appear on the timeline. - CSV import: FeatureDependsOn name lookup is now scoped to the current row's epic instead of searching all features in the project. This prevents cross-epic name collisions when multiple epics share identical feature names (e.g. every epic has 'Infrastructure & Environment'). Previously, the last feature with that name (across all epics) was matched, creating backward cross-epic dependencies that caused cycles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Export: cross-epic deps now written as 'EpicName: FeatureName' so they
round-trip correctly on re-import
- Import staging: validates qualified 'EpicName: FeatureName' entries
against the known epic/feature pairs in the import
- Import commit: resolves 'EpicName: FeatureName' via cross-epic lookup;
plain feature names continue to resolve within the same epic only
- Empty CSV template: updated description column for FeatureDependsOn to
document both formats; added example rows showing same-epic dep
('Authentication') and cross-epic dep ('Platform Setup: Authentication')
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After a successful CSV import, the epicDeps and feature-deps React Query caches were not invalidated, so newly imported dependencies were invisible until a full page reload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move feature mode, schedule mode, and dep chips to a second line under the epic title. Bump EPIC_ROW_H from 36 to 52px to fit. Title now has full label width without truncation competition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove max-w-7xl constraint on TimelinePage main wrapper so the Gantt chart stretches to fill the full viewport width - Widen LABEL_W from 300 to 380px for longer epic names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a 12px mirror div above the GanttChart that scrolls in sync with the main chart and histogram scrollbars so users can scroll horizontally from the top without scrolling to the bottom first. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Last 4 epics now open the dependency dropdown upward (bottom-full) so it isn't hidden behind the resource demand histogram. Also adds max-h-64 + overflow-y-auto so large epic lists scroll within the dropdown instead of overflowing off-screen. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Dropdown now has an auto-focused search input at the top that filters the epic list by name. Search resets each time the picker is opened. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Export was hardcoded to COL_W=64 (week scale) regardless of the active Week/Month/Quarter toggle, causing excess whitespace in month/quarter exports. Now uses ganttColW (scale-aware) and LABEL_W. Top mirror scrollbar width also corrected to use LABEL_W constant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eSize, Gantt UX polish - Add week/month/quarter/year scale toggle to Timeline Gantt - Year scale: H1/H2 top row, Q1-Q4 bottom row, 8px/week column width - TemplateSize column in backlog CSV — auto-expand template tasks on import (XS/S/M/L/XL) - Cross-epic FeatureDependsOn in CSV import via qualified format (Epic::Feature) - Allocation mode (T&M/Full Project/Timeline) and % editing in Resource Counts panel - Start/end week inputs for Timeline allocation mode named resources - Expand All / Collapse All toggle in Gantt label panel header - Dep picker search filter on epic dependency dropdown - Top mirror scrollbar synced with Gantt horizontal scroll - Full-width Gantt layout (removes empty side margins) - Onboarding/buffer zone date calculation fix (computeDates now applies onboardingWeeks offset) - Adaptive zone labels at compressed scales (Onboarding / Onbrd / O) - Fix label column width alignment (LABEL_W=380 applied to ResourceHistogram and NamedResourcesPanel) - Fix histogram bars invisible at year scale (proportional inset instead of hardcoded 8px) - Fix auto-reschedule on resource changes — only fires on first run (entries.length === 0) - Fix expand/collapse state reset on timeline refetch — use knownEpicIds ref to track seen epics - Fix named resource T&M histogram showing full pool demand per row — divide by person count - PNG export and top scrollbar width respect active scale Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #221 (Timeline scale toggle) and #229 (CSV TemplateSize). Also ships a large set of Timeline UX improvements made during the same session.
Related issues
Closes #221
Closes #229
Changes
Core issues
TemplateSize=S(XS/S/M/L/XL) auto-expands linked template tasks using that tier's hoursEpicName::FeatureNameresolves dependencies across epic boundariesTimeline UX
Bug fixes
computeDates()now appliesonboardingWeeksoffset so tooltip dates and zone positions are correct at all scalesOnboarding→Onbrd→O) to fit within the zone rectLABEL_W=380now consistently applied to ResourceHistogram and NamedResourcesPanel (was hardcoded 300, causing misalignment)colW(min 1px, max 4px) instead of hardcoded 8px which produced zero-width bars at year scaleentries.length === 0); resource mutations set a stale banner insteadknownEpicIdsref (tracks all ever-seen epic IDs) so collapsing all is preserved across mutations. Previous fix usingexpandedEpics.size === 0check failed because Collapse All empties the set, making all epics look newcolW(was always using week-scale width)E2E Tests
No new E2E tests in this PR — the existing timeline and backlog specs cover the core flows. Scale toggle and CSV TemplateSize are covered by manual verification.
Tests added/modified: none
E2E test results: existing suite unmodified; server tests 142/142 ✅
Testing
npm testpasses in/server(142 tests)npx tsc --noEmitpasses in/servernpx tsc --noEmitpasses in/clientnpm run test:e2e— not run (no new Playwright tests added)e2e/TESTS.md— no changes neededNotes
knownEpicIdsref approach is the correct fix for the expand/collapse reset bug. An earlier attempt usingepicInitDoneref still failed because the merge logic compared againstexpandedEpics(empty after collapse) not against the set of known IDs.