From c633e78cd406688a23f89c0dc15569ad87f6f394 Mon Sep 17 00:00:00 2001 From: Julian Appel Date: Wed, 30 Sep 2026 09:02:52 +0200 Subject: [PATCH] Add Revit XLSX settings page --- AGENTS.md | 6 +- README.md | 6 +- docs/spec/revit-excel-phase-14-plan.md | 2 +- src/app/projects/[projectId]/page.tsx | 44 +- src/app/projects/[projectId]/revit/page.tsx | 34 + src/frontend/components/revit-csv-modal.tsx | 666 ------------------ .../components/revit-xlsx-settings-modal.tsx | 45 ++ src/frontend/types.ts | 7 + src/frontend/utils/api.ts | 99 +-- src/frontend/utils/project-version-history.ts | 1 + src/frontend/utils/revit-xlsx-settings.ts | 17 + ...external-model-configuration.controller.ts | 60 ++ src/server/routes/project.routes.ts | 8 + tests/revit-csv-frontend-api.test.ts | 251 ------- tests/revit-xlsx-settings-api.test.ts | 38 + 15 files changed, 259 insertions(+), 1025 deletions(-) create mode 100644 src/app/projects/[projectId]/revit/page.tsx delete mode 100644 src/frontend/components/revit-csv-modal.tsx create mode 100644 src/frontend/components/revit-xlsx-settings-modal.tsx create mode 100644 src/frontend/utils/revit-xlsx-settings.ts create mode 100644 src/server/controllers/external-model-configuration.controller.ts delete mode 100644 tests/revit-csv-frontend-api.test.ts create mode 100644 tests/revit-xlsx-settings-api.test.ts diff --git a/AGENTS.md b/AGENTS.md index c95a271..e8d4bff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -329,8 +329,8 @@ the old development-only external CSV data after resetting linked row totals to their manual share. Snapshot schema 10, restore and project transfer use the new state; non-empty legacy CSV snapshots and legacy CSV history entries are rejected with a German error. The backend CSV parser and routes are removed. -The old project-page frontend remains only until its replacement in R4; do not -reconnect it to runtime CSV endpoints. See +R4 adds `/projects/:projectId/revit`, its revisioned XLSX settings and +server-side sample detection, and removes the old project-page CSV modal. See `docs/spec/revit-excel-integration-requirements.md` and `docs/spec/revit-excel-phase-14-plan.md`. @@ -586,7 +586,7 @@ Critical target rules: selected combined/separate mode block export. - Missing GZF defaults visibly to 1 without separate confirmation. - The corrected R2 return workbook was successfully imported into Linear on - 2026-09-30; R3 is complete and R4 is the next package. + 2026-09-30; R3 and R4 are complete and R5 is the next package. - All confirmed writes use typed project commands with `expectedRevision`, complete inverse data and the shared project-command transaction boundary. - Do not add automatic circuit planning, Revit circuit adoption, multi-source diff --git a/README.md b/README.md index b8b9c3e..b70a145 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ für mehrere gleichzeitig arbeitende Prozesse und ein vollständig unterstützte Produktionsdeployment fehlen weiterhin. Anmeldung und zwei feste Rollen sind vorhanden. Die Backend- und Persistenzgrundlage der bisherigen Revit-CSV-/IfcGUID-Anbindung ist durch den XLSX-Austausch des Linear-Plugins mit -Worksharing-ID als externem Schlüssel ersetzt. R0 bis R3 sind abgeschlossen; -die eigene Revit-Seite, Erstimport, Editorzuordnung, Rückgabe und Folgeimport -folgen in R4 bis R10. +Worksharing-ID als externem Schlüssel ersetzt. R0 bis R4 sind abgeschlossen; +die eigene Revit-Seite mit XLSX-Einstellungen ist vorhanden. Erstimport, +Editorzuordnung, Rückgabe und Folgeimport folgen in R5 bis R10. ## Unterstützter Arbeitsablauf diff --git a/docs/spec/revit-excel-phase-14-plan.md b/docs/spec/revit-excel-phase-14-plan.md index 4004eb3..0b1b71a 100644 --- a/docs/spec/revit-excel-phase-14-plan.md +++ b/docs/spec/revit-excel-phase-14-plan.md @@ -12,7 +12,7 @@ Der alte CSV-Plan 14.0–14.6 ist abgelöst und wird nicht fortgeschrieben. | R1 | abgeschlossen | Anforderungen, Plan und Architektur auf Excel/Worksharing-ID umgestellt; alle Pflichtprüfungen bestanden. | | R2 | abgeschlossen und freigegeben | XLSX-Adapter, Parser, synthetische Fixtures, lokaler Referenzprüfer und reale Rückgabedatei sind erstellt; der korrigierte Rückimport wurde am 30.09.2026 erfolgreich in Linear getestet. | | R3 | abgeschlossen | Konfiguration ohne eigene Revision, Worksharing-ID-Datenmodell, Migration 0014, Snapshot 10, Transfer und Backend-CSV-Entfernung sind umgesetzt und geprüft. | -| R4 | offen | Revit-Seite, Navigation, Einstellungen, altes Projektseitenmodal entfernen. | +| R4 | abgeschlossen | Revit-Seite, Navigation und revisionierte XLSX-Einstellungen mit Musterdateiprüfung sind umgesetzt; das alte Projektseitenmodal ist entfernt. | | R5 | offen | Erstimportwizard mit Gerätearten, Familienregeln und optionalen ProjectDevices. | | R6 | offen | Virtualisierte Objekttabelle und Sammelzuordnungen. | | R7 | offen | Editorbereich, Gruppierung, Drag-and-drop, Lösen und integrierte Löschübergänge. | diff --git a/src/app/projects/[projectId]/page.tsx b/src/app/projects/[projectId]/page.tsx index ec99d54..5eb864e 100644 --- a/src/app/projects/[projectId]/page.tsx +++ b/src/app/projects/[projectId]/page.tsx @@ -5,7 +5,7 @@ import { useParams } from "next/navigation"; import { FormEvent, useEffect, useMemo, useState } from "react"; import { ArrowLeft, - FileUp, + FileSpreadsheet, Library, Link2, ListTree, @@ -51,7 +51,6 @@ import { copyProjectDeviceToGlobal, createDistributionBoard, createProjectDevice, - createRoom, deleteProjectDevice, deleteDistributionBoard, disconnectProjectDeviceRows, @@ -83,7 +82,6 @@ import type { BuildingDto, CircuitListDto, CircuitTreeResponseDto, - CreateRoomInput, CreateProjectDeviceInput, DistributionBoardDto, FloorDto, @@ -115,7 +113,6 @@ import { } from "../../../frontend/components/project-settings-modal"; import { FormModal } from "../../../frontend/components/form-modal"; import { ProjectDeviceModal } from "../../../frontend/components/project-device-modal"; -import { RevitCsvModal } from "../../../frontend/components/revit-csv-modal"; import { FloorSelectOptions } from "../../../frontend/components/floor-select-options"; const projectDeviceSyncFieldLabels: Record = { @@ -200,7 +197,6 @@ export default function ProjectDetailPage() { }) ); const [isProjectSettingsOpen, setIsProjectSettingsOpen] = useState(false); - const [isRevitCsvOpen, setIsRevitCsvOpen] = useState(false); const [structureModal, setStructureModal] = useState<"board" | null>(null); const [isProjectDeviceModalOpen, setIsProjectDeviceModalOpen] = useState(false); @@ -679,22 +675,6 @@ export default function ProjectDetailPage() { } } - async function handleCreateRevitRoom(input: CreateRoomInput) { - if (!projectId || !project) throw new Error("Projekt ist nicht geladen."); - const result = await createRoom(projectId, input, project.currentRevision); - setRooms((current) => [...current, result.room]); - applyProjectRevision(result.history.currentRevision); - return result; - } - - async function handleCreateRevitProjectDevice(input: CreateProjectDeviceInput) { - if (!projectId || !project) throw new Error("Projekt ist nicht geladen."); - const result = await createProjectDevice(projectId, input, project.currentRevision); - setProjectDevices((current) => [...current, result.projectDevice]); - applyProjectRevision(result.history.currentRevision); - return result; - } - async function handleCopyBoard() { if ( !projectId || @@ -997,15 +977,13 @@ export default function ProjectDetailPage() {