Skip to content

feat(tracker): Gantt — #2 read-only viewlet#10853

Draft
MichaelUray wants to merge 40 commits into
hcengineering:developfrom
MichaelUray:feat/gantt-upstream-pr2-readonly
Draft

feat(tracker): Gantt — #2 read-only viewlet#10853
MichaelUray wants to merge 40 commits into
hcengineering:developfrom
MichaelUray:feat/gantt-upstream-pr2-readonly

Conversation

@MichaelUray
Copy link
Copy Markdown

@MichaelUray MichaelUray commented May 18, 2026

Summary

Read-only Gantt viewlet for Tracker: a horizontally-scrolling time-canvas with a synced sidebar that lists the issues in the current project / filter, plus a zoom toolbar (Day / Week / Month / Quarter), a "Today" jump, page-scroll buttons, and customizable sidebar columns. No editing yet — drag/resize comes in PR3a, dependencies in PR3b.

The viewlet registers after Kanban so List stays the project default. All Gantt logic lives behind a viewlet.IssueGantt registration; no existing viewlet is mutated.

Supersedes #10852 (closed). The original head SHA was 7b197a93f; the branch has since been rebased onto the current PR1 tip and DCO-cleaned.

What's in this PR (+33 incremental commits)

  • feat(tracker) register viewlet.IssueGantt (placeholder) → wired with reactive queries
  • Gantt library modules — time-scale, layout, types, types-tested with Jest
  • Svelte components — GanttCanvas, GanttHeader, GanttSidebar, GanttBar, GanttTodayMarker, GanttMilestoneFlag, GanttToolbar
  • feat(tracker) register startDate + dueDate as Issue filters
  • Hardened scrollbars (sticky-bottom horizontal scrollbar, Plane-style)
  • Status-badge column + ganttShowStatus toggle
  • Inline-add row in the Gantt sidebar
  • "+ New issue" button in the Gantt toolbar (wired into the standard NewIssue flow)
  • i18n keys for the new Gantt UI strings (en + de)

Stack overview

# Branch Scope Status
PR1 feat/gantt-upstream-pr1-schema schema + version bump open
PR2 feat/gantt-upstream-pr2-readonly this PR — read-only viewlet draft
PR3a feat/gantt-upstream-pr3a-edit editable viewlet draft
PR3b feat/gantt-upstream-pr3b-deps-cascade-cp dependencies + cascade + critical path draft
PR4 feat/gantt-upstream-pr4-polish polish draft
PR5 feat/gantt-upstream-pr5-tier2 undo, saved views, bulk, auto-scheduling draft
PR6 feat/gantt-upstream-pr6-tier3-virtualization virtualization draft
PR7 feat/gantt-upstream-pr7-tier4 mobile + tree + predecessor col + visual deps + notifications draft
Docs (huly-docs#70) MichaelUray:feat/gantt-section reference + screenshots open

Marked as draft to signal stack dependency on PR1. Will be promoted to ready-for-review once PR1 is merged.

How to review

GitHub shows the cumulative diff against develop (PR1 + PR2 = 40 commits, ~2 850 line additions). For the PR2-only incremental diff see:

Fork compare: PR1...PR2 — 33 commits, 34 files

Testing

  • Jest tests on the time-scale and layout modules cover the date-math and row-packing edge cases.
  • Validated on a production-style deployment on 2026-05-18.

DCO

All commits are Signed-off-by.

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>
The sidebar resize handle and the canvas pointer-pan handler both lived
on the gantt-scroller, so dragging the handle started a canvas pan in
parallel — the result was visible stutter and barely-controllable
resize. Two fixes:

- Add .resize-cell to onCanvasPanStart's element exclusion list so the
  pan never starts when the handle is the pointerdown target.
- The resize-cell's own pointer handlers now stopPropagation +
  preventDefault, so even if a sibling listener picked up the bubbled
  event it would not double-process it. setPointerCapture stays so the
  drag tracks the pointer outside the cell bounds.

Plus the v16 toolbar consolidation:
- Move the always-visible blue + button to IssuesView.svelte (the
  shared wrapper for List, Kanban and Gantt). Single source — no
  duplication per viewlet.
- NewIssueHeader stays as the original HeaderButton-based component;
  inline category-level + buttons in the issue list are unaffected.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…yle)

