4.5 KiB
Raw Permalink Blame History

SLICE 5 — gtd-gantt rendering

State-saving rule: update this file immediately after EVERY completed task (tick the checkbox, update Status and Resume notes) and whenever pausing for input — automatically, without being asked. State on disk must always match reality.

Status

COMPLETE (2026-07-15). All rendering code landed; 140/140 unit tests pass; tsc clean; npm run dist builds the .jpl. User manually verified in Joplin desktop. README + SPEC gantt docs added (beyond the original task list, at user request). No automated front-end tests (per the earlier webview-testing decision; disambiguation mirrors the unit-tested collectGantt).

Goal

Render the gantt in the webview: fence interception, message plumbing, DOM, CSS.

Tasks

  • src/gtd-calendar-renderer.ts: intercepts gtd-gantt fences. A block with a non-empty project: value (cheap regex GANTT_PROJECT_LINE, no YAML lib) → inline <span class="gtd-gantt-badge">gantt: <project></span>; otherwise emits the chart placeholder (data-block-type="gantt"). Project value is HTML-escaped and unquoted. Empty-project alignment matches collectGantt (empty ⇒ chart).
  • src/index.ts: handleGetGantt + getGantt switch case, mirroring handleGetKanban (parse → selectedNote → resolveScanFolder → collectGantt → payload with title/cardDetail/scopeAll/configError/warnings+softcap/chart/ stats). No-selectedNote path returns an empty chart.
  • src/gtd-calendar-webview.js: renderGantt + buildGanttGrid and helpers (offsetDays, clampOffset, monthTicks, todayLocalISO, tooltips). Single CSS grid: label column (sticky) + repeat(totalDays, 26px); month tick header row; project header rows; bars via grid-column from day offsets (bg/fg colour or colourFromId hash); milestones as ◆ markers (done → dimmed + struck label, ↻ for recurring); today line spanning body rows; click → openNote; hover text via native title (suppressed when card-detail:none); title/configError/warnings/stats blocks as in other views (stats footnote carries the scope: all marker).
  • src/event-calendar.css: .gtd-gantt-* styles (badge, scroll container, grid, sticky corner/labels, ticks, bars, milestones, today line), using the same rgba/theme-var conventions as existing styles.
  • Manual verification in Joplin desktop — CONFIRMED 2026-07-15. Verified live: item-block badge (gantt: bluesky) renders inline (not a chart); chart renders with title, month tick header, alphabetical project header (bluesky (3)), a note bar spanning begin→end (Jul 114), ◆ milestones on to-do due dates, and the red today line at Jul 15. Footnote reports item/note/folder counts. Host-note exclusion confirmed (an item block in the chart's own note is correctly omitted — put items in separate notes). Unknown-option warning fires correctly for stray keys like todos (gantt has no notes/todos inclusion option).
  • Docs (added at user request; not in the original task list): README gantt section (item vs chart, bar/milestone rules, chart options table) + SPEC.md §2.5 (dual-role disambiguation rule, item/chart schemas). Screenshots not committed — verified interactively instead.

Resume notes

Code complete. Files touched:

  • src/gtd-calendar-renderer.ts (gantt fence + badge/chart disambiguation)
  • src/index.ts (handleGetGantt + switch case + imports)
  • src/gtd-calendar-webview.js (dispatch + renderGantt/buildGanttGrid + helpers)
  • src/event-calendar.css (.gtd-gantt-* styles)

Design choices worth noting for a resumed session:

  • Grid layout is a single display:grid with explicit gridRow/gridColumn per element (label col = 1, day columns = 2..N+1). Bars: grid-column: off+2 / endOff+3 (inclusive end). Milestones: off+2 / span 1. Today line: grid-row: 1 / <rowIndex> at the today column.
  • Hover uses native title tooltips (not the calendar's hover-card DOM) — simpler and reliable; revisit if richer hover cards are wanted. card-detail:none suppresses tooltips; "always" currently behaves like "hover" (no inline text on bars) — a possible future refinement, noted but out of scope.
  • No automated renderer/webview tests by design (front-end testing deferred, per the SLICE-boundary discussion). Disambiguation regex mirrors the unit-tested collectGantt classification.

Next after manual sign-off: SLICE6.