Skip to content

[ci-verify] Gantt pr7 tier4 cumulative (pr2-pr7)#5

Closed
MichaelUray wants to merge 302 commits into
developfrom
ci-verify/gantt-pr7
Closed

[ci-verify] Gantt pr7 tier4 cumulative (pr2-pr7)#5
MichaelUray wants to merge 302 commits into
developfrom
ci-verify/gantt-pr7

Conversation

@MichaelUray

Copy link
Copy Markdown
Owner

Fork-internal CI verification of Phase 3 cascade merge. Not for merge — the real PRs are upstream. Runs the uitest (Playwright) suite on the merged stack.

…sion

1. Context menu is too tall (~19 entries from auto-resolved Huly
   actions). Restructured via includedActions allow-list to 9
   curated entries that make sense for a Gantt bar:
   - Open (Edit issue)
   - Status / Priority / Assignee (existing actionPopup submenus, ›)
   - Set start date / Set due date
   - Copy issue ID / URL
   - Duplicate / Delete

   Component, Milestone, Labels, SubIssue, SetParent, Relations,
   Move-to-project and time-report stay accessible from the standard
   List/Kanban menu but are hidden from Gantt's right-click.

2. Unscheduled-drag-grip in the sidebar shared pointerdown with the
   canvas pan handler. Pan would start before the grip's
   mousedown|stopPropagation fired, swallowing the drag.

   Extended onCanvasPanStart exclusion: now also bails on
   .sidebar-cell, .drag-grip, .resize-handle. The grip's pointerdown
   no longer triggers a stray pan.

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

User UX feedback 2026-05-11: the allow-list approach hid Open (Edit
issue) because tracker registers a custom Open action for
tracker.class.Issue with an auto-generated ID, and it also hid
Set parent issue / Add sub-issue which the user explicitly needs to
manage issue hierarchy from the Gantt.

Switch from includedActions to excludedActions. Hide only the
genuinely noisy entries for a Gantt right-click: Component,
Milestone, Labels, CopyIssueTitle, Relations, NewRelatedIssue,
EditRelatedTargets, MoveToProject, CopyAsMarkdownTable, UnsetParent.

Result: Open / Status / Priority / Assignee / Set start date /
Set due date / Add sub-issue / Set parent issue / Copy ID / Copy URL
/ Duplicate / Delete remain — 12 entries instead of 18, with the
expandable submenus (Status, Priority, Assignee ›) keeping the
visible menu compact.

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

User requirements 2026-05-11:

1. Restructure Gantt right-click menu: "Sub-issue & Parent" as a single
   collapsed Hierarchy ▸ submenu containing
   - Set parent issue…
   - Add sub-issue
   - Link existing as sub-issue…   (NEW)
   The old flat SetParent + NewSubIssue entries are hidden from the
   parent menu (excludedActions) so the Gantt context menu stays compact.

2. EditIssue panel: add a "Set parent issue…" button visible when the
   issue has no parent — previously this was only reachable via right-
   click context menu, not from the open issue itself.

3. SubIssues panel: add a "Link existing as sub-issue" button next to
   the existing "Add sub-issue" button so the user can attach an
   already-existing issue without first opening it.

4. GanttHeader two-row labels (user feedback: "year/month above"):
   - day view:    month name above day number
   - week view:   year above Wnn
   - month view:  year above month name (was entirely missing)
   - quarter view: year split out above Q1/Q2/… (was side-by-side
     "Q1 2026" — visually noisy at dense zoom)

   Supra-label renders only at segment boundaries (1st of month, first
   week of year, January, Q1) so it doesn't repeat in every column.
   3 new jest tests cover day/week/quarter supra cases.

- Hierarchy UiAction missing required `action` field — added no-op
  (Menu.svelte routes the click via `component:` when present).
- dragging-unscheduled no longer shifts existing descendants — the
  synthetic "today" origin would have shifted them by a wildly
  unrelated delta. Unscheduled-drag now only commits the parent.
- LinkSubIssueActionPopup: full ancestor + transitive descendant
  ignore set so the picker can't create cycles (BFS over the
  parents[0].parentId edge, matching scheduler.descendantsWithDates).
- releasePointerCapture now guarded by hasPointerCapture(pointerId)
  to avoid InvalidStateError when a pointerup bubbles from an
  excluded child (resize-handle, drag-grip).
