Skip to content

feat(tracker): Gantt chart for the issue tracker - #10992

Open
MichaelUray wants to merge 1 commit into
hcengineering:developfrom
MichaelUray:feat/gantt-consolidated
Open

feat(tracker): Gantt chart for the issue tracker#10992
MichaelUray wants to merge 1 commit into
hcengineering:developfrom
MichaelUray:feat/gantt-consolidated

Conversation

@MichaelUray

@MichaelUray MichaelUray commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

The search/filter rework this built on has merged (#10998), so this is now a standalone Gantt PR on current develop.

What it adds

  • Read-only viewlet: time-scale canvas with day/week/month/quarter zoom, sidebar columns, today marker and jump-to-start/end/date navigation.
  • Editable bars: drag to move, resize handles for start/due, drag an unscheduled row to schedule it, with optional confirm prompts and permission/conflict handling on commit.
  • Dependencies: FS/SS/FF/SF relations with lag, a dependency editor and arrows, cascade shifting with cycle detection, and critical-path plus slack.
  • Visual polish & coloring: bar labels, quick-info popover, milestone and deadline markers, non-working-day shading, shortcut help; bar coloring by status/priority/assignee/component/milestone with overdue and blocked overlays and sub-issue progress fill.
  • Tiers: undo/redo, saved views, bulk select and bulk drag, auto-scheduling with manual pinning; row virtualization for large projects; a read-only mobile layout, tree view with hierarchy breadcrumbs and a predecessor column.
  • Export & fullscreen: PNG and PDF export plus a fullscreen toggle, confined to the Gantt toolbar.
  • Dependency-shift notification: after a dependency cascade commits, a server-side trigger notifies affected issue collaborators, falling back to the assignee when no Collaborator records exist. It derives the sender, issue metadata, recipient spaces, and same-project issue set server-side rather than trusting client-supplied notification data.

The engine package

Introduces @hcengineering/gantt, a runtime-dependency-free package for the domain-neutral part of the Gantt library — time-scale and working-day calculations, zoom and viewport primitives, drag/pointer state, responsive toolbar helpers, and the neutral GanttItem, GanttDependency, and WorkingCalendar contracts. Tracker-specific scheduling, layout, critical-path and dependency-routing logic remains in the Tracker adapter; the Svelte UI, model schema, Huly actions, notifications, persistence and sanity coverage remain in their corresponding Tracker packages.

Data model and migrations

Adds optional scheduling fields to Tracker documents, including issue deadlines and scheduling mode, project working-day configuration, and component/milestone colors. It also registers the dependency-shift request and notification documents and includes idempotent upgrades for Gantt view options and legacy relation-activity records. Existing issues and projects retain their previous behaviour because the new scheduling fields are optional.

New runtime dependencies

In plugins/tracker-resources, both MIT: @tanstack/svelte-virtual (row virtualization) and jspdf (PDF export). Export re-renders the chart from the data model into an SVG rather than capturing the DOM; the PDF is paginated into bounded pages so large charts stay within the browser canvas and jsPDF size limits.

Locales

en, de and ru carry the full set of new strings, and a unit test enforces ICU placeholder parity across all locale files. Other locales fall back to English at runtime.

Testing

Full CI is green on a fork mirror of this exact head (02933ee0f0) — build, svelte-check, unit test, formatting, docker-build, uitest, uitest-pg, uitest-workspaces, uitest-qms. Fork-CI run: https://github.com/MichaelUray/huly-platform/actions/runs/31542585071

One small cross-cutting change: GanttView is a third writer to the shared result-count store from the search rework, so it uses the owner-token gate (claim/release like List and Kanban); the gate now resets to the pending sentinel on claim, so switching viewlets never shows a stale count.

@ArtyomSavchenko

Copy link
Copy Markdown
Member

Hi @MichaelUray
Thank you for your contribution.
I have the following suggestions:
1. Split out the search/filter rework into its own PR
The one thing that stands out as not Gantt infrastructure is the search/filter overhaul:

packages/ui: SearchInputAdvanced (field-prefixed field:value search), HighlightedText
foundations/server/packages/elastic: the new query_string branch
plugins/view-resources: inline filter chips + overflow popover, query-builder, empty state

2. A separate package for Gantt engine
I think that Gantt engine(gantt/lib) is a good candidate to live as its own reusable package, with the tracker integration staying in tracker-resources. I think we could then reuse it elsewhere — for cards, for example.

@MichaelUray

Copy link
Copy Markdown
Contributor Author

Understood. I'll split the shared search/filter rework into a separate PR.

For the Gantt code, I'll extract a tracker-agnostic engine package with generic item, dependency, scheduling, layout and viewport interfaces. Tracker-specific adapters, Huly actions, notifications and the Svelte integration will remain in tracker-resources.

I'll move this PR back to Draft while restructuring it and update it once both boundaries build and test independently.

Builds on the merged search/filter rework (hcengineering#10998). Introduces @hcengineering/gantt, a dependency-free scheduling/zoom/drag/viewport engine package (with a neutral GanttDependency contract), and wires the tracker-specific adapter, Svelte UI, model schema, dependency-shift notifications and sanity coverage in tracker-resources.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
@MichaelUray
MichaelUray force-pushed the feat/gantt-consolidated branch from 42c196d to 02933ee Compare August 11, 2026 23:14
@MichaelUray
MichaelUray marked this pull request as ready for review August 11, 2026 23:16
* needs to be read synchronously inside event handlers.
*/

let confirming = false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the drag-confirmation gate is a module-level singleton shared across every mounted GanttView, not scoped per view. If two Gantt views are ever mounted simultaneously (e.g. two tabs), confirming a drag in one silently blocks drag input in the other.

weekdayMask: number

/** Holidays as UTC-midnight timestamps. Order is irrelevant; duplicates allowed. */
holidays: Timestamp[]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the new per-project WorkingDaysConfig.holidays duplicates the existing workspace-level HR holiday concept (hr.class.PublicHoliday) with no integration, so holidays must be re-entered per project and can drift from the real HR calendar, skewing cascade/critical-path dates.

if (col === 'startDate') return issue.startDate ?? null
if (col === 'dueDate') return issue.dueDate ?? null
if (col === 'deadline') {
// No native `deadline` field on Issue — preserve the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment actual?
Looks like deadline field was added in this PR

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.

2 participants