Files
leistungsbilanz-ts/docs/circuit-list-editor-interactions.md
T

147 lines
6.8 KiB
Markdown

# Circuit List Editor Interactions
## Editing Model
Inline cells are static text by default. A cell enters edit mode by:
- double-click
- `Enter`
- `F2`
- typing a printable character (type-to-edit)
`Enter` confirms changes. `Escape` cancels current edit draft. `Tab` and `Shift+Tab` confirm and move to next/previous editable cell.
Committed cells on existing circuits and device rows are persisted as typed
project commands with an optimistic project revision. Only the edited fields
are included, so an older tree response cannot write unrelated fields back.
The server records the inverse in the same transaction.
## `selectedCell` vs `editingCell`
- `selectedCell` tracks spreadsheet navigation focus.
- `editingCell` tracks active input draft (`draft`, edit mode, focus token).
The editor can have a selected cell without an active editor input. `editingCell` is only set while editing.
## Normalized Visible Grid
The UI works from a normalized `visibleRows` model built from filtered/sorted sections:
- section header rows
- circuit rows (`circuitCompact`, `circuitSummary`, `reserveCircuit`)
- device rows (`deviceRow`)
- section placeholder rows (`placeholder`)
Selection, keyboard movement, and editability checks run against this normalized grid, not directly against nested API JSON.
## Keyboard Behavior
- `Enter`: start edit (when not editing) or commit (when editing input)
- `F2`: start edit on selected cell
- `Escape`: cancel edit draft, or clear multi-row selection when not editing
- `Tab` / `Shift+Tab`: move between editable cells (commits active edit)
- arrow keys: move selected cell in grid when not editing
- type-to-edit: printable keys open edit mode and replace current display value with typed character
- `Ctrl+Plus` / `Ctrl+Shift+Plus`: insert below the selected circuit or device context
- `Delete`: delete the selected circuit or device context after confirmation
For insertion, a circuit-level cell creates a reserve circuit directly after the selected circuit. A device-level cell creates a manual device row directly after the selected device. On the virtual `-frei-` row, or without a valid row selection, the shortcut creates a circuit at the end of the active section. Insertions use command history and never renumber existing equipment identifiers.
For deletion, a circuit-level cell targets the complete circuit and a device-level cell targets only the device row. Deleting the last device requires an explicit choice between keeping the empty circuit as reserve, deleting the complete circuit, or cancelling. Delete commands are undoable and never renumber remaining circuits.
Creating or deleting a device row updates the row and the circuit reserve state in one SQLite transaction.
## Equipment Identifier Validation
Equipment identifiers are compared case-insensitively after trimming whitespace. A conflicting edit is highlighted before submission and cannot be committed. Existing conflicts are highlighted in the grid. Validation errors remain dismissible above the editor instead of replacing the complete workspace.
## `-frei-` Placeholder Behavior
Each section has a trailing placeholder row showing `-frei-` in BMK column:
- serves as drop target for creating new circuits from project devices or moved rows
- editable placeholder cells can create a new circuit + first row through the same edit command flow
- a new circuit and its initial row(s) are created in one SQLite transaction
## Add Circuit Behavior
Add-circuit actions create reserve circuits in the active section using the section prefix and next numeric suffix (`max + 1`).
No automatic gap-filling or global renumbering is performed.
## Drag-and-Drop Behavior
Intent is separated by drag source type:
- project device drag:
- drop to section/placeholder -> create new circuit with linked row
- the new circuit and linked row are committed atomically
- drop to existing circuit row -> append row to that circuit
- lighting devices are accepted only by the lighting section
- other devices are accepted only by the section matching their phase type
- invalid targets show rejection feedback and do not create data
- device row drag:
- drop to existing circuit -> move row(s) into that circuit
- drop to placeholder -> create new target circuit and move row(s)
- crossing a section boundary requires explicit confirmation
- phase type, category, linked project device and local row values remain unchanged
- target creation, row assignments and reserve-state updates use one SQLite transaction
- circuit drag (BMK handle):
- reorder circuits inside same section only
- cross-section reorder is rejected
- the complete section order is validated and stored in one SQLite transaction
- bulk device row move:
- supported via multi-selection + drag
- multi-circuit move:
- supported for same-section selected circuit blocks
The sidebar insertion controls use the same project-device placement rules as drag-and-drop. Invalid section and circuit options are disabled after selecting a project device.
Cross-section device moves show confirmation-required feedback before drop. The confirmation names source and target sections and warns that the unchanged device classification may need manual review. Cancelling leaves every row and circuit unchanged. Moving never renumbers existing circuits.
## Filtering and Sorting
- Per-column filtering works on normalized displayed values.
- Sorting is view-level first and treats circuits as blocks.
- Multi-device circuits are not split during sort.
- Sorting alone does not persist order.
## Apply Sorted Order
`Apply sorted order` persists current sorted block order to backend by section.
- disabled while filters are active
- undoable via command history
- each complete section order is stored atomically
- until applied, sort remains view-only
## Column Configuration
- Column visibility and order are configurable.
- BMK column (`equipmentIdentifier`) is locked as first column.
- Layout is saved in local storage (`circuitTreeEditor.columnLayout.v1`).
## Undo/Redo
Undo/redo wraps editor operations as command objects and reloads the tree after
each command. Existing Circuit and device-row cell edits plus standalone
insert/delete actions execute persistent project commands; their toolbar
undo/redo calls the project-wide server history. New entities receive stable
UUIDs before insertion, and deletion undo restores those same ids. Move,
reorder and renumber operations still use their existing direct API writes and
session-local inverse callbacks during the cutover.
Covered operations include:
- insert/delete circuit
- insert/delete row
- edit cell values
- moves (single/bulk rows, circuit reorder)
- renumber and identifier update flows
- apply sorted order
Current limitations:
- the visible editor stack is still session-local and is empty after reload
- move, reorder and renumber editor actions are not connected to the persistent
command boundary yet