Commit graph

210 commits

Author SHA1 Message Date
Grovy311
8562d6eb83 cable-sizing: size for the protective device, not just the load; manual entry; icon position
- calculateCableSizing now selects cross-section against
  designCurrentA = max(operatingCurrentA, existingProtectionRatedCurrentA)
  instead of the load current alone. A breaker only trips at its own rated
  current (In), so a cable sized for the actual load could overheat under
  sustained current below that threshold - the standard In <= Iz rule.
  Voltage-drop calculation still uses the real operating current, only the
  capacity check changed. Alerts and the ok-summary now name the breaker as
  the limiting factor when it is one.
- Added a manual cable type/cross-section entry in the modal itself:
  running a calculation pre-fills these fields as a suggestion, but they
  are the single field that actually gets applied, and stay editable -
  this restores the direct manual-entry capability the modal replaced when
  it took over the cableSummary/cableCrossSection cell click.
- Fixed calculator icon position from a trailing ::after (inconsistent
  position depending on cell text length, easy to miss on empty cells) to
  a fixed-position ::before, so it is always in the same place regardless
  of whether cable data is already filled in.
- No new display for the existing protection device - it already has its
  own Schutz column in this app.
2026-08-07 18:02:28 +02:00
Grovy311
a35d04965e docs: document the grid-column coupling and its failure mode 2026-08-07 17:50:57 +02:00
Grovy311
d22f150cbe cable-sizing: trigger on both cable columns, calculator icon
Trigger now matches cableSummary OR cableCrossSection so it still
shows up regardless of which cable-related column a user has visible
(column visibility is a per-browser preference in this app, not fixed
- see docs/cable-sizing-module.md coupling note). Icon changed to a
calculator glyph.
2026-08-07 17:50:26 +02:00
Grovy311
068ec72fe2 cable-sizing: fix trigger column and add visible affordance
The trigger was wired to the cableCrossSection column, which is not in
the default visible column set - the actually visible "Kabel" column
is cableSummary (a computed cableType/cableCrossSection/cableLength
join). Editing cableSummary already maps to the remark field rather
than the underlying cable data (see buildCircuitEditPatch), so this
column was effectively a read-only display already; retargeting the
trigger there loses no existing manual-edit capability. Also adds
.cell-cable-sizing-trigger styling (mirrors .cell-protection-trigger)
so the trigger is visually discoverable, which the initial version was
missing entirely.
2026-08-07 17:49:08 +02:00
Grovy311
4f7a0c2a8c Local-only: allow cj-ki dev origin for HMR handshake
Not part of the cable-sizing proposal. next.config.mjs allowedDevOrigins
was scoped to the project owners own network; without cj-ki (192.168.0.133)
listed, Next.js 16 rejects the client HMR WebSocket handshake from this
host and the client-rendered pages (e.g. the circuit tree editor) hang on
their loading state forever, even though plain HTTP/API requests work
fine. Same root cause already documented for the sibling elt-planung-suite
project. Should not be carried over if this branch is proposed upstream.
2026-08-07 17:43:30 +02:00
Grovy311
01a024f048 cable-sizing: return 400 instead of 500 for an unknown context circuitId/projectId
context.circuitId/projectId are caller-supplied audit-log metadata, not
used in the calculation itself. A stale or unknown id (e.g. a circuit
deleted between page load and this request) violated the foreign key
and fell through to the generic 500 handler; catch it and report it as
a normal validation error instead.
2026-08-07 17:17:44 +02:00
Grovy311
bfcddee128 Local-only: remap test-deploy ports to avoid conflicts on cj-ki
Not part of the cable-sizing proposal - only needed because this host
already runs ~50 other containers using the default 3000/3001 and the
default docker network address pool was exhausted. Should not be
carried over if this branch is ever proposed upstream.
2026-08-07 17:14:07 +02:00
Grovy311
1d030971dd Add proposed cable-sizing module
Isolated module (mirrors src/external-model/ dependency direction) that
adds an on-demand, DIN VDE 0298-4 referenced cable cross-section
calculator: a click-on-a-circuit input mask for laying method,
insulation, ambient temperature, grouping and voltage-drop limit that
suggests a cross-section for the circuit cableCrossSection/cableLength
fields. Applying a suggestion goes through the existing circuit.update
command (expectedRevision, undo/redo) unchanged - nothing here writes
to circuits directly or touches the revision/command system. See
docs/cable-sizing-module.md for the full rationale, API contract,
verification status and maintenance plan. Proposal, not yet reviewed
by the project owner - see the docs file.

