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
Publish 0.7.0
6 files changed
+54−4
README.md+2@@ -44,6 +44,8 @@ Interactive Gantt chart viewer for project timelines. Data-driven, dark by defau **Clean group labels.** A trailing date range in a group label is dropped at render, since the axis already shows the dates and the text goes stale as soon as the plan moves. +**Authored default view.** `project.view` in the data file pins how the chart opens: grain, milestone style, today marker, theme and name-column width. The HTML export bakes it in and ignores the viewer's saved preferences, so a shared snapshot always matches the image that invited the click. In the live app your own choices still win.+ **Changelog.** Every edit is appended to `<datafile>-changelog.jsonl` with the item, the before and after dates, the day shift, and which gesture made it. An AI picking the project up later reads it and builds on your changes instead of overwriting them. The rev counter in the bottom-left corner is the handle: an agent notes it, then asks for only what changed since. ## In action
SKILL.md+21@@ -78,6 +78,27 @@ Create a JSON file with this structure: | title | string | yes | Project name shown in header | | subtitle | string | no | Short tagline (default: "Gantt chart") | | appName | string | no | Shown in brand zone (default: "adom-gantt") |+| view | object | no | The author's intended default view, see below |++**project.view** (optional) sets how the chart opens. It applies to the HTML export, to+a freshly served chart, and to any browser with no saved preference. In the live app a+preference the user has set for themselves still wins; an exported snapshot ignores saved+preferences entirely so it always opens as authored.++```json+"view": { "grain": "quarter", "milestones": "lines", "today": false, "labelWidth": 320 }+```++| Field | Values | Description |+|-------|--------|-------------|+| grain | `day` `week` `month` `quarter` `year` | Cell size |+| milestones | `lines` `diamonds` | Milestone style |+| today | `true` `false` | Show the today marker |+| theme | `dark` `light` | Opening theme |+| labelWidth | number (120-760) | Name column width in px |++Set this when a chart is meant to be shared, so the snapshot on a wiki page matches the+hero image that invited the click. **phases[]** (required, at least 1)
gantt.html+23−1@@ -312,9 +312,31 @@ document.title = `${project.title} — adom-gantt`; // ── View preferences (theme, milestone style, start-date override) ── const PREF_KEY = 'adom-gantt:prefs';+// A snapshot opens as its author curated it, so it ignores whatever the viewer happens+// to have in localStorage from another chart. The export flips this to true.+const SNAPSHOT = false;++// project.view is the author's intended default view. It applies everywhere the chart+// is served fresh: the HTML export, the server render, and any browser with no saved+// preference. In the live app a preference the user has actually set still wins.+function viewDefaults(){+ const v = (project && project.view) || {};+ const d = {};+ if (v.grain && ['day','week','month','quarter','year'].includes(v.grain)) d.granularity = v.grain;+ if (v.milestones) d.msStyle = /^lines?$/.test(v.milestones) ? 'line' : 'diamond';+ if (v.today !== undefined) d.showToday = !!v.today;+ if (v.theme === 'light' || v.theme === 'dark') d.theme = v.theme;+ if (v.labelWidth) d.labelW = Math.max(120, Math.min(760, +v.labelWidth || 0)) || undefined;+ return d;+}+function savedPrefs(){+ if (SNAPSHOT) return {};+ try { return JSON.parse(localStorage.getItem(PREF_KEY)) || {}; } catch { return {}; }+} const prefs = Object.assign( { theme: 'dark', msStyle: 'line', granularity: 'month', showToday: true },- (() => { try { return JSON.parse(localStorage.getItem(PREF_KEY)) || {}; } catch { return {}; } })()+ viewDefaults(),+ savedPrefs() ); function savePrefs(){ try { localStorage.setItem(PREF_KEY, JSON.stringify(prefs)); } catch {} } function applyTheme(){ document.documentElement.setAttribute('data-theme', prefs.theme); }
package.json+1−1@@ -2,7 +2,7 @@ "slug": "adom-gantt", "title": "Adom Gantt", "type": "app",- "version": "0.6.1",+ "version": "0.7.0", "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.6.1",+ "version": "0.7.0", "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": {
server.js+6−1@@ -745,8 +745,13 @@ function generateHTMLSnapshot() { ); } + // A snapshot must open at the view its author curated, not at whatever the viewer+ // has in localStorage from some other chart. project.view supplies the defaults.+ html = html.replace(/const SNAPSHOT = false;/, 'const SNAPSHOT = true;');+ // Add a comment at the top indicating this is a snapshot- html = html.replace('<!DOCTYPE html>', `<!DOCTYPE html>\n<!-- adom-gantt snapshot — generated ${new Date().toISOString()} -->`);+ const v = (data.project && data.project.view) || {};+ html = html.replace('<!DOCTYPE html>', `<!DOCTYPE html>\n<!-- adom-gantt snapshot — generated ${new Date().toISOString()}${Object.keys(v).length ? ' — view ' + JSON.stringify(v) : ''} -->`); return html; }