Integrate print view and document branding
This commit is contained in:
commit
4643c8d11a
59 changed files with 8852 additions and 75 deletions
|
|
@ -12,6 +12,8 @@ ausdrücklich getrennt und dürfen nicht als bereits implementiert verstanden we
|
|||
fachliches Modell und Grid-Aufteilung
|
||||
- [Editor-Interaktionen](circuit-list-editor-interactions.md) – Tastatur,
|
||||
Drag-and-drop, Sortierung, Filterung und Undo/Redo
|
||||
- [Seitenansicht und PDF-Export](print-view.md) – Deckblatt,
|
||||
Verteilerübersicht, Verteilerpläne, Büro-Logo
|
||||
- [Editor-API](circuit-list-editor-api.md) – unterstützte Circuit-First-Endpunkte
|
||||
- [Bekannte Einschränkungen](circuit-list-editor-known-limitations.md) –
|
||||
bewusst noch nicht implementierte oder begrenzte Funktionen
|
||||
|
|
|
|||
|
|
@ -74,8 +74,9 @@ Protected-board structure uses
|
|||
persisted inverse of a delete. The dispatcher also supports the documented
|
||||
project-device, project settings, distribution-board and project-location
|
||||
commands. The generic editor commands listed here use schema version `1`.
|
||||
`project.update-settings` uses version `2` and still accepts supported baseline
|
||||
version `1` commands without changing the newer building classification.
|
||||
`project.update-settings` uses version `3` (including the print cover fields)
|
||||
and still accepts version `2` and supported baseline version `1` commands
|
||||
without changing the newer cover fields or building classification.
|
||||
Pre-baseline formats remain unsupported. Unsupported types or schema versions
|
||||
are rejected. Insert commands contain the complete entity or circuit block
|
||||
with stable ids; delete commands include the expected parent identity. Circuit
|
||||
|
|
@ -173,6 +174,9 @@ synchronizes linked circuit rows implicitly.
|
|||
- `PUT /projects/:projectId`
|
||||
- request:
|
||||
`{ "expectedRevision": 12, "isPublicBuilding": true, "singlePhaseVoltageV": 230, "threePhaseVoltageV": 400, "enabledDistributionBoardSupplyTypes": ["AV", "MSR", "SiBe"], ...projectMetadata }`
|
||||
- optional print cover fields `siteAddress` (max. 500), `workStage` (max.
|
||||
100), `projectLead` and `projectEditor` (max. 200 each); omitted fields keep
|
||||
their value, empty strings are stored as `null`
|
||||
- executes `project.update-settings` as one atomic revision
|
||||
- response:
|
||||
`{ "project": { ... }, "revision": { ... }, "history": { ... } }`
|
||||
|
|
@ -230,9 +234,13 @@ returns HTTP `409` with `PROJECT_HISTORY_OPERATION_UNAVAILABLE`.
|
|||
- stale revisions return `409 PROJECT_REVISION_CONFLICT`
|
||||
- `PUT /projects/:projectId/distribution-boards/:distributionBoardId`
|
||||
- body:
|
||||
`{ "floorId": null, "supplyType": "AV", "expectedRevision": 13 }`
|
||||
- executes `distribution-board.update`; floor and supply type are restored
|
||||
together by persistent Undo/Redo
|
||||
`{ "floorId": null, "supplyType": "AV", "simultaneityFactor": 1, "expectedRevision": 13 }`
|
||||
- optional info-card fields: `boardNumber` (max. 50), `location`,
|
||||
`fedFrom` (max. 200 each) and `remark` (max. 2000); strings are trimmed
|
||||
and an empty string is stored as `null`
|
||||
- executes `distribution-board.update`; all submitted values, including the
|
||||
submitted info fields, are restored together by persistent Undo/Redo
|
||||
- `fedFrom` is free text until the logical feed link is modeled
|
||||
- `POST /projects/:projectId/distribution-boards/:distributionBoardId/copy`
|
||||
- body: `{ "name": "UV-02 Kopie", "expectedRevision": 14 }`
|
||||
- duplicates the complete distribution-board subtree with new owning UUIDs
|
||||
|
|
@ -425,3 +433,27 @@ project device never triggers synchronization implicitly.
|
|||
Parser errors expose stable codes such as `header-not-found`,
|
||||
`ambiguous-header`, `invalid-ifc-guid` and `duplicate-ifc-guid`. The confirmed
|
||||
import uploads and parses the file again and verifies its hash.
|
||||
|
||||
## Document Branding (print view)
|
||||
|
||||
Office-wide branding for the print view. These endpoints are mounted at
|
||||
`/api/document-branding`, outside `/api/projects`, because the data is global
|
||||
and intentionally not part of project revisions, snapshots or transfer.
|
||||
|
||||
- `GET /document-branding`
|
||||
- returns `{ "logo": { "mimeType", "fileName", "sizeBytes", "updatedAtIso" } | null, "office": { "officeName", "officeAddress" } }`
|
||||
- `GET /document-branding/logo`
|
||||
- returns the stored image bytes with its media type, or `404` without logo
|
||||
- responses carry `X-Content-Type-Options: nosniff` and a restrictive
|
||||
Content-Security-Policy so an SVG logo cannot execute scripts
|
||||
- `PUT /document-branding/logo`
|
||||
- request: `{ "fileName": "logo.png", "mimeType": "image/png", "contentBase64": "..." }`
|
||||
- accepted types: `image/png`, `image/jpeg`, `image/svg+xml`; at most 2 MB
|
||||
after decoding; the content signature must match the declared type
|
||||
- replaces an existing logo; returns the logo metadata
|
||||
- `DELETE /document-branding/logo`
|
||||
- removes the logo; returns `204`
|
||||
- `PUT /document-branding/office`
|
||||
- request: `{ "officeName": "…" | null, "officeAddress": "…" | null }`
|
||||
(at most 200 / 500 characters; empty text is stored as not set)
|
||||
- returns `{ "office": { "officeName", "officeAddress" } }`
|
||||
|
|
|
|||
|
|
@ -27,3 +27,12 @@
|
|||
- Protection and cable values are planner-owned manual selections. The later
|
||||
sizing/warning engine does not yet validate them against load, length or
|
||||
voltage-drop rules.
|
||||
- Distribution-board `fedFrom` is free text. The print overview derives its
|
||||
supply structure and "Σ inkl. unterlagert" only from exact text matches with
|
||||
board numbers/names and adds values without an upstream simultaneity factor
|
||||
(see `docs/print-view.md`).
|
||||
- The print view uses a kbp corporate design derived from logo and
|
||||
presentation material. Snapshots do not record an editor, so the cover's
|
||||
Planstände list shows the project's current editor for every entry. On screen, long
|
||||
board plans are not split into pages; pagination happens in the browser print
|
||||
dialog.
|
||||
|
|
|
|||
|
|
@ -241,8 +241,9 @@ und Historienstapel teilen dieselbe Transaktion. Create, Import aus der globalen
|
|||
Gerätebibliothek und Delete laufen über dieselbe Command-Grenze; ihre Antworten
|
||||
liefern Gerät und aktualisierten Historienstand an die Projektseite zurück.
|
||||
`project.update-settings` versioniert Projektname, interne und externe
|
||||
Projektnummer, Bauherr, Beschreibung, die Kennzeichnung als öffentliches
|
||||
Gebäude, beide Standardspannungen sowie die im Projekt freigeschalteten
|
||||
Projektnummer, Bauherr, Beschreibung, die Deckblattangaben (Anschrift,
|
||||
Leistungsphase, Projektleitung, Bearbeitung; Schema-Version 3, Migration
|
||||
`0008`), die Kennzeichnung als öffentliches Gebäude, beide Standardspannungen sowie die im Projekt freigeschalteten
|
||||
Verteiler-Netzarten als eine atomare Änderung. Die Gebäudekennzeichnung ist
|
||||
der spätere Eingang für die Auswahl halogenfreier Kabel und Leitungen. Der
|
||||
Systemkatalog besteht aus `AV`, `SV`, `EV`, `USV`, `MSR` und `SiBe`; mindestens
|
||||
|
|
@ -271,7 +272,8 @@ Die allgemeinen Anwendungskarten verwenden in `src/app/globals.css` einen
|
|||
gleichmäßigen Rahmen, 16-px-Rundungen und einen Schatten mit eigener
|
||||
Dark-Mode-Abstimmung. Bootstrap-Karten mit `shadow-sm` nutzen denselben
|
||||
Schatten; der Stromkreis-Grid bleibt eine eigenständige Komponente.
|
||||
Die Verteilersuche berücksichtigt aktuell Name und Etagenname; die Gerätesuche
|
||||
Die Verteilersuche berücksichtigt Name, Verteilernummer, Örtlichkeit und
|
||||
Etagenname; die Gerätesuche
|
||||
Name, Anzeigename, Kategorie einschließlich deutscher Bezeichnung, Anschlussart
|
||||
und Kostengruppe. Der Gerätefilter „Anschluss“ wählt zwischen 1- und 3-phasig.
|
||||
Mehrere Werte innerhalb eines Filters gelten alternativ, verschiedene Filter
|
||||
|
|
@ -450,7 +452,14 @@ wieder her.
|
|||
verteilerweiten Gleichzeitigkeitsfaktor gemeinsam und stellt alle Werte über
|
||||
dauerhaftes Undo/Redo wieder her. Der Faktor liegt zwischen `0` und `1` und
|
||||
ist für bestehende sowie neu angelegte Verteilungen standardmäßig `1`.
|
||||
Snapshot-Schema 5 enthält zusätzlich den manuellen Mengenanteil jeder
|
||||
Derselbe Befehl versioniert die Felder der Verteiler-Infokarte
|
||||
(`boardNumber`, `location`, `fedFrom`, `remark`, Migration `0007`). Die
|
||||
Infokarte liegt im Bearbeiten-Dialog der Verteilung; die Werte sind lokale
|
||||
Planungswerte und sollen später über den Revit-Abgleich nur nach Vorschau und
|
||||
ausdrücklicher Bestätigung vorbelegt werden. `fedFrom` ist vorerst Freitext.
|
||||
Snapshot-Schema 6 enthält diese Felder und die Deckblattangaben des
|
||||
Projekts; ältere Versionen werden mit `null`
|
||||
hochgestuft. Snapshot-Schema 5 enthält zusätzlich den manuellen Mengenanteil jeder
|
||||
Gerätezeile. Version 4 wird mit `manualQuantity = quantity` hochgestuft und
|
||||
enthält bereits den vollständigen externen Modellzustand
|
||||
aus Quelle, Batches, Raum-Mappings und Objekten. Es enthält außerdem die
|
||||
|
|
@ -520,7 +529,7 @@ Kopieren in ein Projekt erzeugt ein eigenständiges Projektgerät.
|
|||
`toLowerCase()` gegen das vollständige Register der Stromkreisliste und wird
|
||||
von jedem Anlage-/Umbenennungspfad für Stromkreise und Verteilerkomponenten
|
||||
aufgerufen, auch dort, wo zuvor kein Vorab-Check existierte. Snapshot- und
|
||||
Transfer-Integration verwenden aktuell Snapshot-Schema 5. Persistente
|
||||
Transfer-Integration verwenden aktuell Snapshot-Schema 6. Persistente
|
||||
Insert/Delete/Update-Commands für veränderliche Verteilerkomponenten,
|
||||
Gruppen einschließlich befüllter Unterbäume sowie vollständige
|
||||
Gruppensortierung sind integriert. Der Editor zeigt die geschützte Struktur
|
||||
|
|
@ -548,7 +557,7 @@ einschließlich BOM, CRLF und Quotierung bytegleich zurück. Der lokale Befehl
|
|||
|
||||
`external_csv_configurations` enthält höchstens eine versionierte Konfiguration
|
||||
je Projekt. `external-csv-configuration.update` schreibt Anlage, Änderung oder
|
||||
Entfernung zusammen mit Revision und persistentem Undo/Redo. Snapshot-Schema 5,
|
||||
Entfernung zusammen mit Revision und persistentem Undo/Redo. Snapshot-Schema 6,
|
||||
Restore und portabler Projekttransfer enthalten diesen Zustand; beim Duplizieren
|
||||
werden Konfigurations-UUID und Projektlink remapped.
|
||||
|
||||
|
|
|
|||
127
docs/print-view.md
Normal file
127
docs/print-view.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# Seitenansicht und PDF-Export
|
||||
|
||||
Die Seitenansicht ist rein lesend und verändert keine Projektdaten.
|
||||
Die Aktionen für Büroangaben und Logo speichern dagegen globale Einstellungen.
|
||||
Projekt- und Verteilerangaben werden in den jeweiligen Bearbeitungsdialogen
|
||||
über Projektbefehle mit Undo/Redo gepflegt.
|
||||
|
||||
Beim Laden werden die Projektrevisionen aller Stromkreislisten und ein
|
||||
abschließend erneut gelesener Projektstand verglichen. Ändert sich das Projekt
|
||||
währenddessen, wird statt eines gemischten Datenstands eine Aufforderung zum
|
||||
Neuladen angezeigt. Eine bereits geladene Seitenansicht aktualisiert sich nicht
|
||||
automatisch bei späteren Änderungen in einem anderen Tab.
|
||||
|
||||
## Aufruf
|
||||
|
||||
- Projektseite → Button **Seitenansicht** öffnet
|
||||
`/projects/:projectId/print` in einem neuen Tab.
|
||||
- **Als PDF speichern / Drucken** nutzt den Druckdialog des Browsers
|
||||
(Ziel „Als PDF speichern“). Der Dokumenttitel `Leistungsbilanz – <Projekt>`
|
||||
wird als Dateiname vorgeschlagen.
|
||||
- **Planformat** schaltet die Verteilerpläne zwischen A4 quer und A3 quer um.
|
||||
Deckblatt bleibt A4 hoch.
|
||||
- **Büroangaben** pflegt Büroname und Büroanschrift (Planverfasser, für alle
|
||||
Projekte).
|
||||
- **Logo hinterlegen / ersetzen / entfernen** verwaltet das Büro-Logo.
|
||||
|
||||
## Seiten
|
||||
|
||||
1. **Deckblatt (A4 hoch)** – tabellarisch: Projekt, Planverfasser, Dokument,
|
||||
Planstände (aus benannten Sicherungspunkten) und Inhalt. Leere Angaben
|
||||
erscheinen als orangefarbenes „[ergänzen]“.
|
||||
2. **Verteilerübersicht (quer)** – Versorgungsstruktur und Tabelle je
|
||||
Verteiler mit Stromkreisanzahl, P<sub>inst</sub> (Anzahl × Leistung je
|
||||
Stück), P<sub>Geräte</sub> (mit Geräte-GZF), Verteiler-GZF,
|
||||
P<sub>gl</sub>, I<sub>B</sub> und „Σ inkl. unterlagert“.
|
||||
3. **Verteilerpläne (quer, je Verteiler)** – Titelleiste mit
|
||||
Verteilernummer, Bezeichnung, Örtlichkeit, Netzart, „Gespeist von“ und
|
||||
P<sub>gl</sub>; darunter Kopfkomponenten, Gruppen, Stromkreise
|
||||
(mehrzeilige mit Sammelzeile und eingerückten Gerätezeilen),
|
||||
Gruppensummen und Verteilersumme. Fehlende Kabelangaben sind als „offen“
|
||||
markiert. Die Titelleiste steht im Tabellenkopf und wiederholt sich beim
|
||||
Drucken auf Folgeseiten.
|
||||
|
||||
Seitenformat, Ränder und „Seite x von y“ kommen beim Drucken aus benannten
|
||||
`@page`-Regeln (`lb-portrait`, `lb-landscape`), die die Seite zur Laufzeit
|
||||
einfügt. Die Bildschirmansicht zeigt Blätter in Papiergröße; die exakte
|
||||
Seitenaufteilung langer Verteilerpläne entsteht erst beim Drucken.
|
||||
|
||||
## Vorläufige Punkte
|
||||
|
||||
- **Einspeisung / Hierarchie:** `fedFrom` ist Freitext. Die Übersicht ordnet
|
||||
einen Verteiler nur dann unter, wenn der Text eindeutig der Nummer oder
|
||||
Bezeichnung eines anderen Verteilers entspricht (ohne Beachtung von
|
||||
Groß-/Kleinschreibung und äußeren Leerzeichen). Mehrdeutige Treffer bleiben
|
||||
ohne Zuordnung; „Σ inkl. unterlagert“ ist
|
||||
eine einfache Summe ohne übergeordneten GZF. Die fachliche Verknüpfung
|
||||
(Verteiler und/oder speisender Stromkreis) und die Summierungslogik sind
|
||||
offen.
|
||||
- **I<sub>B</sub>** ist ein symmetrischer Drehstromwert
|
||||
S / (√3 · U<sub>3~</sub>) mit S aus P / cos φ je Gerätezeile
|
||||
(fehlendes cos φ = 1) und Verteiler-GZF.
|
||||
- **Corporate Design:** Farben (`--pd-*` in
|
||||
`src/frontend/print/print-document.css`) und Schrift (Arial) sind aus Logo
|
||||
und kbp-Präsentationsmaterial abgeleitet und werden durch die offizielle
|
||||
CD-Vorgabe ersetzt, falls diese abweicht.
|
||||
- **Planstände:** Die Spalte „Bearbeitung“ zeigt für jeden Planstand die
|
||||
aktuelle Bearbeitung aus den Projekteinstellungen, weil Sicherungspunkte
|
||||
(noch) keinen Bearbeiter speichern.
|
||||
|
||||
## Datenquellen des Deckblatts
|
||||
|
||||
| Feld | Quelle |
|
||||
|---|---|
|
||||
| Bauvorhaben, Bauherr, Projektnummern, Beschreibung | Projekteinstellungen |
|
||||
| Anschrift Bauvorhaben, Leistungsphase, Projektleitung, Bearbeitung | Projekteinstellungen → Abschnitt „Deckblatt“ (`siteAddress`, `workStage`, `projectLead`, `projectEditor`) |
|
||||
| Büro, Anschrift Büro | Seitenansicht → „Büroangaben“ (global) |
|
||||
| Stand, Datenstand, Anzahl Verteiler, Inhalt | automatisch |
|
||||
| Planstände | benannte Sicherungspunkte |
|
||||
|
||||
Die vier Projektfelder laufen über `project.update-settings` (Schema-Version
|
||||
3, Migration `0008`) und sind Teil von Snapshot-Schema 6 und Projektexport.
|
||||
Im `PUT /api/projects/:projectId` sind sie optional; fehlende Felder behalten
|
||||
ihren Wert.
|
||||
|
||||
## Büroangaben
|
||||
|
||||
- Tabelle `document_branding_settings` (Schlüssel/Wert, Migration `0008`),
|
||||
global wie das Logo.
|
||||
- `GET /api/document-branding` liefert zusätzlich
|
||||
`office: { officeName, officeAddress }`.
|
||||
- `PUT /api/document-branding/office` mit `{ "officeName", "officeAddress" }`
|
||||
(max. 200 / 500 Zeichen, leerer Text = nicht gesetzt).
|
||||
|
||||
## Logo
|
||||
|
||||
- Globale Büro-Einstellung, nicht Teil von Projekten, Revisionen, Snapshots
|
||||
oder Projektexport.
|
||||
- Tabelle `document_branding_assets` (Migration `0007`).
|
||||
- `GET /api/document-branding` → `{ logo: { mimeType, fileName, sizeBytes, updatedAtIso } | null }`
|
||||
- `GET /api/document-branding/logo` → Bilddaten (`404` ohne Logo), mit
|
||||
`X-Content-Type-Options: nosniff` und restriktiver CSP.
|
||||
- `PUT /api/document-branding/logo` mit
|
||||
`{ "fileName", "mimeType": "image/png" | "image/jpeg" | "image/svg+xml", "contentBase64" }`,
|
||||
maximal 2 MB; der Dateiinhalt wird gegen das Format geprüft.
|
||||
- `DELETE /api/document-branding/logo` → `204`.
|
||||
|
||||
## Code
|
||||
|
||||
- `src/app/projects/[projectId]/print/page.tsx` – Datenladen, Werkzeugleiste,
|
||||
`@page`-Regeln
|
||||
- `src/frontend/print/print-document-model.ts` – reine Berechnungen und
|
||||
Formatierung (Tests: `tests/print-document-model.test.ts`)
|
||||
- `src/frontend/print/print-document.tsx` – Blätter und Tabellen
|
||||
- `src/frontend/print/print-document.css` – Layout, auf `.print-view`
|
||||
begrenzt
|
||||
- `src/frontend/components/distribution-board-info-card.tsx` – Infokarte im
|
||||
Bearbeiten-Dialog der Verteilung
|
||||
|
||||
## Bestehende Datenbanken
|
||||
|
||||
Vor dem Anwenden der additiven Migrationen `0007` und `0008` eine verifizierte
|
||||
Datenbanksicherung mit `npm run db:backup` erstellen. Die neuen Projekt- und
|
||||
Verteilerfelder bleiben bei bestehenden Datensätzen zunächst leer (`null`).
|
||||
Snapshot-Schema 6 enthält beide Feldgruppen; die unterstützten Versionen 1–5
|
||||
werden beim Lesen hochgestuft. Restore und Projektkopie erhalten die neuen
|
||||
Angaben. Globale Büroangaben und Logo gehören zur Datenbanksicherung, nicht
|
||||
zum logischen Projektsnapshot oder Projekttransfer.
|
||||
Loading…
Add table
Add a link
Reference in a new issue