The previous architecture put the canvas-stack inside one big
.gantt-scroller with overflow:scroll, so the native horizontal
scrollbar lived at the bottom of the entire scroll content — far
below the viewport once many rows were scrolled past. Noted:
this; Plane uses a separate sticky h-scrollbar at the bottom of the
visible area.

This commit splits the two scroll axes:

- .gantt-scroller now has overflow-y:auto + overflow-x:hidden. It
  carries vertical scrolling for the rows. Vertical native scrollbar
  unchanged.
- A separate .gantt-hscrollbar sits as a sibling at the bottom of
  .gantt-root (always visible regardless of vertical scroll
  position). It contains a thin track of width=totalCanvasWidth.
- The canvas-cell and header-cell become overflow:hidden, with
  inner wrappers translated by -hScroll.scrollLeft. Horizontal scroll
  is therefore controlled by the proxy bar but the visual sync
  matches what native scrolling would do.
- Pan-drag, jump-to-* and all programmatic scrolls now operate on
  the proxy bar instead of the gantt-scroller.
- ResizeObserver watches both scrollers so changes to either side
  re-sync the viewport bounds.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The previous implementation had the previous v18 sticky horizontal scrollbar still
relied on a native ::-webkit-scrollbar inside an environment where
Huly globally hides scrollbars (\`* { scrollbar-width: none }\`). On
some browsers/OS combinations the bar rendered as a 6px ghost the
user could not see.

This commit replaces the native bar with a DOM-based custom thumb:

- .gantt-hscrollbar contains an .hscroll-shell (position:relative,
  flex:1, min-width:0, overflow:hidden) that fits the viewport width.
- Inside the shell: an .hscroll-track-custom (overflow-x:scroll) is
  the actual scroll-source — its native scrollbar is forcibly hidden
  on both Firefox (scrollbar-width:none) and WebKit (display:none).
  A 1px wide spacer drives its scrollWidth.
- A sibling .hscroll-thumb is absolutely positioned over the shell
  and its left/width are computed from canvasViewportLeft and
  totalCanvasWidth. Pointer drag on the thumb writes back to
  hScrollEl.scrollLeft (and pointermove updates the position
  reactively).
- Click on empty track area page-scrolls 80% of viewport.

Result: a guaranteed-visible 11px tall thumb that follows the
canvas timeline regardless of browser, OS, or Huly's global scroll
styling.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…date range

Robustness fix:
- .gantt-hscrollbar is now position:absolute pinned to gantt-root
  bottom (z-index:10) instead of relying on the flex chain to keep
  it visible. .gantt-scroller reserves padding-bottom:16px so the
  bar never paints over the last canvas row.

Vertical custom scrollbar (parity with horizontal):
- Same DOM-thumb pattern: hidden native scroll on .gantt-scroller,
  custom .vscroll-thumb absolutely positioned at the right edge.
- Thumb position derives from scrollTop / vScrollMax; pointer-drag
  writes back to scrollerEl.scrollTop. Auto-hides when content
  fits.

Status-driven bar colors:
- Pull statusStore.byId once into statusCategoryMap; pass through
  GanttCanvas to each GanttBar. Categories map to fills:
  backlog/unstarted -> theme button-default (grey),
  todo -> blue, active -> amber, won -> green, lost -> muted grey.

Tight time-range:
- computeDateRange now pads by exactly one zoom-unit on each side
  (1d / 7d / 30d / 90d) instead of always 14 days.
- totalCanvasWidth = ceil(scaleWidth) only — no longer inflated to
  fill the viewport, which previously stretched the timeline across
  empty quarters with no issues. If the data fits in the viewport,
  the canvas just doesn't horizontally scroll.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- New StatusBadge.svelte renders a 12px coloured dot per row, mapped
  from the issue's status category via statusStore: backlog grey,
  todo blue, active amber, won green, cancelled muted.
- New ganttShowStatus ToggleViewOption (default ON) joins the existing
  Show-issue-code and Show-title in the Customize-View dropdown.
- Sidebar gains a 22px col-status column rendered before the issue-code
  cell. Milestone rows show a small "MS" tag instead of an issue code.
- Tracker-assets en.json + 12 other locales gain GanttShowStatus
  additively (+1 line per file).

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Implements 8 of the 9 action items from the an external UI review
redesign review. Item 8 (Geist font swap) skipped — would override
Huly's global Inter and is out of PR2 scope.

1. Today-marker date pill: small red rounded label at the top of the
   today line showing "10. May" so the marker speaks for itself.
2. Active-status bars get a stronger fill (#f59e0b amber + white
   text), Won bars green with white text, ToDo bars sky-blue with
   navy text — bars now read at a glance.
3. Sidebar gains a date-range subheader strip ("Feb 2026 – Mar 2027"
   with « » page-nav and click-to-jump-to-today behaviour). Header
   row height grows from 40 to 56px to fit the stacked layout.
4. Hover spotlight: when any row is hovered, non-hovered rows fade
   to 0.55 opacity (external review-style focus).
5. Milestone reference lines shrink from full-canvas dashed lines
   to a tick + filled triangle in the top 14px of the canvas —
   less visual noise behind the bars.
6. Toolbar Unicode glyphs (⏮ « » ⏭) replaced with Huly's own
   ArrowLeft/NavPrev/NavNext/ArrowRight icons; date input wrapped
   in a label with a Calendar icon.
9. Scrollbars slimmed from 14px to 10px tracks with semi-transparent
   thumbs (opacity 0.45 → 0.85 on hover, 1 on drag).

Item 7 (theme-aware bar colors) was already wired via statusCategory
Map in v25 — this commit just verifies the path.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Plane-style: dashed-top-border "+ Add issue" row at the bottom of
GanttSidebar opens the standard CreateIssue popup via showPopup.

- GanttSidebar dispatches `addIssue` from a keyboard- and click-
  accessible row using the existing tracker.string.AddIssue label.
- GanttView wires it to showPopup(CreateIssue, { space, shouldSaveDraft }).
- Row is hidden when no space is available (defensive guard in
  newIssue handler).

Verified on dk3 huly_v7 (gantt-v28): row renders, click opens
"New issue" dialog with Issue title field focused.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Adds Issue.startDate and Issue.dueDate to the ClassFilters mixin for
tracker.class.Issue. Both attributes are TypeDate, which view-model
already wires to view-resources DateFilter (with built-in range
support), so this is the minimal change to expose date-range filtering
in the Tracker filter dropdown — works in List, Kanban, and Gantt.

NB: deploy of this model change is batched with the PR3 multi-pod
deploy (transactor + workspace + tool image + workspace upgrade);
front:gantt-v28 alone is not enough since the ClassFilters mixin TX
lives in the workspace model store.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
GanttView computes hHasOverflow but never gated the bar on it — the
sticky-bottom scrollbar was rendered unconditionally, including in
empty workspaces where it was just visual noise. In addition, when
totalCanvasWidth was barely larger than the track, hThumbWidth could
exceed hTrackWidth and the thumb would visually overflow its container.

Fixes:
- Wrap the .gantt-hscrollbar element in `{#if hHasOverflow}` so it
  disappears in the no-overflow case.
- Clamp the rendered thumb width to `Math.min(hThumbWidth, hTrackWidth)`
  to defuse the degenerate over-track case.

in Playwright: empty workspace no longer renders the scrollbar.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…comments

Strips reviewer-attribution markers ('review-N <date>') from source-code
comments. Comments are kept and rephrased as 'review note' so the noted
constraint or hidden invariant survives, only the internal attribution
is dropped.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
@huly-github-staging
Copy link
Copy Markdown

Connected to Huly®: UBERF-16443

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.

1 participant