4.8 KiB
Circuit List Editor Architecture
Purpose
The circuit-list editor is a circuit-first planning workspace for distribution-board design. It is optimized for spreadsheet-like editing while preserving electrical domain boundaries: circuit-level data stays on circuits, and load rows stay inside circuits.
Frontend Grid Modules
circuit-tree-editor.tsxowns React state, API commands, undo/redo and drag-and-drop orchestration.circuit-grid-model.tsowns column metadata, circuit/device cell ownership, value projection, formatting, numeric parsing and block sort values.circuit-grid-projection.tsowns block-preserving filtering/sorting and the normalized visible row projection.circuit-grid-insertion.tsresolves insertion intent and insertion sort positions.circuit-grid-safety.tsresolves delete intent, BMK conflicts and cross-section move confirmation requirements.
The pure grid modules have no React state and are covered by focused unit tests. This keeps circuit/device ownership rules testable while the editor UI is split incrementally.
Domain Model Overview
CircuitSection- Groups circuits by planning section (for example lighting, single-phase, three-phase).
- Owns section metadata (
key,displayName,prefix, ordering).
Circuit- Core electrical unit in the list.
- Owns circuit-level identifiers and technical data:
equipmentIdentifier(BMK)- protection data
- cable data
- reserve state
- voltage and optional control requirement for future sizing
- circuit-level remark/status
CircuitDeviceRow- Load/device line inside a circuit.
- Owns row-level load and context values:
quantitypowerPerUnitsimultaneityFactorcosPhi- room snapshots
- category/cost group and related row attributes
ProjectDevice- Reusable device template entity at project level.
- Can be linked to
CircuitDeviceRowentries, with copied display values on insert.
- Retained legacy migration source
- Old
consumersrows, mappings and reports are available only to explicit database upgrade tooling. - They are not application-domain entities and have no UI or API.
- Old
Why A Circuit Is Not One Row
A circuit can contain zero, one, or many device rows. Treating a circuit as a single row breaks:
- BMK ownership (belongs to circuit, not each device row)
- circuit-level protection/cable fields
- grouped calculations and circuit move/reorder semantics
The tree model keeps circuit identity stable while allowing row-level load composition.
Rendering Model: Single vs Multi Device
- Single-device circuit:
- Rendered as compact combined row (
circuitCompact) for fast editing.
- Rendered as compact combined row (
- Multi-device circuit:
- Rendered as one circuit summary row (
circuitSummary) plus indenteddeviceRowentries.
- Rendered as one circuit summary row (
This keeps visual density high without losing ownership boundaries.
Reserve / Empty Circuits
Circuits with no device rows are rendered as reserve rows (reserveCircuit).
Section-level -frei- placeholder rows represent insertion targets for creating a new circuit in that section.
BMK Ownership (equipmentIdentifier)
equipmentIdentifier / BMK is circuit-owned (Circuit.equipmentIdentifier).
- Device rows do not have their own BMK.
- Existing identifiers must stay stable unless explicitly changed by user action.
- Renumbering is explicit, not implicit on move/sort/delete.
Data Ownership Split: Circuit vs Device Row
Circuit-level fields on Circuit:
- protection type/rating/characteristic
- cable type/cross-section/length
- RCD/terminal/status
Device-level load fields on CircuitDeviceRow:
- quantity, power per unit, simultaneity, cosPhi
- row naming/categorization and room snapshots
This split matches execution-design workflows where many loads share one protective path.
Calculated Totals
rowTotalPoweris calculated perCircuitDeviceRow.circuitTotalPoweris calculated as sum of all row totals in one circuit.
Totals are exposed by the tree response and shown in computed read-only cells.
Frontend Route
Primary circuit-first editor route:
/projects/:projectId/circuit-lists/:circuitListId/tree-edit
The sibling /tree route is a read-only structure preview. Old
/projects/:projectId/circuit-lists bookmarks redirect to the project page.
Future Persistence Direction
Persistent undo/redo, project revisions, logical snapshots, external-model exchange and PostgreSQL readiness are specified in Project History and External Model Architecture.
Critical multi-write commands already use explicit persistence transaction adapters. The next step is to compose these command boundaries into server-side, project-scoped revisions and change sets. Database backups remain separate from user-visible project snapshots.