423 existing + 11 new tests pass, build:api/build:web/typecheck:scripts
clean.
2026-08-07 17:13:59 +02:00
a17e2e3f4b Merge remote-tracking branch 'origin/feature/amev-picker-and-collapsible-sidebar' 2026-08-06 22:01:54 +02:00
64ccd1f829 Add dark mode toggle in the sidebar
Adds a persistent dark/light theme toggle (localStorage +
data-bs-theme on <html>) so it applies globally, including the
circuit editor route which has no visible sidebar. An inline
beforeInteractive script sets the theme before hydration to avoid a
flash of the wrong theme.

Bootstrap components pick up data-bs-theme automatically; the custom
circuit-grid CSS previously used ~150 hardcoded hex colors, all
converted to semantic tokens in globals.css with light/dark values.

Verified with a headless-browser pass across the project list, project
detail page, circuit editor, project-device drawer and a settings
modal in both themes; no console errors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:56:21 +02:00
a99980c47b Update docs for the code-review fixes
- circuit-list-editor-api.md: next-identifier moved under
  /projects/:projectId and now documents its 404 scoping behavior.
- current-architecture.md: clarify that the BMK trigger register's
  DB-level normalization is ASCII-only and describe the added
  application-level Unicode-aware uniqueness check that closes the
  umlaut gap; note the additive migration 0006 indexes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:33:28 +02:00
b45dc5002d Fix code-review findings across domain, persistence, server and frontend
Full-codebase review turned up five real correctness/security bugs and
a dozen smaller inconsistencies; all are fixed here with matching test
coverage:

- BMK uniqueness silently allowed German-umlaut duplicates ("Ä1" vs
  "ä1") because the DB's normalized index only folds ASCII case. Added
  a shared Unicode-aware pre-check used by every circuit/component
  insert and rename path (one of which had no pre-check at all).
- CircuitDeviceRow.simultaneityFactor had no upper bound at the row
  level (command model and snapshot/restore schema), unlike every
  sibling entity, letting a bad value silently corrupt power totals.
- Grid cell editing silently misread German thousands-separator input
  ("1.500" parsed as 1.5); "." is now rejected outright with a clear
  message instead of guessing.
- The editor's shared command runner (runCommand/applyHistory) had no
  re-entrancy guard, so a double click/drop could fire the same
  command twice and race a BMK collision or revision conflict. Added a
  synchronous ref guard plus isSaving on the buttons that lacked it.
- GET .../next-identifier leaked circuit-numbering state for sections
  in other projects (no ownership check, 400 instead of 404). Moved
  under /projects/:projectId and scoped it.

Also: added the missing circuits.section_id / circuit_device_rows.
circuit_id indexes (migration 0006), gave FormModal a focus trap /
Escape-to-close / focus restore and rebuilt ProjectSettingsModal on
top of it instead of duplicated markup, removed dead code (3 orphaned
domain model files, an unused persistence helper, a wrapper only used
by its own test), pointed the project page at GET /projects/:id
instead of listing+filtering client-side, closed the gap between the
documented 18 MB CSV limit and the ~17.17 MiB actually enforced, added
missing upper bounds on several free-text fields, filled in nine
missing German labels in the revision timeline, replaced a
key-order-fragile JSON.stringify equality check with a real field
comparison, made an implicit sort-order assumption in three
renumbering helpers explicit, cleared the sidebar's target selection
when it no longer resolves after a tree reload, and fixed
updateGlobalDevice to check-then-write instead of write-then-check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 21:31:16 +02:00
fa96be2d42 Fix crash handling and log noise in logging feature
Review of the logging work from the previous commit turned up a real
correctness issue: the uncaughtException/unhandledRejection handlers
logged the error but let the process keep running, which silently
disabled Node's default crash-on-fatal-error behavior and could leave
a zombie process serving broken requests instead of restarting. Both
processes now log and then exit(1); restart: unless-stopped is added
to both services so Docker actually brings them back up.

