Commit graph

117 commits

Author SHA1 Message Date
4ff01b2ccd Harden Linear XLSX end to end 2026-09-30 21:02:20 +02:00
2581beee3c Add Linear XLSX follow-up import 2026-09-30 20:40:40 +02:00
1a4c8cad8c Add Revit return workbook export 2026-09-30 15:15:17 +02:00
77d775fde1 Complete Revit object editor assignments 2026-09-30 14:35:14 +02:00
4489cd76f0 Allow saving default Revit settings 2026-09-30 13:51:43 +02:00
4ac32e103d Add virtualized Revit object planning 2026-09-30 10:03:36 +02:00
bfdd048269 Add Linear XLSX initial import 2026-09-30 09:50:58 +02:00
c633e78cd4 Add Revit XLSX settings page 2026-09-30 09:02:52 +02:00
847f4e9493 Harden user management integration 2026-09-28 22:42:03 +02:00
73579d1e79 Merge branch 'main' into feature/user-management 2026-09-28 22:32:48 +02:00
9165b8238c Compact single-board feeder circuit rows 2026-09-28 22:14:39 +02:00
Grovy311
95bfba2f67 Merge origin/main into feature/user-management
Renumber the users migration to 0013_users so it follows the upstream
0012_good_gateway (logical board feeds); AGENTS.md deferred-work list keeps
both the new feed items and the auth items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:46:21 +02:00
Grovy311
5073d9342a Harden authentication and put filter toggle and fields in one row
Security: per-username login throttling, constant-time unknown-user check,
Sec-Fetch-Site CSRF guard for writes, session rotation on login and
password change, absolute session lifetime, sessions ended on reset and
deactivation, last-admin protection, input length caps, ASCII usernames,
clickjacking headers. Covered by tests/authentication.test.ts.

