feat(tracker): Gantt — #4 visual polish + UX refinement#10856
Draft
MichaelUray wants to merge 248 commits into
Draft
feat(tracker): Gantt — #4 visual polish + UX refinement#10856MichaelUray wants to merge 248 commits into
MichaelUray wants to merge 248 commits into
Conversation
Schema-only foundation for the upcoming Gantt-chart view in tracker. No UI in this PR. Changes: - Issue.startDate: Timestamp | null (interface + IssueDraft + @prop with @Index) - Milestone.startDate: Timestamp | null (interface + @prop, reusing the existing tracker.string.StartDate IntlString) - New DependencyKind type ('finish-to-start' | 'start-to-start' | 'finish-to-finish' | 'start-to-finish') - New IssueRelation AttachedDoc class with kind: DependencyKind, signed lag: number — registered in models/tracker via TIssueRelation - 7 new IntlString keys: IssueStartDate, GanttDependency, GanttDependency{FinishToStart,StartToStart,FinishToFinish,StartToFinish}, GanttLag — all 13 locales updated - Cross-plugin literal updates in importer + github sync to satisfy the new required Issue.startDate / Milestone.startDate fields: - packages/importer/src/importer/importer.ts: AttachedData<Issue> literal - services/github/pod-github/src/sync/issueBase.ts: 'startDate' added to GithubIssueData Omit list (github sync does not own scheduling) - services/github/pod-github/src/sync/issues.ts + pullrequests.ts: AttachedData<Issue|GithubPullRequest> literals Out of scope (deferred to follow-up PRs): - UI for Gantt view, drag/resize, dependency editor, critical path - blockedBy → IssueRelation migration (ships atomically with the writer redirect in the dependency-UI PR) - LinkIssues permission (tracker uses forbid-style permissions; needs maintainer discussion) - Activity-feed wiring for IssueRelation (needs a producer to test against) - IssueTemplate.startDate (template propagation semantics undecided) Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
3 tests covering migrateAddStartDate: - writes startDate=null to Issues in DOMAIN_TASK with the right filter - writes startDate=null to Milestones in DOMAIN_TRACKER with the right filter - issues exactly two update calls (one per class) Follows the MigrationClient mock pattern from models/chat/src/__tests__/migration.test.ts. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…tion Backfills startDate=null on existing Issues (DOMAIN_TASK) and Milestones (DOMAIN_TRACKER) so the new schema field has a defined value on every pre-existing document. Idempotent via the standard tryMigrate state-key mechanism (state: 'gantt-add-startdate'). Verified domain choices against existing migration helpers: - migrateIdentifiers / passIdentifierToParentInfo use DOMAIN_TASK for Issues (lines 145, 161 in this file). - TMilestone @model decorator confirms DOMAIN_TRACKER for Milestones (models/tracker/src/types.ts:372). Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…ghten typing UI changes (so the new schema fields are actually editable, in chronological order Start → Due/Target): - New StartDateEditor.svelte (mirrors DueDateEditor.svelte for startDate) - ControlPanel: render Start Date row above Due Date row in the issue side panel; both always-visible (no `!== null` guard) so users can set them on issues that don't have a date yet - NewMilestone form: Start Date input above Target Date input - Milestone list view: Start Date column before Target Date column - TIssueRelation: tighten interface to `extends AttachedDoc<Issue, 'relations'>` so attachedTo + collection are statically typed. The model class re-declares `collection: 'relations'` to match the narrower base. - Drop 4 unused Dependency-kind IntlString keys (FinishToFinish, FinishToStart, StartToFinish, StartToStart) — they had no consumer in PR 1; will be re-introduced in PR 4 (dependency editor). - Simplify migration.ts comments — drop ageing line-references. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The DocAttributeBar side panel sorts attributes by attr.rank ?? toRank(_id) (see plugins/view-resources/src/components/ClassAttributeBar.svelte:42-47), so without explicit ranks the visible order on a Milestone was hash-based (startDate before Status, breaking the chronological flow the user expects). Set ranks so the side panel renders Status → Start date → Target date. Comments and attachments stay where they are (they're collections, filtered out of the attribute panel by categorizeFields). Issues are unaffected — the Issue side panel is the custom ControlPanel.svelte which renders Start date / Due date in explicit slots (see PR 1's UI commit). Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…body in chronological order
The right-side DocAttributeBar sorts attributes by attr.rank ?? toRank(_id),
giving startDate before status (toRank('startDate') < toRank('status')
lexicographically). Setting an explicit rank via @prop's third arg did not
propagate through the workspace upgrade for existing Attribute documents
in the model TX log — the rank made it into the bundled txes but the
existing Attribute creation TXes are not replaced on upgrade-workspace.
Pivot: render Status, Start date, Target date in the EditMilestone body
in explicit chronological order, and add 'status', 'startDate', 'targetDate'
to ignoreKeys so they don't appear duplicated in the side panel. This
mirrors how Issue's ControlPanel.svelte handles its date fields.
Reverts the no-op @prop rank attempt.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…aces The fulltext-pod's compiled model version (baked into bundle/model.json via common/scripts/version.txt at build time) lags whenever the workspaces have been migrated to a newer patch but the pod was not rebuilt. In that state the indexer rejects every incoming Tx with a `wrong version` warning, new issues silently fail to land in Elasticsearch, and search returns empty results for any document created after the migration. Bumping `version.txt` aligns the compiled model with the workspaces. All future builds (front, transactor, workspace, tool, fulltext) will emit 0.7.423, the indexer accepts the Tx stream again, and the deferred backlog gets consumed automatically — no manual reindex needed. This commit is the build-side companion to the schema migration in this same PR. Without it the fulltext-pod cannot consume the migrated workspace's Tx events. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…reactive queries PR 2 read-only Gantt is now end-to-end functional: - Two reactive queries (issues, milestones) - buildLayout(issues) -> rows with depth + isSummary - createTimeScale(zoom, dateRange.from) -> date<->px math - Summary ranges computed per parent issue from children's date span - Local zoom state (Day/Week/Month/Quarter) - no ViewletPreference plumbing - Horizontal scroll via canvas-scroller; vertical scroll moves Sidebar via translate Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- viewlets.ts: register IssueGantt AFTER IssueKanban so List stays default - viewlets.ts: drop showColorsViewOption (canvas does not honour it yet) - GanttBar.svelte: normalise reversed startDate>dueDate ranges UX: - GanttSidebar adds Title column with sticky two-column header - Sticky time-scale header decoupled from milestone strip (layout fix) - Per-row jump-to-bar arrow (Plane-style) when bar is offscreen - ResizeObserver initialises viewport on mount and on resize Milestones as Gantt rows + collapse: - Milestones group their issues as nested children (depth+1) - Collapsible toggle per parent row, local collapsedIds Set - Milestone summary bar uses existing GanttBar with aggregated range Icon: - Register tracker.icon.Gantt to #timeline svg (Gantt pictogram) Tests: 25/25 jest pass; svelte-check 0 errors. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- Visible top row with [«] [Today] [»] | Day Week Month Quarter | ⚙ - Today scrolls to current date, prev/next page-scroll by 80% viewport - Settings popover toggles Issue-Code and Title columns Layout: - Bigger row height (28→36) and bar font (11→13px) for readability - Sidebar reworked into flex-column with separate clipped rows region so scrolled rows can never paint over the sticky header(layout fix) - Drag handle between sidebar and canvas (120–600px range) - ResizeObserver re-syncs viewport on drag/resize/zoom changes Interaction: - Vertical gridlines aligned to time-scale ticks (Plane-style) - Row hover highlights both sidebar and canvas, with rich HTML tooltip (issue title + start + due + duration) - Title click in sidebar dispatches openIssue → showPanel(EditIssue) - Double-click on canvas bar dispatches openIssue - Wheel forwarding from sidebar to canvas-scroller (vertical scroll works while hovering issue list) - Pointerdown + drag on empty canvas pans both axes - Jump-to-bar buttons now use the bar's true left-edge target Tests: 25/25 jest pass; svelte-check 0 errors. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
totalCanvasWidth (was viewport width), with viewBox in scroll-content coordinates. The sticky header lives in the same coordinate system as the canvas-stack so horizontal scroll no longer clips the time-axis. - showPanel uses tracker.component.EditIssue instead of the hardcoded string + 'as any' cast. - Removed unused GanttToolbar.svelte and GanttMilestoneFlag.svelte (dead files since toolbar moved into GanttView and milestone flags became rows). Toolbar: - Time-navigation cluster: ⏮ « Today » ⏭ + native date picker that jumps to a specific date. Replaces the lone Today button. Interaction polish: - Sidebar wheel forwarding now uses direct scrollTop/scrollLeft mutation with deltaMode scaling — same speed as native canvas scroll. - TodayMarker no longer hides when scrolled offscreen (SVG width handles clipping); milestone reference lines render unconditionally for the same reason. Tests: 25/25 jest pass; svelte-check 0 errors. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- Register two ToggleViewOptions on the Gantt viewlet: ganttShowIssueCode (default OFF) and ganttShowTitle (default ON). These show up in the standard Customize-View dropdown. - Drop the per-component settings popover from GanttView; sidebar column visibility now reads viewOptions directly. - Hover tooltip always surfaces the issue code (e.g. OSTRO-31), even when the issue-code column is hidden. - IntlStrings + en/de/es/fr/it/ja/pt/ru/zh/cs translations added. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Bug: .gantt-sidebar rendered at its natural height (≈ rows × 36px), and .sidebar-host had overflow:visible, so for many issues the sidebar visually overflowed gantt-body which in turn made gantt-body's scrollHeight balloon to the sidebar's natural height. The result was that scrolling over the sidebar appeared to scroll the page area instead of just the canvas. Fix: - .sidebar-host now overflow:hidden + height:100% + flex-column - .gantt-sidebar height:100% + flex:1 1 auto so it fills the host rather than stretching past it Verified: gantt-body scrollHeight == clientHeight, only .canvas-scroller has scrollable content. Wheel-forward over the sidebar moves canvas-scroller and the sidebar transform together. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…ticky) Replaces the dual-scroller architecture (sidebar + canvas as siblings, manual wheel-forwarding for the sidebar) with a single .gantt-scroller that wraps both columns in a CSS grid. Sidebar uses position:sticky left:0 so it stays at the left edge during horizontal scroll, while the time-axis header uses position:sticky top:0. Browser handles all wheel events natively at native speed. Why: the previous design rendered the sidebar at its natural height (rows × 36px), which could be much larger than the visible viewport. overflow:visible on the sidebar host let it bleed past gantt-body and made the page area appear to scroll. The wheel-forward hack only worked for synthetic events; in real browsers, wheel events over the sidebar either scrolled too slowly (deltaMode mismatch) or stopped firing. Layout (CSS grid, 2 rows × 3 cols): - (1,1) sticky top+left: corner with column titles - (1,2) sticky top: resize-corner (5px gutter) - (1,3) sticky top: time-axis header - (2,1) sticky left:0: GanttSidebar rows - (2,2) sticky left:Wpx: vertical resize-handle - (2,3) normal: GanttCanvas SVG overflow:scroll on .gantt-scroller forces both scrollbars to always render — the user explicitly asked for visible scrollbars (Plane parity). GanttSidebar drops its scrollTop prop and the transform-based row positioning; rows now flow naturally inside the scroll container. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The standard NewIssueHeader is rendered by the Tracker shell outside the viewlet. Inside the Gantt view this looked like the action was missing. Add a prominent + New issue button in the gantt-toolbar that opens CreateIssue with the current project space pre-selected, matching the behaviour of NewIssueHeader. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- Remove "+ New issue" button from GanttView. PR2 stays read-only; issue creation lives in PR3 with edit/drag. - Localize all visible Gantt strings via use:tooltip + Label, no more hardcoded English: Today, Jump to start/end, Previous/Next period, Jump to date, Issue, Title, Milestone, Start/Target/Due, Expand, Collapse, Scroll left/right to bar. - Add 9 new IntlStrings (GanttToday, GanttJumpToStart, GanttJumpToEnd, GanttJumpToDate, GanttPreviousPeriod, GanttNextPeriod, GanttScrollLeftToBar, GanttScrollRightToBar, GanttExpand, GanttCollapse) on top of the existing GanttShowIssueCode and GanttShowTitle. - Restore all 13 locale files to their PR1 baseline formatting and add only the additive Gantt entries (~17 new lines per locale, English fallback). ko.json, pt-br.json, tr.json now ship the same Gantt keys as the rest. Tests: tracker-resources svelte-check 0 errors; tracker-assets locale test pass. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
User-requested UX consolidation: the same compact "+ New issue" button should appear above every Tracker viewlet (List, Kanban, Gantt) instead of the bulky text+dropdown HeaderButton. - Replace HeaderButton with two stacked Button instances: * primary blue circular icon-only IconAdd (newIssue / newProject) * regular grey circular IconDropdown with secondary actions popup - Always visible regardless of viewlet (kind of a tab-bar shortcut) - showTooltip surfaces the keybinding from the existing tracker action - Draft indicator stays as small dot on top-right of the plus button Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
When the GanttCanvas SVG is serialized into a standalone .svg file (e.g. via XMLSerializer in export paths) the resulting blob must declare the SVG namespace or browsers/PDF renderers reject it. The in-DOM HTML parser tolerates the missing attribute, but external consumers do not. exporter.ts already patches xmlns onto a clone before serialization; adding it on the source removes that fallback dependency and makes any direct outerHTML/XMLSerializer dump valid standalone SVG. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…ariables Hardcoded hex values (#dc2626, #10b981, #f59e0b, #3b82f6, #94a3b8, …) in GanttBar, GanttCanvas, StatusBadge, GanttDependencyArrow, GanttDependencyLayer, GanttConnectorDot, GanttSidebar, GanttSidebarColumn don't react to Huly's dark/light theme and would glare in dark mode. Map to existing theme vars: - red/critical/violated/overdue → --theme-state-negative-color - green/won status → --theme-state-positive-color - orange/active/warning → --theme-warning-color - blue/todo/primary → --theme-state-primary-color - grey/neutral/backlog/slack → --theme-state-regular-color - indigo connector dot keeps the existing --theme-state-info-color fallback pattern (no canonical var exists yet) Known limitation: ConfirmCascadePopup illustration colors and the export-renderer/exporter SVG output keep hex literals — the popup is a fixed-palette diagram, and exported SVG/PNG must be self-contained (theme vars wouldn't resolve outside Huly). Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…in Gantt mode
User-Report 2026-05-15: Im Gantt-Mode wird nur 'Configure Columns'
angezeigt (was Spalten fuer die Extended-Sidebar konfiguriert) aber
'Customize View' fehlt — und genau in 'Customize View' liegen die
Bar-Labels und anderen Gantt-relevanten ViewOptions, die der User
braucht.
Wurzel: v121.12 Refactor B hat das FALSCHE versteckt — der
ViewOptionsButton (mit Bar-Labels) wurde rausgenommen, aber genau der
sollte BLEIBEN. Mein Mental-Model zur Refactor-Zeit war invertiert.
Beide Buttons haben in Gantt-Mode echte Funktionen:
- 'Customize view' (sliders) → Bar-Labels + ganttQuickInfoOnClick +
ganttSidebarColumnsExtended +
ganttBarLabelLeft/Inside/Right etc.
- 'Configure columns' (eye) → Phase-3a Extended-Sidebar Spalten-
Konfiguration
Fix: showViewOptions-Prop entfernt, beide Buttons immer sichtbar.
Wording-Split (Customize view vs Configure columns) bleibt.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…o silence Firefox scroll-linked positioning warning Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…gure-button instances
User reported v121.12 Refactor B (Customize-View vs Configure-Columns split)
ist nicht durchgängig — die Anzeige stimmt in Listen- und Card-View
weiterhin nicht.
Wurzel: Es gibt DREI separate Components mit derselben 'ViewOptionsButton
plus Configure-ButtonIcon' Logik, aber Refactor B fixte nur EINE:
- view-resources/.../ViewletSettingButton.svelte (singular) ✅ v121.12
- view-resources/.../ViewletsSettingButton.svelte (plural) ❌ verbleibend
- card-resources/.../ViewSettingButton.svelte (Card-View) ❌ verbleibend
Die beiden verbleibenden Components zeigten ihren Configure-ButtonIcon noch
mit 'CustomizeView' Tooltip statt 'ConfigureColumns', d.h. Sub-Issue-Liste
(QueryIssuesList) + MeetingMinutes + VacancyApplications + Card-View
hatten weiterhin BEIDE Buttons mit demselben 'Customize View'-Tooltip.
Fix: beide auf view.string.ConfigureColumns umstellen — gleicher
IntlString-Key der bereits in v121.12 in plugins/view-assets/lang/{en,de}.json
+ 11 weitere Locales gepflegt wurde.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The platform Card.svelte routes X-click through an optional onCancel
prop and only falls back to dispatch('close') when onCancel is unset.
GanttSaveViewPopup was relying on the dispatch path with a wrapping
<Card on:close={...}> forwarder, which empirically did not close the
popup in v121.11 (user report). Wire onCancel explicitly so X-click
calls dispatch('close') directly on the popup component, bypassing
the Card→handler→re-dispatch chain that wasn't reaching PopupInstance.
OK-button continues to dispatch close{detail} from onSave so the
caller in GanttView.openSaveViewPopup() still receives the form
payload synchronously before Card's tail-close fires.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
… + numeric days-input
Replace the legacy Day/Week/Month/Quarter button row in the Gantt
toolbar-center with a single DropdownLabelsIntl + a numeric EditBox
showing the currently visible day-count.
- New helper lib/zoom-dropdown.ts with three pure functions:
- dropdownSelectionForPxPerDay() maps userPxPerDay+zoom to one of
day/week/month/quarter/custom with an EPSILON_PPD tolerance.
- visibleDaysFromPxPerDay() / pxPerDayFromVisibleDays() are mutual
inverses around the viewport width; defensive against NaN/zero.
- Custom is never directly selectable from the dropdown: the entry is
only inserted while wheel-zoom has placed userPxPerDay off-preset, so
clicking the dropdown still reflects the active state but does not
offer Custom as a no-op pick.
- Editing the days-input drives userPxPerDay = width/days, which flips
the dropdown to Custom (unless the value happens to land on a preset).
- Keyboard shortcuts D/W/M/Q and Ctrl+Wheel keep their existing wiring.
IntlStrings: GanttZoomDay/Week/Month/Quarter/Custom + GanttZoomLabel +
GanttZoomVisibleDays (plural) + GanttZoomDaysSuffix/Aria, in EN and DE.
Tests: tracker-resources jest 633 -> 645 (12 new in zoom-dropdown).
svelte-check: 0 errors.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…etSettingButton
v121.16 reverted v121.12 #B's only call-site override, leaving the prop
with default true and no remaining caller. Drop the prop and the
{#if showViewOptions} guard; ViewOptionsButton now renders whenever the
viewlet supplies viewOptions, matching observable behaviour since v121.16.
Tracked in 2026-05-15 regression audit, item Bug-1.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…s tooltips Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…nfo open-editor button iOS/Android intercept double-tap for system zoom, which collides with the gantt 'dblclick → open full editor' shortcut and makes opening issues unreliable on phones. Phone layout now: - drops the dblclick handler on bar-wrap groups (still active on tablet/desktop); - force-enables ganttQuickInfoOnClick regardless of the user's view option so the quick-info popover is always reachable via single tap; - routes the popover's existing 'Open full editor' button through the same showPanel(EditIssue) call the desktop dblclick uses. Result: mobile users get a deterministic single-tap → quick-info → 'Open full editor' path with no system-zoom interference, while desktop/tablet behaviour is unchanged. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…s handler An external code review flagged GanttBar's tabindex="-1" + svelte-ignore as a potential upstream-review red flag. The behaviour is intentional: focus management is centralised in GanttView.onKey (Tab/Shift-Tab cycles scheduledIssues in visual order, Arrows shift focused bar). Native per-rect Tab navigation would cycle in DOM order which doesn't match chart order, so we route everything through moveFocus() instead. Spell that contract out in a block comment above the non-summary bar <rect>, mirroring the existing summary-path comment, with a pointer to the canonical handler location in GanttView.svelte. Pure documentation, no runtime change. Tabindex="0" + native browser focus order remains a possible follow-up if upstream requests it; leaving as Option-A (documentation) per v121.19 task scope. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Rebase --onto upstream/develop introduced conflicts that were resolved by keeping HEAD versions, losing content from later commits in the branch history. Fixed: - Restore all gantt/*.svelte and lib/*.ts to pre-rebase-backup state (upstream/develop does not touch the gantt directory) - Remove duplicate function bodies in scheduler.ts and drag-controller.ts - Restore 71 missing ViewOptions in models/tracker/src/viewlets.ts - Add missing @hcengineering/notification dep to plugins/tracker/package.json - Restore missing IntlStrings in tracker plugin index.ts (Deadline, BarLabel*, GanttBarLabel*, GanttQuickInfoOnClick, GanttSavedView*, GanttMobile*, GanttExport*, GanttFullscreen, GanttMoreActions, QuickInfoOpenFullEditor, DependencyShifted*) - Restore 27 missing en/de lang strings (GanttSavedView*, GanttMobile*, GanttExport*, GanttFullscreen, GanttMoreActions) - Fix trackerModel -> tracker in models/tracker/src/migration.ts - Restore 31 missing strings in tracker-resources/src/plugin.ts - Add DeadlineEditor usage back in ControlPanel.svelte Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…ly correct cast) Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…te-check pass Add missing pure-logic modules (bulk-boundary, bulk-selection, dependency-shift-send, dependency-shift-notify, flash-store, gantt-view-options, saved-views, tree-expand-store, undo-manager, y-viewport) that GanttView.svelte imports. Fix dependency-router.ts to include full ArrowVisibility/YBounds/clippedEndpointPx exports. Add multiSelectedIssueIds + layoutMode props to GanttCanvas. Add hasDeadline/isOverdue import to GanttCanvas. Fix GanttBar resize handles to use on:pointerdown instead of undefined on:mousedown. Add coDrag field to DragEvent mousedown-bar and DragState dragging-body types. Add ShiftedIssuePayload + DependencyShiftedNotification interfaces to tracker plugin. Add GanttExpandAll/GanttCollapseAll/GanttTreeBreadcrumb i18n strings. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
At low pixels-per-day densities (month=4, quarter=1.5) the chart fits in the viewport with no horizontal overflow, so the custom h-scrollbar element is not rendered. The wheel-zoom handler early-returned on the missing element, leaving Ctrl+Wheel a no-op in those zoom levels. Fall back to scrollerEl for the cursor-anchor bounding box and skip the scrollLeft-anchor step entirely when there is no overflow (nothing to scroll). Wheel-zoom now works at every density. Also introduce adaptiveWheelFactor: 0.012 for ppd<4 (month/quarter), 0.006 for ppd>=4 (week/day). Exponential math is multiplicatively adaptive, but in the low-density bands the absolute pixel delta per notch is small enough that users perceive the same exp step as slower than at high density. The bumped factor restores subjectively equal responsiveness across all four presets. Five new unit tests cover the factor boundaries and the adaptive-vs-fixed contrast at ppd=1.5 and ppd=14. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…wlet renders its own The shared View-Options popup renders a Group-by + Order-by dropdown pair plus a list of viewlet-specific toggles (bar labels, confirm dialogs, etc.). In Gantt mode the toolbar already provides its own dedicated group-by and order-by dropdowns wired to the Gantt-internal layout, so the popup's pair is visually duplicated and not wired to anything — users see the same control twice and changing the popup version has no effect. Add a hideGroupingAndOrdering prop that propagates from ViewletSettingButton → ViewOptionsButton → ViewOptions. When true the popup skips its grouping and ordering rows (plus the separator before the toggles) and renders only the 'other' toggles, which remain wired. IssuesView passes hideGroupingAndOrdering=isGanttMode so list mode keeps the previous behaviour and Gantt mode shows only the useful toggles. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…line comments Strips internal-tracking phrases from source-code comments: Tier-N Item M, Tier-N #M, v121.NN, per Tier-N spec, plus leftover internal review markers mentions. The comments themselves are preserved — only the attribution labels are dropped so the noted constraint or hidden invariant survives. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…idebar The Extended Sidebar toggle (ganttSidebarColumnsExtended) used to ship a hardcoded identifier/title/predecessors/slack quartet with no UI to add the other supported columns. The Configure-Columns button is generic viewlet-config and has no effect on the Gantt sidebar. Add 8 per-column ViewOption toggles under the Extended Sidebar toggle in the Customize-View popup: Status / Priority / Assignee / Estimation / StartDate / DueDate / Deadline / Progress. Each toggle appends its column to the default set; the order matches the natural reading order on the sidebar (status..progress..predecessors..slack). Toggles are collapsed when the Extended Sidebar toggle is off so the popup does not grow indefinitely. Also raises the sidebar size limits: total width 600→1200 px, per-column width cap 400→600 px, so the extra columns actually have room to render. Finally adds a showConfigureColumns prop on ViewletSettingButton (default true). IssuesView passes false in Gantt mode so the configure-columns icon no longer renders there — it had no effect on the Gantt sidebar anyway. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
After the PR3a refactor dropped the duplicate \« \» date-nav buttons from the corner-range, the remaining tree-toggle buttons (collapse-all, expand-all) still inherited the old `justify-content: center` and ended up visually floating in the middle of the corner cell. Switch to `flex-start` so the buttons hug the left edge of the sidebar grid, matching the alignment of the column-toggle chevrons in the rows below. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
This was referenced May 18, 2026
|
Connected to Huly®: UBERF-16445 |
This was referenced May 18, 2026
Draft
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
Visual + UX polish across the Gantt view: theme-variable colours instead of hex, sidebar tree glyphs become Chevron icons, the corner cell hosts Expand-all / Collapse-all (left-aligned), priority filter shows Urgent / High / Medium / Low labels, continuous Ctrl+wheel zoom, mobile-friendly long-press routing, data-driven PNG/PDF export with full sidebar + chart, and a dedicated
Customize-ViewvsConfigure-Columnssplit with distinct tooltips.Also lands the Estimation row in the bar quick-info popover, the
GanttSaveViewPopupmodal scaffold (Save-View UI shell — the persistence layer lands in PR5), and theIssueRelationactivity feed so dependency add/remove/update events show in the standard activity stream.What's in this PR (+105 incremental commits)
Look & feel
ChevronRight/ChevronDowniconsaria-labelsviatranslateCB; addaria-label+ title to date-nav buttonsxmlnsto canvas SVG rootToolbar & view-option UX
Customize-View+Configure-Columnsbuttons in Gantt mode, with split tooltipsCustomize-Viewbuttons in Gantt mode; viewlet renders its ownFilterBaras single sourceInteraction
GanttBar— pointer-only events + long-press routing (touch friendliness)layoutMode+ pinch-zoom intoGanttViewtranslateXsync viarAF(silences Firefox scroll-linked positioning warning)Sidebar extension
nameLookupmap through group-by helpersSave-View scaffold
GanttSaveViewPopupmodal — name + fix-window + public toggles (persistence in PR5)onCancelExport
Activity feed
IssueRelationadd/remove/update activity viewletsRelationActivityPresenterfor activity feed renderingIssueRelationremove activity docsremoveCollectionfor relation deletion so activity feed renders detaili18n
Stack overview
…pr1-schema…pr2-readonly…pr3a-edit…pr3b-deps-cascade-cp…pr4-polish…pr5-tier2…pr6-tier3-virtualization…pr7-tier4MichaelUray:feat/gantt-sectionMarked as draft to signal stack dependency on PR1 → PR3b.
How to review
→ Fork compare: PR3b...PR4 — 105 commits, 118 files
This is largely incremental UX work — most commits are small and self-explanatory. Largest single concern is the sidebar-sort cycle + comparators, which has its own test fixture.
Testing
DCO
All commits are
Signed-off-by.