app
Adom Gantt
Public Made by Adomby adom
Interactive Gantt chart viewer for project timelines, with a table view and an analytics page over the same data. Data-driven, dark by default with a print-friendly light mode, and fully editable in the browser: drag bars to move or resize, multi-select and batch-shift dates, manage dependency arrows inline, reorder rows, filter by phase, and undo. One click auto-schedules the whole plan so every dependency lines up finish-to-start on working days, skipping weekends and US federal holidays, push
← Commit history
Fix: milestone line tags never overlap. Row pitch used each cap's own height, so a wrapped two-line tag was ridden into by the shorter tag on the row below. Use a uniform row pitch set by the tallest tag, and re-run cap layout after web-fonts load. Bump 0.7.1.
3 files changed
+12−4
gantt.html+10−2@@ -820,8 +820,13 @@ function layoutMsCaps(){ rows[0].push([tx-tw/2-GAP, tx+tw/2+GAP]); } const fits=(row,l,r)=>row.every(([a,b])=>r<a||l>b);+ // Uniform row pitch set by the tallest tag: a wrapped (two-line) tag on an upper+ // row can never be ridden into by a shorter tag on the row below.+ let rowH=14;+ caps.forEach(c=>{rowH=Math.max(rowH,c.cap.offsetHeight||14);});+ rowH+=3; caps.forEach(c=>{- const w=c.cap.offsetWidth||80, h=c.cap.offsetHeight||14;+ const w=c.cap.offsetWidth||80; const l=c.x-w/2-GAP, r=c.x+w/2+GAP; let n=0; while(true){@@ -830,7 +835,7 @@ function layoutMsCaps(){ n++; } rows[n].push([l,r]);- c.cap.style.top=(2+n*(h+3))+'px';+ c.cap.style.top=(2+n*rowH)+'px'; }); } @@ -862,6 +867,9 @@ function scheduleRelayout(){clearTimeout(rlTimer);rlTimer=setTimeout(()=>{ let lastRelayoutW=timelineEl.clientWidth; window.addEventListener('resize',scheduleRelayout); if(window.ResizeObserver)new ResizeObserver(scheduleRelayout).observe(timelineEl);+// Web-font load changes tag widths and heights after the first measure, so re-run the+// milestone cap collision layout once fonts settle, or tags can overlap on a cold load.+if(document.fonts&&document.fonts.ready)document.fonts.ready.then(()=>{if(prefs.msStyle==='line')layoutMsCaps();}); // ── Filter ── function applyFilter(){items.forEach(r=>{let vis=true;if(r.phase!==undefined&&!phaseVis[r.phase])vis=false;if(r.type==='milestone'&&!msVis)vis=false;r._lDiv.classList.toggle('dim',!vis);r._bDiv.classList.toggle('dim',!vis);});drawDeps();}
package.json+1−1@@ -2,7 +2,7 @@ "slug": "adom-gantt", "title": "Adom Gantt", "type": "app",- "version": "0.7.0",+ "version": "0.7.1", "description": "Interactive Gantt chart viewer for project timelines. Data-driven, dark by default with a print-friendly light mode, and fully editable in the browser: drag bars to move or resize, multi-select and batch-shift dates, manage dependency arrows inline, reorder rows, filter by phase, and undo. Every edit is recorded in an append-only changelog so an AI can read what a human changed and build on it. Imports JSON, CSV, MS Project XML and Jira CSV; exports JSON, CSV, SVG and a self-contained HTML snapshot.", "main": "server.js", "bin": {
page.json+1−1@@ -2,7 +2,7 @@ "slug": "adom-gantt", "title": "Adom Gantt", "type": "app",- "version": "0.7.0",+ "version": "0.7.1", "description": "Interactive Gantt chart viewer for project timelines. Data-driven, dark by default with a print-friendly light mode, and fully editable in the browser: drag bars to move or resize, multi-select and batch-shift dates, manage dependency arrows inline, reorder rows, filter by phase, and undo. Every edit is recorded in an append-only changelog so an AI can read what a human changed and build on it. Imports JSON, CSV, MS Project XML and Jira CSV; exports JSON, CSV, SVG and a self-contained HTML snapshot.", "main": "server.js", "bin": {