Filter panel: toggle, fields and count share one row to save space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:30:30 +02:00
Grovy311
8d2948cdb1 Match sidebar bottom layout to the Wochenplanung reference (theme toggle + Abmelden in one row)
Square icon-only theme toggle sits next to the Abmelden button in a shared
row, collapsing to just the toggle when the sidebar is collapsed - same
arrangement as pm-app's Sidebar.tsx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 20:32:26 +02:00
Grovy311
c56cfb30ad Add login-required user management (admin/user roles, Config->Benutzer)
No self-signup: admins create every account in Config -> Benutzer with a
typed start password; a forced password change gates first use. Session-
cookie auth protects all /api/* routes; /api/users additionally requires
the admin role. See docs/authentication.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 19:51:47 +02:00
042a050876 Show logical feeder loads in project and circuit views 2026-09-27 22:37:04 +02:00
dce31ee143 Add optional room areas 2026-09-27 20:00:03 +02:00
a6500e2b26 Add estimate row project device handoff 2026-09-27 18:36:48 +02:00
5cbbd3a84a Align cable sizing with DIN VDE 0298-4 2026-09-27 17:01:23 +02:00
598003554a Merge remote-tracking branch 'origin/main' into feature/cable-sizing 2026-09-27 16:54:12 +02:00
573487666c Integrate rough estimate balance 2026-09-27 12:37:59 +02:00
868f48e7ac Integrate project building structure 2026-09-27 10:45:10 +02:00
4643c8d11a Integrate print view and document branding 2026-09-27 10:32:07 +02:00
2e223be8b4 Integrate project overview filters and icon actions
Document filter combinations, reset and browser persistence. Keep the search hint applicable before board information fields are introduced.

Validation: 20 focused tests, 431 total tests, API/web builds, scripts and Next typechecks, and diff checks passed. GUI retest skipped as authorized based on the colleague's prior testing.
2026-09-26 21:16:48 +02:00
641513c2ef Integrate circuit list navigation and AMEV cell picker
Preserve the ID fallback and compact editor controls. Add dialog keyboard focus, Tab containment and Escape handling; document navigation and picker behavior.

Validation: 418 tests, API/web builds, scripts and Next typechecks, isolated AMEV dialog checks and diff checks passed. Full GUI retest waived by the user based on the colleague's prior testing; the keyboard follow-up was checked in isolation.
2026-09-26 21:14:20 +02:00
203757b92c Integrate compact editor actions and fix header units 2026-09-26 21:07:36 +02:00
Grovy311
37a70b6b36 Add the rough power balance module for early design phases
In LPH 2/3 there are no circuits yet, but the office needs a power
balance by DIN 276 cost group, as in the Excel template "Leistungsbilanz -
KG400": each trade enters consumers by piece or by area (W/m²) with GLF
and cos phi; the balance sums AV and SV per cost group, adds a reserve and
derives the maximum current.

The module is separate from the circuit structure: own tables
(migration 0010), own folder src/estimate-balance and an import-free
shared calculation used by API and UI. Writes go through project commands
(estimate-balance.insert/.update/.delete with complete documents), so
revision checks and Undo/Redo apply; it is not part of project snapshots
or transfer yet. A comparison endpoint sums the device rows of all circuit
lists by cost group (longest prefix) against the estimate.

The UI adds a sidebar entry, a list of Stände (template KG 400, empty or
copy) and a spreadsheet-like editor with autosave, AMEV picker for the
GLF, totals, reserve, maximum current, comparison table and print layout.
The tests reproduce the template example exactly (143.24 kW, 148.48 kVA,
157.56 kW / 163.33 kVA with 10 % reserve, 235.75 A). See
docs/estimate-balance.md and issue #7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 17:39:28 +02:00
Grovy311
80dbc73230 Merge fix/client-id-insecure-context for client-side ids 2026-09-26 14:22:35 +02:00
Grovy311
837b29c7c5 Add icon actions and collapsible filters to the project overview
The overview now uses the same icon buttons as the circuit list editor:
row actions are icon-only IconButtons (Pencil, Link2, Library, Trash2),
card-header and panel actions show icon plus text, and the circuit-list
link uses the new IconLink. The version history uses Undo2/Redo2, a
chevron toggle and a RotateCcw restore action. Page-header buttons stay
Bootstrap buttons with a lucide icon so the upcoming "Seitenansicht"
button of feature/print-view merges without conflicts and matches them.

The Verteilungen and Projektgeräte cards get a PM-style filter bar:
search plus MultiSelectDropdown (checkbox list with "Alle", closes on
outside click and Escape) and "Zurücksetzen" while a filter is active.
Only the bar collapses; the state is kept per card in localStorage and a
collapsed active filter shows "Filter aktiv". The header row shows
"x von y", and an empty-state row explains when filters hide everything.
The filter logic is a pure module (overview-filters.ts) with node tests;
selections that are no longer offered (deleted floor) are ignored.

IconButton now imports React explicitly like the other components that
are rendered in node tests with the classic JSX runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 13:01:31 +02:00
Grovy311
5f4d9bf789 Show the sidebar on every page except the print view
AppShell showed the sidebar only on the project list and overview, so it
disappeared on the building structure page and in the circuit list
editor. It is collapsible, so it now stays on every page. Only the print
view, a stand-alone document opened in its own tab and printed as PDF,
keeps the full width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 13:00:20 +02:00
Grovy311
cd89c4a499 Add buildings above floors and a building structure page
Projects with several buildings could not be structured: floors and rooms
hung directly off the project. Floors can now belong to a building
(migration 0009: table buildings, nullable floors.building_id). Rooms and
distribution boards keep their floor; their building follows from it.
Existing floors stay without a building.

Buildings use the location-structure command store with
project-building.insert/.update/.delete, inverses and persistent Undo/Redo;
deleting a building with assigned floors is rejected. Floor commands carry
buildingId since command version 2. Version 1 floor commands from existing
history predate buildings and are upgraded with buildingId = null before
they are executed and persisted, so forward and inverse keep one version.

Project snapshot schema 7 stores buildings and floor.buildingId; versions
1-6 are upgraded without buildings. Restore and portable transfer include
buildings, and the transfer remaps building ids.

Buildings, floors and rooms move from the project overview to their own
page /projects/:id/struktur with three columns (Gebäude -> Etagen -> Räume)
that filter each other, and a sidebar entry. Floor selects in the board and
room dialogs are grouped by building. Unchanged dialogs close without a
command. Details in docs/building-structure.md; see issue #6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:52:34 +02:00
Grovy311
79fcb75ffb Create client ids without crypto.randomUUID
crypto.randomUUID() is only defined in secure contexts (HTTPS or
localhost). Opened over plain HTTP from another machine in the LAN, the
circuit list editor failed with "crypto.randomUUID is not a function"
whenever it created a circuit, device row, circuit group or distribution
board component, including typing into the -frei- row.

createClientId() uses crypto.randomUUID() where available and otherwise
builds an RFC 4122 version 4 UUID from crypto.getRandomValues(), which
works in every context. AGENTS.md notes the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:01:43 +02:00
Grovy311
ced4917a86 Offer the AMEV simultaneity-factor table in the circuit list
The selected GZF cell shows a small table-icon button, and Alt+ArrowDown opens
the same picker from the selected or edited cell; Escape closes it. The
shared GzfPickerModal is reused. The picked mean value is committed through
commitEdit with an explicit target cell, so it is a regular undoable edit on
device rows, compact circuits, reserve circuits and the -frei- row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:52:38 +02:00
Grovy311
49488f4e1b Add optional cable-sizing module
Per-circuit cross-section recommendation as a separate module attached to
the circuit list. It never writes project data itself: "Übernehmen" applies
cable type, cross-section and length through the regular circuit.update
command, so revisions and Undo/Redo stay intact.

- Pure domain module (src/cable-sizing) with IEC 60364-5-52:2009 Annex B
  tables for PVC and XLPE, copper and aluminium, methods A1, A2, B1, B2, C,
  D1, D2 and E. Every value was cross-checked against public reproductions;
  where sources differ the lower value is used (docs/cable-sizing-module.md).
- Temperature and grouping between table values round to the safer value;
  values outside the tables return no result instead of a factor of 1.
  Ground methods use B.52.18 (D2) and B.52.19 A (D1).
- Overload protection: circuit-breakers In <= Iz; gG fuses additionally
  I2 <= 1.45 Iz with I2 = 1.6/1.9/2.1 In.
- Inputs prefilled from the circuit: power, phase (group or device rows),
  project voltage, power-weighted cos phi, length and protective device.
- Opened from a "Leitungsberechnung" button in the row actions, not from a
  grid cell, so cable cells keep the spreadsheet behavior.
- Stateless API under /api/cable-sizing; no database table or migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:16:18 +02:00
Grovy311
7692699ee2 Add print cover fields and office profile
- Project settings gain siteAddress, workStage, projectLead and
  projectEditor (project.update-settings schema version 3, migration 0009);
  versions 2 and 1 stay executable and keep the current cover values.
  Snapshot schema 6 carries the fields; older versions upgrade with null.
- Global office profile (office name/address) next to the document logo:
  table document_branding_settings, PUT /api/document-branding/office,
  editable from the print view toolbar.
- Cover page reads all fields; empty values show the "[ergänzen]" marker.
  The Planstände editor column shows the project editor.
- Shared logo constants moved to a dependency-free module so the Next.js
  bundler can import them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:39:18 +02:00
Grovy311
4779e4a1a7 Add print view, board info card and document logo upload
- Seitenansicht (/projects/:projectId/print): tabular cover page, board
  overview with supply structure and power sums, one plan per board with a
  repeating title block; PDF via the browser print dialog with named @page
  rules (A4 portrait cover, A4/A3 landscape plans, page x of y).
- Distribution-board info card (board number, location, fed-from, remark)
  in the board edit dialog, persisted through the additively extended
  distribution-board.update command (migration 0008, snapshot schema 6,
  legacy subtree commands normalized).
- Global document logo upload (PNG/JPEG/SVG, max 2 MB) outside project
  revisions and snapshots.
- fed-from stays free text; the overview hierarchy and cumulated sums are
  preliminary until the feed link is modeled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:38:59 +02:00
Grovy311
d95f0bf5c0 Compact circuit list column headers with filter icons
- Replace the "Filtern" text buttons with a funnel icon next to the column
  label; an active filter is highlighted and shows its value count.
- Header labels no longer break inside words (e.g. "Bemerkung"); hyphens
  are non-breaking and a trailing unit moves to its own line, so all
  headers share one height.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:30:15 +02:00
Grovy311
e394ff93f4 Use icon buttons in the circuit list editor
- New IconButton/IconButtonSeparator component based on lucide-react.
- Toolbar: icon plus text, grouped into history, view and insert blocks.
- Group headers: compact icons for add circuit, upstream fuse (VS), group
  RCD (FI), edit, move up/down, renumber and delete; the header no longer
  overflows the grid.
- Rows: add device, delete circuit (trash) and delete device (ListX).
- The previous German labels remain accessible names and tooltips;
  destructive actions highlight in the danger color.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:23:36 +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
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
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
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
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
44b6fde940 Add public building project setting 2026-07-31 17:41:30 +02:00
facf788ce8 Remove circuit structure preview 2026-07-31 14:52:37 +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