- openSetStartDate (context menu) now surfaces commit failures via
  NotificationSeverity.Error, matching commitDrag's error handling.
- i18n: drag-grip tooltip and duration tooltip pulled out of hardcoded
  English into tracker.string.GanttDragToSchedule + GanttDurationTooltip.

New files:
- plugins/tracker-resources/src/components/LinkSubIssueActionPopup.svelte
- plugins/tracker-resources/src/components/gantt/GanttHierarchySubmenu.svelte

i18n: 5 new keys (Hierarchy, LinkExistingSubIssue, SetParentIssueLabel,
GanttDragToSchedule, GanttDurationTooltip).

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

User UX requirements 2026-05-11:

1. Click-to-select gate: a bar must be clicked once to become "selected"
   (solid blue outline, .bar.selected) before the next mousedown
   actually starts a drag/resize. Prevents accidentally dragging an
   issue while panning the canvas horizontally — earlier feedback was
   that fast horizontal pans would catch a bar by mistake. Plane-style
   UX. Clicking the canvas background clears the selection.

2. Confirmation popup before commit: GanttConfirmCommitPopup shows a
   "Move X to Y – Z?" / "Change X to Y – Z?" dialog with Cancel/Apply
   buttons. Two independent ViewOption toggles (Customize-View → Display)
   gate whether the popup appears:
     - ganttConfirmMove   (default-on) — drag-body
     - ganttConfirmResize (default-on) — resize-left/right
   Saves to the same per-viewlet option store as ganttShowStatus, so
   each user gets their own preference. Skip the popup entirely when
   the preview is unchanged (zero-delta drag).

   sub-issues it renders as the MS-Project claw rather than a regular
   rect. Previously the claw had no mousedown/contextmenu, so commitDrag's
   parent-pulls-children path was unreachable from the UI. A transparent
   `summary-hit` rect now spans the claw and wires the standard
   onBarDown / onBarContextMenu handlers, plus the two resize-handles.
   Milestone summaries (issueObj === undefined) stay read-only.

- Split GanttConfirm{Move,Resize} setting label from dialog title.
  New keys: GanttConfirmMoveTitle = "Move issue?", GanttConfirmResizeTitle
  = "Change issue dates?". Setting labels remain "Confirm before moving an
  issue" etc.
- Drop unused GanttClickToSelect string.
- New jest suite `link-sub-issue-cycle.test.ts` (6 tests) fences the
  ancestor/descendant/self/cycle ignore logic so future refactors can't
  silently regress cycle protection.

Deploy:
- models/tracker + models/all rebuilt to ship the new ViewOption keys.
- front/transactor/workspace/tool images at gantt-v35.
- Workspace upgrade applied to all 3 dk3 workspaces — toggles appear in
  Customize-View → Display.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…et + a11y roles

per explicit user preference for both select-first + confirm-popup
default-on):

1. Parent-drag now shifts the FULL descendant tree, not just children
   that happen to be in the view's filtered `issues` array. Previously
   a Tracker filter that hid some sub-issues caused them to stay at
   the old date while their parent moved — silent tree drift. commitDrag
   and shiftFocused both now run `client.findAll(tracker.class.Issue,
   { space: issue.space })` to query the full space before walking
   descendantsWithDates. One extra query per commit, no impact on drag-
   interactive frame rate.

2. computeCanvasX (unscheduled drag) now offsets by sidebarWidthPx +
   5 px instead of just sidebarWidthPx. The 5 px is the resize-cell
   column between sidebar and canvas (.resize-cell). The hscrollbar
   has always used this offset (style="padding-left: {sidebarWidthPx +
   5}px"); unscheduled-drag was the only consumer that missed it,
   causing drops to land a few pixels off at high zoom.

3. A11y: the 6 interactive <rect>s on GanttBar (regular + summary +
   resize handles, both branches) now carry role="button",
   tabindex="-1", and aria-label so screen readers announce them as
   actionable. The a11y-click-events-have-key-events warning is
   suppressed per-rect with svelte-ignore plus a banner comment
   explaining that keyboard support lives at the GanttView level
   (Tab/ArrowLeft/Right). 94 → 88 warnings.

Tests: 5 suites / 60 passed.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…bels

friction observation about select-first + confirm-popup left as-is
per explicit user preference, the parent-drag performance note is a
future-large-space concern):

