Add distribution board copy and delete controls
This commit is contained in:
@@ -5,12 +5,14 @@ import { useParams } from "next/navigation";
|
||||
import { FormEvent, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
copyGlobalDeviceToProject,
|
||||
copyDistributionBoard,
|
||||
copyProjectDeviceToGlobal,
|
||||
createDistributionBoard,
|
||||
createFloor,
|
||||
createProjectDevice,
|
||||
createRoom,
|
||||
deleteProjectDevice,
|
||||
deleteDistributionBoard,
|
||||
disconnectProjectDeviceRows,
|
||||
exportProjectTransfer,
|
||||
getProjectDeviceSyncPreview,
|
||||
@@ -91,6 +93,7 @@ export default function ProjectDetailPage() {
|
||||
editingBoardSimultaneityFactor,
|
||||
setEditingBoardSimultaneityFactor,
|
||||
] = useState("1");
|
||||
const [editingBoardCopyName, setEditingBoardCopyName] = useState("");
|
||||
const [floorName, setFloorName] = useState("");
|
||||
const [roomNumber, setRoomNumber] = useState("");
|
||||
const [roomName, setRoomName] = useState("");
|
||||
@@ -405,6 +408,7 @@ export default function ProjectDetailPage() {
|
||||
setEditingBoardSimultaneityFactor(
|
||||
String(board.simultaneityFactor)
|
||||
);
|
||||
setEditingBoardCopyName(`${board.name} Kopie`);
|
||||
}
|
||||
|
||||
function openBoardCreator() {
|
||||
@@ -463,6 +467,88 @@ export default function ProjectDetailPage() {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCopyBoard() {
|
||||
if (
|
||||
!projectId ||
|
||||
!project ||
|
||||
!editingBoard ||
|
||||
!editingBoardCopyName.trim()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
setIsSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await copyDistributionBoard(
|
||||
projectId,
|
||||
editingBoard.id,
|
||||
editingBoardCopyName.trim(),
|
||||
project.currentRevision
|
||||
);
|
||||
setBoards((current) => [
|
||||
...current,
|
||||
result.distributionBoard,
|
||||
]);
|
||||
setCircuitLists((current) => [
|
||||
...current,
|
||||
result.circuitList,
|
||||
]);
|
||||
applyProjectRevision(result.history.currentRevision);
|
||||
setEditingBoard(null);
|
||||
} catch (err) {
|
||||
setError(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: "Verteilung konnte nicht kopiert werden."
|
||||
);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeleteBoard() {
|
||||
if (!projectId || !project || !editingBoard) {
|
||||
return;
|
||||
}
|
||||
const confirmed = window.confirm(
|
||||
`Verteilung „${editingBoard.name}“ wirklich löschen?\n\n` +
|
||||
"Dabei werden die Stromkreisliste, alle Gruppen, Stromkreise, Gerätezeilen, Schutzgeräte und weiteren Verteilergeräte entfernt. " +
|
||||
"Der Vorgang kann anschließend über die projektweite Historie rückgängig gemacht werden."
|
||||
);
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
setIsSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await deleteDistributionBoard(
|
||||
projectId,
|
||||
editingBoard.id,
|
||||
project.currentRevision
|
||||
);
|
||||
setBoards((current) =>
|
||||
current.filter((board) => board.id !== result.distributionBoardId)
|
||||
);
|
||||
setCircuitLists((current) =>
|
||||
current.filter(
|
||||
(circuitList) =>
|
||||
circuitList.distributionBoardId !==
|
||||
result.distributionBoardId
|
||||
)
|
||||
);
|
||||
applyProjectRevision(result.history.currentRevision);
|
||||
setEditingBoard(null);
|
||||
} catch (err) {
|
||||
setError(
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: "Verteilung konnte nicht gelöscht werden."
|
||||
);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleExportProject() {
|
||||
if (!project) {
|
||||
return;
|
||||
@@ -1111,7 +1197,7 @@ export default function ProjectDetailPage() {
|
||||
|
||||
{structureModal === "board" ? (
|
||||
<FormModal
|
||||
description="Eine Stromkreisliste mit den vier Standardbereichen wird automatisch angelegt."
|
||||
description="Eine Stromkreisliste mit den drei Standardgruppen wird automatisch angelegt."
|
||||
isSaving={isSaving}
|
||||
onClose={() => setStructureModal(null)}
|
||||
onSubmit={handleCreateBoard}
|
||||
@@ -1271,6 +1357,75 @@ export default function ProjectDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="my-4" />
|
||||
<section aria-labelledby="copy-distribution-board-heading">
|
||||
<h3
|
||||
className="h6"
|
||||
id="copy-distribution-board-heading"
|
||||
>
|
||||
Verteilung kopieren
|
||||
</h3>
|
||||
<p className="text-secondary small">
|
||||
Erstellt eine vollständige Kopie des zuletzt gespeicherten
|
||||
Stands einschließlich Gruppen, Stromkreisen, Gerätezeilen und
|
||||
Schutzgeräten. Noch nicht gespeicherte Änderungen oben werden
|
||||
nicht übernommen.
|
||||
</p>
|
||||
<div className="row g-2 align-items-end">
|
||||
<div className="col-12 col-md">
|
||||
<label
|
||||
className="form-label"
|
||||
htmlFor="copy-distribution-board-name"
|
||||
>
|
||||
Bezeichnung der Kopie
|
||||
</label>
|
||||
<input
|
||||
className="form-control"
|
||||
id="copy-distribution-board-name"
|
||||
maxLength={200}
|
||||
onChange={(event) =>
|
||||
setEditingBoardCopyName(event.target.value)
|
||||
}
|
||||
value={editingBoardCopyName}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12 col-md-auto">
|
||||
<button
|
||||
className="btn btn-outline-primary"
|
||||
disabled={isSaving || !editingBoardCopyName.trim()}
|
||||
onClick={() => void handleCopyBoard()}
|
||||
type="button"
|
||||
>
|
||||
Verteilung kopieren
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<hr className="my-4" />
|
||||
<section
|
||||
aria-labelledby="delete-distribution-board-heading"
|
||||
className="border border-danger-subtle rounded p-3"
|
||||
>
|
||||
<h3
|
||||
className="h6 text-danger"
|
||||
id="delete-distribution-board-heading"
|
||||
>
|
||||
Gefahrenbereich
|
||||
</h3>
|
||||
<p className="text-secondary small mb-3">
|
||||
Entfernt die vollständige Verteilung. Die Aktion wird erst
|
||||
nach einer ausdrücklichen Warnung ausgeführt und kann über die
|
||||
projektweite Historie rückgängig gemacht werden.
|
||||
</p>
|
||||
<button
|
||||
className="btn btn-outline-danger"
|
||||
disabled={isSaving}
|
||||
onClick={() => void handleDeleteBoard()}
|
||||
type="button"
|
||||
>
|
||||
Verteilung löschen
|
||||
</button>
|
||||
</section>
|
||||
</FormModal>
|
||||
) : null}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user