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
0.14.1: read the app version per request, not once at boot
The header version was cached at server startup. gantt.html is read per request,
so a deploy that only changes the HTML needs no restart, and that deploy left the
header showing the previous release: exactly the drift the injection was built to
prevent. It reads package.json on the page request now.
3 files changed
+11−8
package.json+1−1@@ -2,7 +2,7 @@ "slug": "adom-gantt", "title": "Adom Gantt", "type": "app",- "version": "0.14.0",+ "version": "0.14.1", "description": "Interactive Gantt chart viewer for project timelines, with a table view 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. Toggle to the table for every task and milestone as a row with owner, deadline and status, filtered per owner and edited in place. 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+2−2@@ -2,7 +2,7 @@ "slug": "adom-gantt", "title": "Adom Gantt", "type": "app",- "version": "0.14.0",+ "version": "0.14.1", "description": "Interactive Gantt chart viewer for project timelines, with a table view 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. Toggle to the table for every task and milestone as a row with owner, deadline and status, filtered per owner and edited in place. 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": {@@ -63,4 +63,4 @@ "name": "Drew Owens", "email": "[email protected]" }-}+}
server.js+8−5@@ -22,14 +22,17 @@ if (!fs.existsSync(DATA_FILE)) { const STATE_FILE = DATA_FILE.replace(/\.json$/, '-state.json'); const LOG_FILE = DATA_FILE.replace(/\.json$/, '-changelog.jsonl'); const APP_DIR = __dirname;-// Read once from our own manifest so the header cannot drift from the released-// version. gantt.html ships a placeholder; it is substituted on the way out.-const APP_VERSION = (() => {+// Read from our own manifest per request, not once at boot. gantt.html is already+// read per request, so a deploy that only changes the HTML needs no restart; if+// the version were cached at startup that deploy would leave the header showing+// the previous release, which is exactly the drift this was built to prevent.+// Cheap: a small file, and only on the page request.+function appVersion() { try { return JSON.parse(fs.readFileSync(path.join(APP_DIR, 'package.json'), 'utf8')).version || ''; } catch { return ''; }-})();+} function serveApp() {- return fs.readFileSync(path.join(APP_DIR, 'gantt.html'), 'utf8').split('__APP_VERSION__').join(APP_VERSION);+ return fs.readFileSync(path.join(APP_DIR, 'gantt.html'), 'utf8').split('__APP_VERSION__').join(appVersion()); } const DATA_DIR = path.dirname(DATA_FILE);