Move circuits between groups
This commit is contained in:
@@ -52,9 +52,11 @@ import {
|
||||
buildCircuitSectionRenumberAssignments,
|
||||
} from "../utils/circuit-section-renumber-command";
|
||||
import {
|
||||
buildCircuitGroupMovePlan,
|
||||
buildCircuitGroupRenumberPlan,
|
||||
buildCircuitGroupReorderAssignments,
|
||||
buildNewCircuitGroupSnapshot,
|
||||
canMoveCircuitToGroup,
|
||||
canRenumberCircuitGroups,
|
||||
canDeleteCircuitGroup,
|
||||
renameCircuitGroupSnapshot,
|
||||
@@ -96,6 +98,7 @@ import {
|
||||
listProjectDevices,
|
||||
moveCircuitDeviceRowsCommand,
|
||||
moveCircuitDeviceRowsToNewCircuitCommand,
|
||||
moveCircuitToGroupCommand,
|
||||
reorderCircuitSectionCommand,
|
||||
reorderCircuitSectionsCommand,
|
||||
reorderCircuitGroupsCommand,
|
||||
@@ -2524,7 +2527,8 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
});
|
||||
}
|
||||
|
||||
// Handles circuit drag intent and reorders whole circuit blocks within one section only.
|
||||
// Reorders whole circuit blocks within a group or moves one complete circuit
|
||||
// to another group of the same category.
|
||||
async function handleCircuitReorderDrop(event: DragEvent<HTMLElement>, intent: CircuitReorderDropIntent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -2538,8 +2542,75 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
setError("Der gezogene Stromkreis fehlt.");
|
||||
return;
|
||||
}
|
||||
const sourceSectionIds = sourceCircuitIds
|
||||
.map((id) => findCircuitSectionId(id))
|
||||
.filter((id): id is string => Boolean(id));
|
||||
const isCrossGroupMove =
|
||||
sourceSectionIds.length === 1 &&
|
||||
sourceSectionIds[0] !== intent.sectionId;
|
||||
if (isCrossGroupMove) {
|
||||
if (
|
||||
sourceCircuitIds.length !== 1 ||
|
||||
!canMoveCircuitToGroup(
|
||||
data?.sections ?? [],
|
||||
sourceCircuitIds[0],
|
||||
intent.sectionId
|
||||
)
|
||||
) {
|
||||
setError(
|
||||
"Gruppenübergreifend kann genau ein Stromkreis in eine Gruppe derselben Kategorie verschoben werden."
|
||||
);
|
||||
return;
|
||||
}
|
||||
let plan: ReturnType<typeof buildCircuitGroupMovePlan>;
|
||||
try {
|
||||
plan = buildCircuitGroupMovePlan({
|
||||
sections: data?.sections ?? [],
|
||||
circuitId: sourceCircuitIds[0],
|
||||
targetSectionId: intent.sectionId,
|
||||
placement:
|
||||
intent.kind === "section-end"
|
||||
? { kind: "end" }
|
||||
: {
|
||||
kind:
|
||||
intent.kind === "before-circuit"
|
||||
? "before"
|
||||
: "after",
|
||||
targetCircuitId: intent.targetCircuitId,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
setError(normalizeUiError(err));
|
||||
return;
|
||||
}
|
||||
const selectionIntent: SelectionIntent = {
|
||||
rowKey: `circuitSummary:${plan.circuitId}`,
|
||||
cellKey: "equipmentIdentifier",
|
||||
rowType: "circuitSummary",
|
||||
sectionId: plan.targetSectionId,
|
||||
circuitId: plan.circuitId,
|
||||
};
|
||||
await runCommand({
|
||||
label: "Stromkreis in andere Gruppe verschieben",
|
||||
redo: async () => {
|
||||
const result = await moveCircuitToGroupCommand(
|
||||
projectId,
|
||||
getExpectedProjectRevision(),
|
||||
plan
|
||||
);
|
||||
applyProjectCommandResult(result);
|
||||
pendingSelectedCircuitIdsAfterReload.current = [
|
||||
plan.circuitId,
|
||||
];
|
||||
return selectionIntent;
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!intent.valid) {
|
||||
setError("Stromkreise können derzeit nicht bereichsübergreifend verschoben werden.");
|
||||
setError(
|
||||
"Stromkreise können nur innerhalb einer Gruppe oder einzeln zwischen Gruppen derselben Kategorie verschoben werden."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const section = data?.sections.find((entry) => entry.id === intent.sectionId);
|
||||
@@ -2549,7 +2620,9 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
}
|
||||
const sectionCircuitIds = new Set(section.circuits.map((circuit) => circuit.id));
|
||||
if (sourceCircuitIds.some((id) => !sectionCircuitIds.has(id))) {
|
||||
setError("Stromkreise können derzeit nicht bereichsübergreifend verschoben werden.");
|
||||
setError(
|
||||
"Die ausgewählten Stromkreise gehören nicht zur Zielgruppe."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const primaryCircuitId = sourceCircuitIds[0];
|
||||
@@ -2892,6 +2965,23 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
const activeDraggedCircuitIds =
|
||||
draggingCircuitIds.length > 0 ? draggingCircuitIds : draggingCircuitId ? [draggingCircuitId] : [];
|
||||
const draggingCircuitCount = activeDraggedCircuitIds.length;
|
||||
const isCircuitDropTargetValid = (targetSectionId: string) => {
|
||||
const sourceSectionIds = activeDraggedCircuitIds
|
||||
.map((id) => findCircuitSectionId(id))
|
||||
.filter((id): id is string => Boolean(id));
|
||||
return (
|
||||
(sourceSectionIds.length > 0 &&
|
||||
sourceSectionIds.every(
|
||||
(sectionId) => sectionId === targetSectionId
|
||||
)) ||
|
||||
(activeDraggedCircuitIds.length === 1 &&
|
||||
canMoveCircuitToGroup(
|
||||
data.sections,
|
||||
activeDraggedCircuitIds[0],
|
||||
targetSectionId
|
||||
))
|
||||
);
|
||||
};
|
||||
const selectedProjectDevice = resolveSelectedProjectDevice();
|
||||
const suggestedSection = selectedProjectDevice
|
||||
? data.sections.find((section) => section.key === inferProjectDeviceSectionKey(selectedProjectDevice))
|
||||
@@ -3479,12 +3569,17 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
}`}
|
||||
onDragOver={(event) => {
|
||||
if (draggingCircuitCount > 0) {
|
||||
const valid = isCircuitDropTargetValid(
|
||||
section.id
|
||||
);
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = "none";
|
||||
event.dataTransfer.dropEffect = valid
|
||||
? "move"
|
||||
: "none";
|
||||
setCircuitReorderIntent({
|
||||
kind: "section-end",
|
||||
sectionId: section.id,
|
||||
valid: false,
|
||||
valid,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -3519,7 +3614,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
void handleCircuitReorderDrop(event, {
|
||||
kind: "section-end",
|
||||
sectionId: section.id,
|
||||
valid: false,
|
||||
valid: isCircuitDropTargetValid(section.id),
|
||||
});
|
||||
}
|
||||
}}
|
||||
@@ -3803,10 +3898,9 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
onClick={() => setActiveSectionId(row.sectionId)}
|
||||
onDragOver={(event) => {
|
||||
if (draggingCircuitCount > 0) {
|
||||
const sourceSectionIds = activeDraggedCircuitIds
|
||||
.map((id) => findCircuitSectionId(id))
|
||||
.filter((id): id is string => Boolean(id));
|
||||
const valid = sourceSectionIds.length > 0 && sourceSectionIds.every((sectionId) => sectionId === row.sectionId);
|
||||
const valid = isCircuitDropTargetValid(
|
||||
row.sectionId
|
||||
);
|
||||
if (row.rowType === "placeholder") {
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = valid ? "move" : "none";
|
||||
@@ -3929,13 +4023,10 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
onDrop={(event) => {
|
||||
if (draggingCircuitCount > 0) {
|
||||
if (row.rowType === "placeholder") {
|
||||
const sourceSectionIds = activeDraggedCircuitIds
|
||||
.map((id) => findCircuitSectionId(id))
|
||||
.filter((id): id is string => Boolean(id));
|
||||
void handleCircuitReorderDrop(event, {
|
||||
kind: "section-end",
|
||||
sectionId: row.sectionId,
|
||||
valid: sourceSectionIds.length > 0 && sourceSectionIds.every((sectionId) => sectionId === row.sectionId),
|
||||
valid: isCircuitDropTargetValid(row.sectionId),
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -3943,16 +4034,13 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
if (activeDraggedCircuitIds.includes(row.circuit.id)) {
|
||||
return;
|
||||
}
|
||||
const sourceSectionIds = activeDraggedCircuitIds
|
||||
.map((id) => findCircuitSectionId(id))
|
||||
.filter((id): id is string => Boolean(id));
|
||||
const rect = (event.currentTarget as HTMLTableRowElement).getBoundingClientRect();
|
||||
const isAfter = event.clientY > rect.top + rect.height / 2;
|
||||
void handleCircuitReorderDrop(event, {
|
||||
kind: isAfter ? "after-circuit" : "before-circuit",
|
||||
sectionId: row.sectionId,
|
||||
targetCircuitId: row.circuit.id,
|
||||
valid: sourceSectionIds.length > 0 && sourceSectionIds.every((sectionId) => sectionId === row.sectionId),
|
||||
valid: isCircuitDropTargetValid(row.sectionId),
|
||||
});
|
||||
}
|
||||
return;
|
||||
@@ -4283,7 +4371,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
<span className="drop-hint">
|
||||
{circuitReorderIntent.valid
|
||||
? `${draggingCircuitCount || 1} Stromkreis(e) ans Bereichsende verschieben`
|
||||
: "Bereichsübergreifendes Verschieben nicht zulässig"}
|
||||
: "Nur ein Stromkreis kann zwischen Gruppen derselben Kategorie verschoben werden"}
|
||||
</span>
|
||||
) : null}
|
||||
{circuitReorderIntent &&
|
||||
@@ -4294,7 +4382,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
|
||||
? circuitReorderIntent.kind === "before-circuit"
|
||||
? `${draggingCircuitCount || 1} Stromkreis(e) vor diesen Stromkreis verschieben`
|
||||
: `${draggingCircuitCount || 1} Stromkreis(e) hinter diesen Stromkreis verschieben`
|
||||
: "Bereichsübergreifendes Verschieben nicht zulässig"}
|
||||
: "Nur ein Stromkreis kann zwischen Gruppen derselben Kategorie verschoben werden"}
|
||||
</span>
|
||||
) : null}
|
||||
</td>
|
||||
|
||||
Reference in New Issue
Block a user