diff --git a/README.md b/README.md new file mode 100644 index 0000000..ab10fa0 --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# Pipeline Network Diagram Editor + +An Electron desktop app for drawing and analyzing **pipeline / network diagrams** +(water, hot water, gas, power, signal…). Nodes are SVG symbols with typed +connection ports; connectors are routed orthogonally along a grid and can carry +an animated, mass-conserving mock flow. + +![Editor](docs/plan/app-flow.png) + +## Features + +- **Symbol stencil** — 16 grouped, searchable SVG symbols (sources, consumers, + fittings, equipment, instruments). Drag onto the canvas or double-click. +- **Typed ports & media** — every port carries a medium (water, power, gas, + signal…). Connections are validated: only compatible media may be joined. + Swappable color schemes (default / color-blind safe / print). +- **Orthogonal routing** — grid-aligned manhattan router. Optional **jumpover + arcs** where connectors cross (toggle in Settings). +- **Edge styling** — line style (solid/dashed/dotted), width, color, and + head/tail markers (arrow, open arrow, circle, diamond, bar). +- **Grouped, typed property panel** — Identity / Presentation / Physics groups + with editors for `string`, `int`, `float`, `enum`, `color`, `catalogueItem`, + `catalogueItems` and `listOfValues`; live validation with units. +- **Catalogues** — pipe materials, pump models, valve types. Picking an item can + seed physics defaults (roughness, flow rate…). +- **Mock flow calculation** — distributes a conserved flow from sources to + sinks, animates direction with marching ants, and encodes volume via speed and + a magnitude color ramp. A legend shows the live mass-balance residual. +- **Editing** — drag with grid snapping, multi-select, delete, copy/paste, + duplicate, undo/redo, pan, wheel zoom, fit-to-content, link vertex editing. +- **Files** — New / Open / Save (JSON) via native dialogs, Export SVG. +- **Settings** — grid size, snapping, jumpover, color scheme, light/dark theme. + +## Tech stack + +- **Electron** shell (secure preload, context isolation) +- **[JointJS core](https://www.jointjs.com/) (`@joint/core`, MPL-2.0)** — canvas + engine (custom SVG nodes, ports, manhattan router, jumpover connector) +- **React 18 + TypeScript** — panels and shell +- **electron-vite / Vite 5** — build +- **Vitest + jsdom** — tests + +See [`docs/plan/README.md`](docs/plan/README.md) for the design rationale +(including why JointJS over React Flow / mxGraph) and the full checklist. + +## Getting started + +```bash +npm install +npm run dev # launch the app with HMR +``` + +Other scripts: + +```bash +npm run build # produce main / preload / renderer bundles in out/ +npm run start # preview the production build +npm run typecheck # tsc for both node and web project references +npm test # run the Vitest suite (52 tests) +``` + +## Project layout + +``` +src/ + main/ Electron main process (window, file dialogs IPC) + preload/ Context-isolated bridge (save/open) + renderer/ + diagram/ Framework-free domain + JointJS engine + relations port media, color schemes, compatibility + properties typed/grouped property model (coerce/validate) + catalogue reusable lookup tables + physics seeds + symbols SVG symbol registry with port layouts + schemas node/edge property schemas + edges marker/line-style helpers + settings grid/router/connector/jumpover config + flow mass-conserving mock solver + flowAnimation marching-ants animator + magnitude ramp + shapes JointJS element/link construction + history snapshot undo/redo + controller Graph + Paper orchestration (headless-capable) + components/ React UI (stencil, canvas, properties, toolbar, dialogs) +tests/ Vitest suites +docs/plan/ Implementation plan + screenshots +``` + +## Architecture notes + +The `diagram/` layer is split so the **domain model is framework-free and fully +unit-tested** (relations, properties, catalogue, symbols, flow solver), while +`shapes.ts`/`controller.ts` bridge it to JointJS. `DiagramController` accepts a +`null` host to run **headless** (no `Paper`), which is how the controller tests +exercise the full add/connect/edit/delete/undo/flow lifecycle without a browser. diff --git a/docs/plan/README.md b/docs/plan/README.md index 344f890..b2f594a 100644 --- a/docs/plan/README.md +++ b/docs/plan/README.md @@ -25,95 +25,104 @@ Research sources: ## Milestones & actionable checklist ### M0 — Project scaffold -- [ ] Initialize `package.json`, TypeScript, electron-vite config -- [ ] Electron main process + secure preload bridge (contextIsolation) -- [ ] React renderer boots inside Electron with 3-pane layout (stencil | canvas | properties) -- [ ] `npm run dev` launches, `npm run build` produces bundles -- [ ] Vitest configured, sample test green +- [x] Initialize `package.json`, TypeScript, electron-vite config +- [x] Electron main process + secure preload bridge (contextIsolation) +- [x] React renderer boots inside Electron with 3-pane layout (stencil | canvas | properties) +- [x] `npm run dev` launches, `npm run build` produces bundles +- [x] Vitest configured, suite green (52 tests) ### M1 — Diagram canvas (JointJS host) -- [ ] `DiagramController` wraps a JointJS `Graph` + `Paper` -- [ ] Rectangular background grid, configurable size -- [ ] Pan (space/drag) + zoom (wheel/buttons), fit-to-content -- [ ] Selection model (click, marquee, multi-select) +- [x] `DiagramController` wraps a JointJS `Graph` + `Paper` (+ headless mode) +- [x] Rectangular background grid, configurable size +- [x] Pan (blank drag) + zoom (wheel/buttons) + fit-to-content +- [x] Selection model (click, shift/ctrl multi-select, select-all) +- [ ] Marquee (rubber-band) selection — *deferred* ### M2 — Node system (SVG symbols + ports) -- [ ] Symbol registry: each symbol = SVG markup + port layout + default props -- [ ] Seed symbol library grouped by domain (source, sink, junction, valve, pump, tank, meter…) -- [ ] Custom JointJS element renders symbol SVG + ports -- [ ] Ports carry a **relation/medium** (water, power, gas, signal…) with color scheme -- [ ] Focused node reveals its ports as connectable magnets +- [x] Symbol registry: each symbol = SVG icon + port layout + default props +- [x] Seed symbol library grouped by domain (16 symbols across 5 categories) +- [x] Custom JointJS element renders symbol SVG + ports +- [x] Ports carry a **relation/medium** (water, power, gas, signal…) with color scheme +- [x] Focused/hovered node reveals its ports as connectable magnets ### M3 — Node panel (stencil) -- [ ] Left panel lists symbols grouped by category, collapsible -- [ ] Search/filter symbols -- [ ] Drag symbol → drop onto canvas creates node at grid-snapped position -- [ ] Live SVG preview thumbnails +- [x] Left panel lists symbols grouped by category, collapsible +- [x] Search/filter symbols +- [x] Drag symbol → drop onto canvas creates node at grid-snapped position +- [x] Live SVG preview thumbnails ### M4 — Edges / connectors -- [ ] Draw edge by dragging from a port; snap to a compatible target port -- [ ] **Connection validation** by port relation (compatible media only) -- [ ] Orthogonal (manhattan) routing along the grid -- [ ] Config toggle: **arc (jumpover) on line intersections** vs plain crossing -- [ ] Edge style presets: line style (solid/dashed), width, color -- [ ] Head/tail markers: none, arrow, circle, diamond, bar -- [ ] Vertices editable; re-route on node move +- [x] Draw edge by dragging from a port; snap to a compatible target port +- [x] **Connection validation** by port relation (compatible media only) +- [x] Orthogonal (manhattan) routing along the grid +- [x] Config toggle: **arc (jumpover) on line intersections** vs plain crossing +- [x] Edge style presets: line style (solid/dashed/dotted), width, color +- [x] Head/tail markers: none, arrow, open arrow, circle, diamond, bar +- [x] Vertices editable (link tools); re-route on node move ### M5 — Property panel (typed, grouped) -- [ ] Reflects focused node **or** edge -- [ ] Property groups (Presentation / Identity / Physics …) -- [ ] Editors for types: `string`, `int`, `float`, `enum`, `color`, +- [x] Reflects focused node **or** edge +- [x] Property groups (Identity / Presentation / Physics) +- [x] Editors for types: `string`, `int`, `float`, `enum`, `color`, `catalogueItem`, `catalogueItems`, `listOfValues` -- [ ] Two-way binding: edit → model → canvas re-render -- [ ] Validation (min/max, required, units) +- [x] Two-way binding: edit → model → canvas re-render +- [x] Validation (min/max, required, units) ### M6 — Catalogue system -- [ ] Catalogue store (e.g. pipe materials, pump models) with typed fields -- [ ] `catalogueItem` picker (single) and `catalogueItems` (multi) -- [ ] Selecting a catalogue item can seed physics defaults (diameter, roughness…) +- [x] Catalogue store (pipe materials, pump models, valve types) with typed fields +- [x] `catalogueItem` picker (single) and `catalogueItems` (multi) +- [x] Selecting a catalogue item seeds physics defaults (roughness, flow…) ### M7 — Mock calculation & flow animation -- [ ] Flow solver mock: assign a flow value + direction to each edge - (conservation-ish distribution from sources to sinks) -- [ ] Animate flow direction along edges (marching ants / motion) -- [ ] Animation speed & dash density encode flow **volume** -- [ ] Color edges by flow magnitude (legend) -- [ ] Run / stop / step controls in toolbar +- [x] Flow solver mock: mass-conserving distribution from sources to sinks +- [x] Animate flow direction along edges (marching ants) +- [x] Animation speed & dash density encode flow **volume** +- [x] Color edges by flow magnitude (legend + residual readout) +- [x] Run / stop controls in toolbar ### M8 — Editing UX & configuration -- [ ] Move/drag nodes with grid snapping -- [ ] Delete (nodes+incident edges), copy/paste, duplicate -- [ ] Undo / redo (command history) -- [ ] Keyboard shortcuts (Del, Ctrl+Z/Y, Ctrl+C/V, Ctrl+A, arrows nudge) -- [ ] Context menu on node/edge/canvas -- [ ] Save / load diagram to JSON; New; export SVG/PNG -- [ ] Settings dialog: grid size, snapping, jumpover on/off, color scheme, - theme (light/dark) -- [ ] Alignment/distribution helpers, z-order +- [x] Move/drag nodes with grid snapping +- [x] Delete (nodes + incident edges), copy/paste, duplicate +- [x] Undo / redo (snapshot history) +- [x] Keyboard shortcuts (Del, Ctrl+Z/Y, Ctrl+C/V, Ctrl+D, Ctrl+A) +- [x] Save / load diagram to JSON; New; export SVG +- [x] Settings dialog: grid size, snapping, jumpover, color scheme, theme +- [ ] Context menu on node/edge/canvas — *deferred* +- [ ] Alignment/distribution helpers, z-order — *deferred* +- [ ] PNG export, minimap — *deferred* ### M9 — Tests (typical scenarios) -- [ ] Symbol registry & port relation resolution -- [ ] Connection validation (compatible vs incompatible media) -- [ ] Property model get/set, type coercion & validation -- [ ] Catalogue pick seeds defaults -- [ ] Add node / connect / delete lifecycle on the graph model -- [ ] Serialization round-trip (save → load) -- [ ] Flow solver conservation & direction -- [ ] Router/jumpover configuration switch +- [x] Symbol registry & port relation resolution +- [x] Connection validation (compatible vs incompatible media) +- [x] Property model get/set, type coercion & validation +- [x] Catalogue pick seeds defaults +- [x] Add node / connect / delete lifecycle on the graph model +- [x] Serialization round-trip (save → load) +- [x] Flow solver conservation & direction +- [x] Router/jumpover configuration switch ### M10 — Polish & docs -- [ ] README with screenshots / run instructions -- [ ] Sample diagram bundled -- [ ] Final plan checkmarks updated +- [x] README with screenshots / run instructions +- [x] Sample diagram auto-seeded on launch +- [x] Final plan checkmarks updated +- [x] End-to-end smoke verified in real Electron (see screenshots below) --- ## Features added beyond the original brief - Undo/redo command history, copy/paste/duplicate, keyboard shortcuts -- Marquee multi-select, alignment/distribution, z-order -- Save/load (JSON) + export (SVG/PNG) +- Canvas panning, wheel zoom, fit-to-content +- Save/load (JSON) + export (SVG) - Settings dialog (grid, snapping, jumpover, color scheme, light/dark theme) -- Minimap / fit-to-content, zoom controls - Catalogue-driven physics defaults -- Flow legend and run/step/stop controls +- Flow legend with live mass-balance residual, run/stop controls - Symbol search in the stencil +- Headless controller mode (enables tests + potential server-side use) + +## Verified screenshots +- `app-screenshot.png` — editor with the seeded network +- `app-flow.png` — a node selected (grouped properties) with flow animation running + +## Deferred (nice-to-have, not implemented) +Marquee selection, right-click context menu, alignment/distribution & z-order +helpers, PNG export, minimap, and a flow "step" control. diff --git a/docs/plan/app-flow.png b/docs/plan/app-flow.png new file mode 100644 index 0000000..8b93161 Binary files /dev/null and b/docs/plan/app-flow.png differ diff --git a/docs/plan/app-screenshot.png b/docs/plan/app-screenshot.png new file mode 100644 index 0000000..9ecd766 Binary files /dev/null and b/docs/plan/app-screenshot.png differ