1. .settings-btn / .settings-popover removed from GanttView.svelte.
   They were leftover from an earlier custom-popover prototype that
   was replaced by Huly's standard ToggleViewOption pattern in PR2;
   the CSS was orphaned. Drops 4 svelte-check warnings.

2. Resize handle ARIA labels were hardcoded English ("Resize start" /
   "Resize end"). Now translated via tracker.string.GanttAriaResizeStart
   and GanttAriaResizeEnd. Translation resolves async on themeStore
   language change; falls back to the English default until resolved.

84 warnings (was 88).

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>
handleCanvasMouseUp is async; passing it directly to window
add/removeEventListener triggers @typescript-eslint/no-misused-promises
(Promise returned where a void return is expected). Introduce a single
stable void-returning wrapper (onWindowMouseUp) used at all three sites
so add and remove still reference the same listener object — a per-call
arrow wrapper would leak the listener. The mouseup commit stays
fire-and-forget with its existing internal error handling.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
lang.test enforces en/ru structural parity. Gantt feature keys added to
en.json were missing in ru.json; filled with the en value as a
placeholder pending translation (Huly convention). No existing ru
translations changed.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
MichaelUray pushed a commit that referenced this pull request Jul 9, 2026
…marked invariant

- cursor: pointer when editable+unselected, grab when selected,
  grabbing during active drag (same state machine for summary claw)
- .bar.selected: 3px stroke + stronger glow, paint-order stroke fill
  so the armed state is unmistakable on every status fill color
- .bar.focused: 1px dashed (was 2px solid) — visually distinct from
  .selected so the two states never look identical
- handleBarMouseDown syncs focusedIssueId to selectedIssueId on
  first-click and onBackgroundClick clears both; eliminates the
  'multiple bars marked' visual where Tab-focus + click-select
  highlighted two bars simultaneously
- resize handles only render when the bar is selected (avoids
  accidental edge-grabs on unarmed bars; minimal surface for the
  ew-resize cursor)

User feedback 2026-05-11 from dk3 deployment: single click did not
visibly mark the bar and multiple bars appeared selected at once.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The previous isEditable/isFocused/isSelected functions hid their
underlying state dependencies (editableIssueIds Set, focusedIssueId,
selectedIssueId) from Svelte's template dependency tracker. The
template binding 'editable={isEditable(row.issue._id)}' only
re-evaluated when its visible references (isEditable function ref
and row.issue._id) changed — never when the underlying Set or string
mutated.

Initial pass: editableIssueIds is empty, bars render editable=false.
Async canEditIssue loop populates the Set, but the template never
re-runs the binding. GanttBar.onBarDown early-returns on !editable,
so click/drag/resize all silently failed — user reported clicking a
bar did nothing.

Same staleness applied to selectedIssueId and focusedIssueId: even
after handleBarMouseDown set selectedIssueId, the binding never
re-evaluated, so the .selected class never reached the DOM.

Fix: promote the three helpers to '$:' reactive declarations.
Svelte now sees the underlying state as a dependency and reassigns
the function on every relevant change, which invalidates the
template binding and re-evaluates the prop.

Verified end-to-end in Playwright on dk3 huly_v7 stack (gantt-v39):
- 5 bars all editable=true after createQuery + canEditIssue loop
- single click sets exactly one .selected (and synced .focused)
- click on another bar deselects the previous one
- click on background clears both selected and focused
- drag from selected bar enters .active-drag with cursor=grabbing
- mouseup leaves active-drag state cleanly
- resize handles only render when the bar is selected

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

- canEditMilestone() helper in utils.ts, mirrors canEditIssue's
  guest-vs-member logic (non-guests can edit, guests cannot)
- Milestone label cell in GanttSidebar gets class='cell-title clickable'
  + role='link' + on:click → openMilestone, matching the issue row
- New openMilestone event on the sidebar dispatcher, threaded through
  GanttView.onMilestoneOpen → showPopup(EditMilestone, …)

User feedback 2026-05-11: milestones in the Gantt sidebar were a plain
non-interactive label; only issues opened on click. PR3.2 brings the
sidebar to parity. Canvas-bar edit-mode parity for milestones (drag /
resize) is deferred to PR3.3 — that requires a DragState refactor
across 5 files to accept both Issue and Milestone payloads.

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

EditMilestone expects 'object: Milestone' and reads object.label /
status / dates synchronously on mount. LayoutRow.milestone carries
only a MilestoneMarker (compact view), so passing it directly threw
'Cannot read properties of undefined (reading label)'.