Also: harden the logger against JSON.stringify throwing on
non-serializable meta, log aborted (closed-before-finished) requests
in the API access log, and stop the Next.js proxy from logging the
Docker healthcheck's request to "/" every few seconds so real
navigation events aren't drowned out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 19:58:31 +02:00
ea3c02cd6b Add configurable structured logging
Adds a leveled JSON logger (error/warn/info/verbose/debug, controlled via
LOG_LEVEL) wired into the Express API (access log, error middleware,
crash handlers, memory heartbeat) and the Next.js server (page-request
proxy, instrumentation crash handlers, heartbeat). LOG_LEVEL is exposed
through compose.yaml, and both services now rotate their Docker logs
(json-file, 20m x 10 files) instead of growing unbounded. Intended to
capture long-running diagnostic data for the intermittent 502s seen on
the Docker host.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 19:45:39 +02:00
root
f26c000007 Add local uris to nextjs config 2026-08-06 18:58:56 +02:00
Grovy311
9bd22dfcb7 Add AMEV Gleichzeitigkeitsfaktor-Auswähler und einklappbare Seitenleiste
- Gzf-Picker-Modal mit AMEV-Tabelle 3 (Planungshilfe für elektrische
  Leistungsbilanzen) im Projektgerät-Modal und im globalen Geräteformular
- Docker-Deploy-Tooling (docker-start.sh, run-migrations.js) für den
  produktiven Container
- Seitenleiste ist jetzt einklappbar (Icon-only, Zustand in localStorage)
2026-08-03 17:07:14 +02:00
74bea1a3c9 Add Revit circuit list object feed 2026-08-02 18:59:01 +02:00
a69b7b603f Add external object new circuit command 2026-08-02 18:55:57 +02:00
347b3717c3 Add external object new row command 2026-08-02 18:44:46 +02:00
1a7dd7fe03 Add external object row assignment command 2026-08-02 18:38:38 +02:00
dac19b093c Add external row quantity foundation 2026-08-02 18:26:22 +02:00
bc2bc7ece5 Add Revit catalog creation flow 2026-08-02 18:08:18 +02:00
ab2449419b Add Revit initial import wizard 2026-08-02 17:52:21 +02:00
8646f346e6 Add Revit initial import apply API 2026-08-02 17:42:29 +02:00
c9e5fdd876 Add Revit initial import planning 2026-08-02 17:38:17 +02:00
c634570018 Add atomic Revit initial import 2026-08-02 17:33:32 +02:00
e87a3289fa Include external models in project snapshots 2026-08-02 17:25:25 +02:00
76493b573e Add external model persistence foundation 2026-08-02 17:18:24 +02:00
d0fc1a7caf Widen Revit CSV dialog 2026-08-02 17:10:22 +02:00
a9d6301753 Add Revit CSV project dialog 2026-08-02 16:59:18 +02:00
caa6caf99f Add Revit CSV preview API 2026-08-02 16:49:42 +02:00
219da5ec3b Persist Revit CSV configuration 2026-08-02 16:33:18 +02:00
da689af518 Verify Revit reference CSV 2026-08-02 16:01:05 +02:00
bfe8b790b2 Add Revit CSV transport 2026-08-02 15:56:02 +02:00
43cee890e7 Define Revit CSV contracts 2026-08-02 15:51:52 +02:00
927b868dcb Plan Revit CSV integration 2026-08-02 15:47:12 +02:00
c96ba1cbaf Added revit specs 2026-08-02 15:38:02 +02:00
44b6fde940 Add public building project setting 2026-07-31 17:41:30 +02:00
43a3bb0b69 Align documentation with clean baseline 2026-07-31 16:41:37 +02:00
facf788ce8 Remove circuit structure preview 2026-07-31 14:52:37 +02:00
1eed19ef6b Add editable project floors and rooms 2026-07-31 14:46:06 +02:00
1e3c721cfa Derive project device phases from category 2026-07-31 14:37:45 +02:00
5fb81bab04 Support decimal commas and cell units 2026-07-31 14:33:47 +02:00
734a2bcfc4 Create clean release database baseline 2026-07-31 14:07:26 +02:00
5bee3cb103 Add distribution board copy and delete controls 2026-07-31 12:03:52 +02:00
86f1d42e60 Expose distribution board copy and delete API 2026-07-31 11:59:31 +02:00
0fd564a930 Persist complete distribution board subtrees 2026-07-31 11:57:10 +02:00
13693f64b1 Model complete distribution board subtrees 2026-07-31 11:51:46 +02:00
bd8dd09f79 Open circuit protection from grid cell 2026-07-31 10:02:11 +02:00
54874f9fcb Render circuit protection values 2026-07-31 09:56:49 +02:00