Sidebar now dispatches milestoneId; GanttView resolves to the full
Milestone from its milestones query before showPopup.

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

DragState / DragEvent refactor: 'issue: Issue' becomes 'target: DragTarget'
where DragTarget is a discriminated union { kind: 'issue', doc: Issue } |
{ kind: 'milestone', doc: Milestone }. The reducer stays doc-agnostic —
it only operates on originStart / originEnd / cursor deltas, with the
target threaded through unchanged. Renamed originDue → originEnd and
previewDue → previewEnd to reflect the doc-agnostic semantics
(Milestone.targetDate plays the same role as Issue.dueDate).

mousedown-bar now carries explicit originStart / originEnd captured at
the dispatch boundary so the reducer doesn't need to know which field
on target.doc to read.

Milestone rendering (brainstorm decision A): bars are emitted on
milestone rows only when startDate is set. The synthetic children-
aggregate summary-claw is dropped from milestone rows — the milestone
IS the milestone, not its assigned-issues range. Open-ended milestones
(startDate null) remain represented only by the diamond on the top
strip.

Cascade on milestone body-drag (brainstorm decision B): all assigned
issues plus their descendants shift by the same delta. Resize doesn't
cascade — only the milestone bounds change. Issue-cascade (parent →
descendants) is unchanged.

commitDrag now branches by state.target.kind:
- Issue: startDate / dueDate update + descendant cascade (existing).
- Milestone: startDate / targetDate update + assigned-issues cascade.

editableIssueIds Set now holds both Issue and Milestone _ids; the
async permission loop checks canEditIssue or canEditMilestone for
each. milestonesById Map (built reactively from milestones query)
gives GanttCanvas the full Milestone doc to wrap in a DragTarget at
mousedown time.

Tests updated for new field names; 2 new test cases cover milestone
mousedown + resize-right reducer behavior.

Resize-overlay and Sidebar drag-state probes also renamed.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
When the user mouses-down on a bar that isn't currently selected, treat
the gesture as a canvas pan (same as click+drag on empty space) instead
of swallowing the drag. The bar still receives its mousedown — the
click-to-select gate still arms selectedIssueId — but the parallel pan
allows the user to scroll horizontally / vertically from the same
gesture.

Selected bars stay excluded so PR3's second-click drag/resize still
fires; otherwise the bar would never move once armed.

User feedback 2026-05-11: previously click+drag on an unselected bar
did nothing visible (selectedIssueId was set but the user wanted to
scroll the canvas).

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>
- kindCode / kindFromCode: round-trip between long-form 'finish-to-start'
  (persisted) and two-letter display codes 'FS' (notation only).
- signedLag: '+2d' / '-1d' / '' (zero) for lag display.
- formatPredecessors: filter relations by target, join 'XXkindLag' tokens.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
BFS over relation graph from target; closes-the-loop iff source is
reachable. O(V + E) per call. Self-loops always count as cycles.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
anchorOf maps DependencyKind to which bar-edge the arrow attaches to;
endpointPx returns the pixel coordinate of that edge's midpoint.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
- bezierPath: cubic SVG path with control points on bar y-axis and
  offset = max(40, |dx|/2) for visual balance.
- pathMidpoint: de Casteljau closed form at t=0.5 (lag-pill anchor).
- arrowheadPoints: 3-vertex triangle at p2 along the curve tangent.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Hover-emphasize helper. Hovering a bar highlights it + direct neighbors;
hovering an arrow highlights just its two endpoints.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Adds 'connector-drawing' / 'connector-target-hover' states plus the
matching mousedown/move/up events. Reducer wiring lands in Task 9.

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

idle/hover-bar + mousedown-connector → connector-drawing; mousemove
with hoveredBar !== source toggles target-hover; mouseup or Escape
returns to idle. Self-hover on the source bar stays in drawing
(no relation A → A).

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Spread-based return in reduceFromConnector copied target field from
connector-target-hover state into the returned connector-drawing
object. TypeScript permits this excess-property leak through
spreads. Replaced with explicit construction and strengthened the
back-to-drawing test to assert 'target' is absent.

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>
Iterates IssueRelation list, renders one GanttDependencyArrow each, plus
a live bezier preview tied to connector-drawing / connector-target-hover
drag states.

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, leftover internal review markers).
Comments themselves are preserved — only the attribution labels are dropped.

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>
@MichaelUray MichaelUray force-pushed the ci-verify/gantt-pr7 branch from 0a4d78e to 661b2ec Compare July 9, 2026 07:46
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…ed by localStorage

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Adds an opt-in 'Predecessors' column to the Tracker issue list, so
power users can see dependency relationships without switching to the
Gantt view. Spec
docs/superpowers/specs/2026-05-14-huly-gantt-predecessor-column-design.md.

Rendering (spec-mandated):
- Identifier + Kind + Lag notation, e.g. 'PROJ-3 FS+2d'.
- Zero lag drops the +0d suffix ('PROJ-3 FS').
- Multiple predecessors collapse to 'first +N more' with a hover
  tooltip listing every upstream issue.
- Click on the identifier navigates to the predecessor issue via
  DocNavLink -> EditIssue (standard Tracker navigation).
- Empty cell when the issue has no incoming relations.

Files:
- plugins/tracker-resources/src/components/issues/
    PredecessorsColumnPresenter.svelte  -- live-query relation + sources
    PredecessorsTooltip.svelte           -- +N more hover body
- plugins/tracker-resources/src/plugin.ts  -- PredecessorsColumn component id
- plugins/tracker-resources/src/index.ts   -- register component
- models/tracker/src/viewlets.ts           -- column entry (optional, hidden by default)

i18n strings 'Predecessors'/'Vorgaenger' already exist in en+de from
the Gantt sidebar column work, no new strings needed.

Tests: 518 -> 531 (13 helper tests added in previous commit).
svelte-check: 0 errors on new components.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…uping by recipient

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

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…yChangeKind for Visual DependencyEditor

Adds tooltip strings (one per kind) plus the picker aria-label and the
'Change type' link label in EN + DE. Keys match existing convention.

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

Replaces the dropdown in DependencyEditor with a 2x2 grid of clickable
SVG mini-diagrams (FS / SS / FF / SF). After a pick the grid collapses
to a compact single-diagram view plus an inline -14..+14d lag slider
and a 'Change type' link that re-expands the grid. The existing
NumberInput stays as fallback for values outside the slider range
(-30..+90 storage clamp unchanged).

Per spec 2026-05-14-huly-gantt-visual-dependency-editor-design.md:
- 2x2 layout (FS/SS top, FF/SF bottom)
- lag slider embedded in the picked diagram view
- collapse-after-pick UX with re-expand button
- role=radio + arrow-key keyboard navigation between diagrams
- aria-label + title tooltips with full kind-hint i18n strings

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

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Adds pure-TS helpers for the upcoming 2x2-grid mini-diagram picker:

- DIAGRAM_KINDS in spec-mandated grid order (FS/SS/FF/SF)
- diagramGridIndex() for keyboard navigation (Arrow keys)
- clampLagSlider() for the inline -14..+14d slider
- getDiagramSvgPaths() returns rects + arrow polyline per kind,
  with FS/FF distinguishable by arrow endpoint (left vs right of S)

18 new tests, 549 total.

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

Two small follow-ups discovered during the final pass:

  - GanttBar .bar gets touch-action: none so iOS Safari does not
    hijack pointerdown on a bar with native pan-zoom (Spec §"iOS-
    Safari Edge-Cases"). Without this the long-press timer never
    fires because Safari steals the gesture before pointerup.

  - The drawer's top offset was hardcoded to 32 px via a non-existent
    --gantt-header-height variable. HEADER_HEIGHT is 56 in
    GanttView.svelte; the drawer now matches, with a comment to keep
    it in sync. height: calc(100% - 56px) so the drawer doesn't
    overflow under the bottom of the canvas-cell either.

Tests: 631 / 631. svelte-check: 0 errors.
Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Phone-mode (≤640 px) gets:
  - Hamburger button in the toolbar that toggles a slide-out drawer
    overlay carrying the issue list (Spec §"Phone": Sidebar Phone =
    Slide-out-Drawer auf Tap).
  - Sidebar-cell goes absolute + translateX(-100%) by default; the
    .drawer-open class slides it to 0. Tap-anywhere-on-canvas
    backdrop dismisses it; the onJump handler also closes it once
    the user has scrolled to the picked row (Spec §"Phone": Tap
    schließt Drawer).
  - Resize-corner / resize-cell are hidden — finger-width column
    resize is fiddly and the drawer covers the viewport anyway.

Tablet-mode (641–1024 px) gets:
  - .nav-btn / .gantt-toolbar-icon-btn / .zoom-btn min-44x44 px hit
    targets so touch-tap is reliable (Spec §"Tablet": Hit-Targets
    min 44x44 px).

Confirm popups become responsive (Spec §"Risks": 600 px popups
overflow 320 px screens): max-width: min(480px, 95vw) + box-sizing
border-box. On Phone the popup is read-only so this is belt-and-
braces, but the cap also helps narrow-window desktop users.

i18n strings (EN + DE) added for hamburger aria-label and the
read-only hint. Tests: 631 / 631. svelte-check: 0 errors.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Close the coverage gap surfaced by the 2026-05-15 regression audit:

- cascade-token.ts: 9 tests covering default + custom prefix, the
  <date>-<counter> suffix shape, monotonic counter increment and 1000-call
  uniqueness.
- dependency-shift-send.ts: 5 tests around early-return paths (empty
  primaries+shifts, empty bundle, missing PersonSpace) and the onError /
  silent-swallow contract. The Tx-create bundle remains untested by
  design (pure IO glue with no behaviour to assert).
- menu-actions.ts: 14 tests covering the ganttExtraActions array shape
  (group, icon, component, props) plus the openSetStartDate popup wiring
  and the four callback branches (dismiss, clear, auto-fill-due,
  no-auto-fill).

exporter.ts stays untested: every export is bound to the DOM / canvas /
html2canvas / jsPDF and cannot run under the node Jest env without
either refactoring or pulling in jsdom. Audit report appended with the
rationale.

645 -> 673 tests.

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, leftover internal review markers).
Comments themselves are preserved — only the attribution labels are dropped.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
Lift the gantt-toolbar controls (Group-by, Date-Nav, Zoom preset + days
input, Undo/Redo, Hamburger, Fullscreen) out of GanttView and into the
SpaceHeader's row 2 so the user sees a single unified toolbar instead
of three stacked strips.

Render order matches the spec: Filter -> Group-by -> Lupe -> Date-Nav ->
Week -> days -> Undo/Redo -> All/Active/Backlog -> Hamburger ->
Fullscreen (Hamburger now before Fullscreen, swapped from legacy).

State bridges across the parent/child boundary via a writable Svelte
store (ganttToolbarSnapshot): GanttView keeps owning the values and
handlers, writes a snapshot on every reactive update, and clears it
on destroy. A standalone GanttToolbarBar component subscribes to the
store and renders the controls in two clusters, one per slot.

SpaceHeader gains:
- overrideSearch prop + search slot to let consumers replace the
  built-in SearchInput + FilterButton when needed
- extra-trailing slot rendered after the ModeSelector

Non-gantt viewlets (List, Kanban) keep the SpaceHeader default exactly
as before.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
The SpaceHeader's row-2 search cluster uses flex-direction: row-reverse,
so markup order is reversed from visual L→R. Split GanttToolbarBar's
search section into search-mid (Group-by only) and search-end (the rest)
and reverse the internal markup order so the user sees:

  Filter → Group-by → Lupe → Date-Nav → Week → days → Undo/Redo

The extra cluster keeps row direction so the trailing section's
Hamburger-before-Fullscreen markup matches the visual order.

Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
…s in extended sidebar

- Move the Fullscreen toggle out of the gantt-toolbar trailing slot into
  the global status bar (packages/ui Root.svelte, next to the gear icon)
  so it's reachable from every viewlet, not only Gantt. The button
  switches Maximize/Minimize icon based on document.fullscreenState.

- Swap the search-row ordering so the Lupe (SearchInput) sits leftmost
  and Filter sits next to it: visual L→R is now Lupe → Filter →
  Group-by → Date-Nav → Week → days → Undo/Redo.

- Restore milestone labels (and start/due dates) in the extended-columns
  sidebar. The Phase-3a renderer fell through to an empty placeholder
  for any non-issue row; the user reported milestone text vanished as
  soon as Extended Sidebar Columns was enabled. Now the title column
  shows the milestone label (italic, matching the legacy compact
  sidebar), and the startDate/dueDate/deadline columns show the
  milestone's startDate/targetDate.

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>
@MichaelUray MichaelUray force-pushed the ci-verify/gantt-pr7 branch 3 times, most recently from 3032588 to fcaf5ae Compare July 9, 2026 18:54
@MichaelUray MichaelUray deleted the ci-verify/gantt-pr7 branch July 10, 2026 07:37
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