Persist circuit reorders

This commit is contained in:
2026-07-25 21:22:10 +02:00
parent 08a2775a88
commit abcb468807
26 changed files with 914 additions and 372 deletions
@@ -1,8 +1,18 @@
import { and, eq } from "drizzle-orm";
import {
assertCircuitSectionReorderProjectCommand,
circuitSectionReorderCommandType,
createCircuitSectionReorderProjectCommand,
type CircuitSectionReorderAssignment,
type CircuitSectionReorderProjectCommand,
} from "../../domain/models/circuit-section-reorder-project-command.model.js";
import {
assertCircuitSectionsReorderProjectCommand,
circuitSectionsReorderCommandType,
createCircuitSectionsReorderProjectCommand,
type CircuitSectionsReorderProjectCommand,
type CircuitSectionsReorderSection,
} from "../../domain/models/circuit-sections-reorder-project-command.model.js";
import type {
CircuitSectionReorderProjectCommandStore,
ExecuteCircuitSectionReorderCommandInput,
@@ -14,106 +24,49 @@ import { circuits } from "../schema/circuits.js";
import { applyProjectHistoryTransition } from "./project-history.persistence.js";
import { appendProjectRevision } from "./project-revision.persistence.js";
type ReorderHistoryCommand =
| CircuitSectionReorderProjectCommand
| CircuitSectionsReorderProjectCommand;
export class CircuitSectionReorderProjectCommandRepository
implements CircuitSectionReorderProjectCommandStore
{
constructor(private readonly database: AppDatabase) {}
execute(input: ExecuteCircuitSectionReorderCommandInput) {
assertCircuitSectionReorderProjectCommand(input.command);
this.assertSupportedCommand(input.command);
return this.database.transaction((tx) => {
const section = tx
.select({
id: circuitSections.id,
circuitListId: circuitSections.circuitListId,
projectId: circuitLists.projectId,
})
.from(circuitSections)
.innerJoin(
circuitLists,
eq(circuitLists.id, circuitSections.circuitListId)
)
.where(eq(circuitSections.id, input.command.payload.sectionId))
.get();
if (!section || section.projectId !== input.projectId) {
throw new Error(
"Circuit section does not belong to project."
const commandSections = this.getCommandSections(input.command);
const inverseSections = commandSections.map((section) => {
this.assertCompleteCurrentSection(
tx,
input.projectId,
section
);
return {
sectionId: section.sectionId,
assignments: section.assignments.map((assignment) => ({
circuitId: assignment.circuitId,
expectedSortOrder: assignment.targetSortOrder,
targetSortOrder: assignment.expectedSortOrder,
})),
};
});
for (const section of commandSections) {
this.applyAssignments(tx, section);
}
const persistedCircuits = tx
.select({
id: circuits.id,
circuitListId: circuits.circuitListId,
sortOrder: circuits.sortOrder,
})
.from(circuits)
.where(eq(circuits.sectionId, section.id))
.all();
const assignments = input.command.payload.assignments;
if (
persistedCircuits.length !== assignments.length ||
persistedCircuits.some(
(circuit) =>
circuit.circuitListId !== section.circuitListId
)
) {
throw new Error(
"Circuit reorder must include every circuit in the section."
);
}
const circuitsById = new Map(
persistedCircuits.map((circuit) => [circuit.id, circuit])
);
for (const assignment of assignments) {
const circuit = circuitsById.get(assignment.circuitId);
if (
!circuit ||
circuit.sortOrder !== assignment.expectedSortOrder
) {
throw new Error(
"Circuit changed before section reorder execution."
);
}
}
const inverse = createCircuitSectionReorderProjectCommand(
section.id,
assignments.map((assignment) => ({
circuitId: assignment.circuitId,
expectedSortOrder: assignment.targetSortOrder,
targetSortOrder: assignment.expectedSortOrder,
}))
);
for (const assignment of assignments) {
if (
assignment.expectedSortOrder === assignment.targetSortOrder
) {
continue;
}
const updated = tx
.update(circuits)
.set({ sortOrder: assignment.targetSortOrder })
.where(
and(
eq(circuits.id, assignment.circuitId),
eq(circuits.sectionId, section.id),
eq(
circuits.sortOrder,
assignment.expectedSortOrder
)
const inverse =
input.command.type === circuitSectionReorderCommandType
? createCircuitSectionReorderProjectCommand(
inverseSections[0].sectionId,
inverseSections[0].assignments
)
)
.run();
if (updated.changes !== 1) {
throw new Error(
"Circuit changed during section reorder execution."
);
}
}
: createCircuitSectionsReorderProjectCommand(
inverseSections
);
const revision = appendProjectRevision(tx, {
projectId: input.projectId,
expectedRevision: input.expectedRevision,
@@ -132,4 +85,125 @@ export class CircuitSectionReorderProjectCommandRepository
return { revision, inverse };
});
}
private assertSupportedCommand(
command: ReorderHistoryCommand
) {
if (command.type === circuitSectionReorderCommandType) {
assertCircuitSectionReorderProjectCommand(command);
return;
}
if (command.type === circuitSectionsReorderCommandType) {
assertCircuitSectionsReorderProjectCommand(command);
return;
}
throw new Error("Unsupported circuit section reorder command.");
}
private getCommandSections(
command: ReorderHistoryCommand
): CircuitSectionsReorderSection[] {
if (command.type === circuitSectionReorderCommandType) {
return [
{
sectionId: command.payload.sectionId,
assignments: command.payload.assignments,
},
];
}
return command.payload.sections;
}
private assertCompleteCurrentSection(
database: AppDatabase,
projectId: string,
sectionCommand: CircuitSectionsReorderSection
) {
const section = database
.select({
id: circuitSections.id,
circuitListId: circuitSections.circuitListId,
projectId: circuitLists.projectId,
})
.from(circuitSections)
.innerJoin(
circuitLists,
eq(circuitLists.id, circuitSections.circuitListId)
)
.where(eq(circuitSections.id, sectionCommand.sectionId))
.get();
if (!section || section.projectId !== projectId) {
throw new Error(
"Circuit section does not belong to project."
);
}
const persistedCircuits = database
.select({
id: circuits.id,
circuitListId: circuits.circuitListId,
sortOrder: circuits.sortOrder,
})
.from(circuits)
.where(eq(circuits.sectionId, section.id))
.all();
const assignments = sectionCommand.assignments;
if (
persistedCircuits.length !== assignments.length ||
persistedCircuits.some(
(circuit) =>
circuit.circuitListId !== section.circuitListId
)
) {
throw new Error(
"Circuit reorder must include every circuit in the section."
);
}
const circuitsById = new Map(
persistedCircuits.map((circuit) => [circuit.id, circuit])
);
for (const assignment of assignments) {
const circuit = circuitsById.get(assignment.circuitId);
if (
!circuit ||
circuit.sortOrder !== assignment.expectedSortOrder
) {
throw new Error(
"Circuit changed before section reorder execution."
);
}
}
}
private applyAssignments(
database: AppDatabase,
sectionCommand: {
sectionId: string;
assignments: CircuitSectionReorderAssignment[];
}
) {
for (const assignment of sectionCommand.assignments) {
if (
assignment.expectedSortOrder === assignment.targetSortOrder
) {
continue;
}
const updated = database
.update(circuits)
.set({ sortOrder: assignment.targetSortOrder })
.where(
and(
eq(circuits.id, assignment.circuitId),
eq(circuits.sectionId, sectionCommand.sectionId),
eq(circuits.sortOrder, assignment.expectedSortOrder)
)
)
.run();
if (updated.changes !== 1) {
throw new Error(
"Circuit changed during section reorder execution."
);
}
}
}
}
@@ -8,54 +8,6 @@ export class CircuitSectionTransactionRepository
{
constructor(private readonly database: AppDatabase) {}
updateSortOrders(sectionId: string, orderedCircuitIds: string[]) {
if (orderedCircuitIds.length === 0) {
return;
}
if (new Set(orderedCircuitIds).size !== orderedCircuitIds.length) {
throw new Error(
"Stromkreise dürfen in der Reihenfolge nicht mehrfach vorkommen."
);
}
this.database.transaction((tx) => {
const sectionCircuits = tx
.select({ id: circuits.id })
.from(circuits)
.where(eq(circuits.sectionId, sectionId))
.all();
const sectionCircuitIds = new Set(
sectionCircuits.map((circuit) => circuit.id)
);
if (
sectionCircuits.length !== orderedCircuitIds.length ||
orderedCircuitIds.some((circuitId) => !sectionCircuitIds.has(circuitId))
) {
throw new Error(
"Die Reihenfolge muss alle Stromkreise des Bereichs enthalten."
);
}
for (let index = 0; index < orderedCircuitIds.length; index += 1) {
const result = tx
.update(circuits)
.set({ sortOrder: (index + 1) * 10 })
.where(
and(
eq(circuits.sectionId, sectionId),
eq(circuits.id, orderedCircuitIds[index])
)
)
.run();
if (result.changes !== 1) {
throw new Error(
"Ein Stromkreis wurde vor Abschluss der Sortierung verändert."
);
}
}
});
}
updateEquipmentIdentifiers(
circuitListId: string,
updates: Array<{ id: string; equipmentIdentifier: string }>,
@@ -0,0 +1,94 @@
import {
assertCircuitSectionReorderProjectCommand,
circuitSectionReorderCommandSchemaVersion,
type CircuitSectionReorderAssignment,
} from "./circuit-section-reorder-project-command.model.js";
import type { SerializedProjectCommand } from "./project-command.model.js";
export const circuitSectionsReorderCommandType =
"circuit.reorder-sections" as const;
export const circuitSectionsReorderCommandSchemaVersion =
circuitSectionReorderCommandSchemaVersion;
export interface CircuitSectionsReorderSection {
sectionId: string;
assignments: CircuitSectionReorderAssignment[];
}
export interface CircuitSectionsReorderCommandPayload {
sections: CircuitSectionsReorderSection[];
}
export interface CircuitSectionsReorderProjectCommand
extends SerializedProjectCommand<CircuitSectionsReorderCommandPayload> {
schemaVersion: typeof circuitSectionsReorderCommandSchemaVersion;
type: typeof circuitSectionsReorderCommandType;
}
export function createCircuitSectionsReorderProjectCommand(
sections: CircuitSectionsReorderSection[]
): CircuitSectionsReorderProjectCommand {
const command: CircuitSectionsReorderProjectCommand = {
schemaVersion: circuitSectionsReorderCommandSchemaVersion,
type: circuitSectionsReorderCommandType,
payload: { sections },
};
assertCircuitSectionsReorderProjectCommand(command);
return command;
}
export function assertCircuitSectionsReorderProjectCommand(
command: SerializedProjectCommand<unknown>
): asserts command is CircuitSectionsReorderProjectCommand {
if (
command.schemaVersion !==
circuitSectionsReorderCommandSchemaVersion ||
command.type !== circuitSectionsReorderCommandType
) {
throw new Error("Unsupported circuit sections reorder command.");
}
if (!isPlainObject(command.payload)) {
throw new Error(
"Circuit sections reorder payload must be an object."
);
}
const sections = command.payload.sections;
if (!Array.isArray(sections) || sections.length === 0) {
throw new Error(
"Circuit sections reorder command requires sections."
);
}
const sectionIds = new Set<string>();
for (const section of sections) {
if (!isPlainObject(section)) {
throw new Error(
"Circuit sections reorder command contains an invalid section."
);
}
if (
typeof section.sectionId !== "string" ||
!section.sectionId.trim()
) {
throw new Error("sectionId must be a non-empty string.");
}
if (sectionIds.has(section.sectionId)) {
throw new Error(
"Circuit sections reorder command contains duplicate section ids."
);
}
assertCircuitSectionReorderProjectCommand({
schemaVersion: circuitSectionReorderCommandSchemaVersion,
type: "circuit.reorder-section",
payload: {
sectionId: section.sectionId,
assignments: section.assignments,
},
});
sectionIds.add(section.sectionId);
}
}
function isPlainObject(value: unknown): value is Record<string, unknown> {
return value !== null && typeof value === "object" && !Array.isArray(value);
}
@@ -1,4 +1,5 @@
import type { CircuitSectionReorderProjectCommand } from "../models/circuit-section-reorder-project-command.model.js";
import type { CircuitSectionsReorderProjectCommand } from "../models/circuit-sections-reorder-project-command.model.js";
import type {
AppendedProjectRevision,
ProjectRevisionSource,
@@ -11,12 +12,16 @@ export interface ExecuteCircuitSectionReorderCommandInput {
description?: string;
actorId?: string;
historyTargetChangeSetId?: string;
command: CircuitSectionReorderProjectCommand;
command:
| CircuitSectionReorderProjectCommand
| CircuitSectionsReorderProjectCommand;
}
export interface ExecutedCircuitSectionReorderCommand {
revision: AppendedProjectRevision;
inverse: CircuitSectionReorderProjectCommand;
inverse:
| CircuitSectionReorderProjectCommand
| CircuitSectionsReorderProjectCommand;
}
export interface CircuitSectionReorderProjectCommandStore {
@@ -4,5 +4,4 @@ export interface CircuitSectionTransactionStore {
updates: Array<{ id: string; equipmentIdentifier: string }>,
tempNamespace: string
): void;
updateSortOrders(sectionId: string, orderedCircuitIds: string[]): void;
}
@@ -2,7 +2,6 @@ import type { CircuitSectionTransactionStore } from "../ports/circuit-section-tr
import { CircuitRepository } from "../../db/repositories/circuit.repository.js";
import { CircuitSectionRepository } from "../../db/repositories/circuit-section.repository.js";
import type {
ReorderSectionCircuitsInput,
UpdateSectionEquipmentIdentifiersInput,
} from "../../shared/validation/circuit.schemas.js";
import { CircuitNumberingService } from "./circuit-numbering.service.js";
@@ -97,27 +96,4 @@ export class CircuitWriteService {
return this.circuitRepository.listBySection(sectionId);
}
async reorderCircuitsInSection(sectionId: string, input: ReorderSectionCircuitsInput) {
// Reorder updates sortOrder only. BMKs remain unchanged; users may renumber explicitly later.
const section = await this.circuitSectionRepository.findById(sectionId);
if (!section) {
throw new Error("Invalid section id.");
}
const sectionCircuits = await this.circuitRepository.listBySection(sectionId);
const sectionIds = new Set(sectionCircuits.map((circuit) => circuit.id));
if (sectionCircuits.length !== input.orderedCircuitIds.length) {
throw new Error("orderedCircuitIds must include all circuits of the section.");
}
for (const circuitId of input.orderedCircuitIds) {
if (!sectionIds.has(circuitId)) {
throw new Error("Circuit id does not belong to section.");
}
}
this.getCircuitSectionTransactionStore().updateSortOrders(
sectionId,
input.orderedCircuitIds
);
return this.circuitRepository.listBySection(sectionId);
}
}
@@ -23,6 +23,10 @@ import {
assertCircuitSectionReorderProjectCommand,
circuitSectionReorderCommandType,
} from "../models/circuit-section-reorder-project-command.model.js";
import {
assertCircuitSectionsReorderProjectCommand,
circuitSectionsReorderCommandType,
} from "../models/circuit-sections-reorder-project-command.model.js";
import {
assertCircuitSectionRenumberProjectCommand,
circuitSectionRenumberCommandType,
@@ -225,6 +229,13 @@ export class ProjectCommandService implements ProjectCommandExecutor {
command: input.command,
}).revision;
}
case circuitSectionsReorderCommandType: {
assertCircuitSectionsReorderProjectCommand(input.command);
return this.circuitSectionReorderStore.execute({
...input,
command: input.command,
}).revision;
}
case circuitSectionRenumberCommandType: {
assertCircuitSectionRenumberProjectCommand(input.command);
return this.circuitSectionRenumberStore.execute({
+80 -32
View File
@@ -30,6 +30,9 @@ import {
import {
buildCircuitDeviceRowMoveAssignments,
} from "../utils/circuit-device-row-move-command";
import {
buildCircuitSectionReorderAssignments,
} from "../utils/circuit-section-reorder-command";
import type {
CellKey,
CellKind,
@@ -52,7 +55,8 @@ import {
listProjectDevices,
moveCircuitDeviceRowsCommand,
moveCircuitDeviceRowsToNewCircuitCommand,
reorderSectionCircuits,
reorderCircuitSectionCommand,
reorderCircuitSectionsCommand,
renumberCircuitSection,
redoProjectCommand,
updateSectionEquipmentIdentifiers,
@@ -991,22 +995,42 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
return;
}
// Sorting is view-only until explicitly applied; this avoids accidental persisted reorders.
const reorderedSections = changedSections.map((changedSection) => {
const currentSection = data.sections.find(
(section) => section.id === changedSection.sectionId
);
if (!currentSection) {
throw new Error("Ein sortierter Bereich wurde nicht gefunden.");
}
return {
sectionId: currentSection.id,
assignments: buildCircuitSectionReorderAssignments(
currentSection.circuits,
changedSection.order
),
};
});
// Sorting is view-only until explicitly applied. All affected sections are
// then committed as one atomic project-history entry.
await runCommand({
label: "Sortierte Reihenfolge übernehmen",
redo: async () => {
for (const section of changedSections) {
await reorderSectionCircuits(section.sectionId, section.order);
}
const result = await reorderCircuitSectionsCommand(
projectId,
getExpectedProjectRevision(),
reorderedSections,
"Sortierte Reihenfolge übernehmen"
);
applyProjectCommandResult(result);
setSortState(null);
setOpenFilterColumn(null);
return null;
},
undo: async () => {
for (const section of beforeBySection) {
await reorderSectionCircuits(section.sectionId, section.order);
}
return null;
undo: async () => null,
persistent: {
undoIntent: () => null,
redoIntent: () => null,
},
});
}
@@ -2112,7 +2136,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
// Applies same-section circuit reorder as explicit id ordering.
// No implicit renumbering is performed here.
async function applyCircuitReorder(intent: CircuitReorderDropIntent, sourceCircuitIds: string[]) {
function resolveCircuitReorderOrder(intent: CircuitReorderDropIntent, sourceCircuitIds: string[]) {
const section = data?.sections.find((entry) => entry.id === intent.sectionId);
if (!section) {
throw new Error("Der Bereich ist ungültig.");
@@ -2135,7 +2159,7 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
const insertIndex = intent.kind === "after-circuit" ? targetIndex + 1 : targetIndex;
nextIds.splice(insertIndex, 0, ...block);
}
await reorderSectionCircuits(section.id, nextIds);
return nextIds;
}
// Handles project-device drag intent. This path creates linked rows/circuits and
@@ -2414,31 +2438,55 @@ export function CircuitTreeEditor(props: { projectId: string; circuitListId: str
setError("Stromkreise können derzeit nicht bereichsübergreifend verschoben werden.");
return;
}
const beforeOrder = section.circuits.map((circuit) => circuit.id);
const primaryCircuitId = sourceCircuitIds[0];
const targetOrder = resolveCircuitReorderOrder(
intent,
sourceCircuitIds
);
const assignments = buildCircuitSectionReorderAssignments(
section.circuits,
targetOrder
);
if (assignments.length === 0) {
return;
}
const label =
sourceCircuitIds.length > 1
? `${sourceCircuitIds.length} Stromkreise neu anordnen`
: "Stromkreise neu anordnen";
const selectionIntent: SelectionIntent = {
rowKey: `circuitSummary:${primaryCircuitId}`,
cellKey: "equipmentIdentifier",
rowType: "circuitSummary",
sectionId: intent.sectionId,
circuitId: primaryCircuitId,
};
await runCommand({
label: sourceCircuitIds.length > 1 ? `${sourceCircuitIds.length} Stromkreise neu anordnen` : "Stromkreise neu anordnen",
label,
redo: async () => {
await applyCircuitReorder(intent, sourceCircuitIds);
const result = await reorderCircuitSectionCommand(
projectId,
getExpectedProjectRevision(),
intent.sectionId,
assignments,
label
);
applyProjectCommandResult(result);
pendingSelectedCircuitIdsAfterReload.current = sourceCircuitIds;
return {
rowKey: `circuitSummary:${primaryCircuitId}`,
cellKey: "equipmentIdentifier",
rowType: "circuitSummary",
sectionId: intent.sectionId,
circuitId: primaryCircuitId,
};
return selectionIntent;
},
undo: async () => {
await reorderSectionCircuits(intent.sectionId, beforeOrder);
pendingSelectedCircuitIdsAfterReload.current = sourceCircuitIds;
return {
rowKey: `circuitSummary:${primaryCircuitId}`,
cellKey: "equipmentIdentifier",
rowType: "circuitSummary",
sectionId: intent.sectionId,
circuitId: primaryCircuitId,
};
undo: async () => null,
persistent: {
undoIntent: () => {
pendingSelectedCircuitIdsAfterReload.current =
sourceCircuitIds;
return selectionIntent;
},
redoIntent: () => {
pendingSelectedCircuitIdsAfterReload.current =
sourceCircuitIds;
return selectionIntent;
},
},
});
}
+41 -5
View File
@@ -36,6 +36,12 @@ import type {
import type {
CircuitDeviceRowMoveAssignment,
} from "../../domain/models/circuit-device-row-move-project-command.model";
import type {
CircuitSectionReorderAssignment,
} from "../../domain/models/circuit-section-reorder-project-command.model";
import type {
CircuitSectionsReorderSection,
} from "../../domain/models/circuit-sections-reorder-project-command.model";
async function request<T>(url: string, init?: RequestInit): Promise<T> {
const response = await fetch(url, {
@@ -319,11 +325,41 @@ export function renumberCircuitSection(sectionId: string) {
});
}
export function reorderSectionCircuits(sectionId: string, orderedCircuitIds: string[]) {
return request(`/api/circuit-sections/${sectionId}/circuits/reorder`, {
method: "PATCH",
body: JSON.stringify({ orderedCircuitIds }),
});
export function reorderCircuitSectionCommand(
projectId: string,
expectedRevision: number,
sectionId: string,
assignments: CircuitSectionReorderAssignment[],
description: string
) {
return executeProjectCommand(
projectId,
expectedRevision,
{
schemaVersion: 1,
type: "circuit.reorder-section",
payload: { sectionId, assignments },
},
description
);
}
export function reorderCircuitSectionsCommand(
projectId: string,
expectedRevision: number,
sections: CircuitSectionsReorderSection[],
description: string
) {
return executeProjectCommand(
projectId,
expectedRevision,
{
schemaVersion: 1,
type: "circuit.reorder-sections",
payload: { sections },
},
description
);
}
export function updateSectionEquipmentIdentifiers(
@@ -0,0 +1,44 @@
import type {
CircuitSectionReorderAssignment,
} from "../../domain/models/circuit-section-reorder-project-command.model.js";
import type { CircuitTreeCircuitDto } from "../types.js";
export function buildCircuitSectionReorderAssignments(
circuits: CircuitTreeCircuitDto[],
orderedCircuitIds: string[]
): CircuitSectionReorderAssignment[] {
if (
circuits.length !== orderedCircuitIds.length ||
new Set(orderedCircuitIds).size !== orderedCircuitIds.length
) {
throw new Error(
"Die Reihenfolge muss jeden Stromkreis des Bereichs genau einmal enthalten."
);
}
const circuitsById = new Map(
circuits.map((circuit) => [circuit.id, circuit])
);
const assignments = orderedCircuitIds.map((circuitId, index) => {
const circuit = circuitsById.get(circuitId);
if (!circuit) {
throw new Error(
"Die Reihenfolge enthält einen ungültigen Stromkreis."
);
}
return {
circuitId,
expectedSortOrder: circuit.sortOrder,
targetSortOrder: (index + 1) * 10,
};
});
if (
assignments.every(
(assignment) =>
assignment.expectedSortOrder === assignment.targetSortOrder
)
) {
return [];
}
return assignments;
}
@@ -1,7 +1,6 @@
import type { Request, Response } from "express";
import { circuitWriteService } from "../composition/circuit-write-service.js";
import {
reorderSectionCircuitsSchema,
updateSectionEquipmentIdentifiersSchema,
} from "../../shared/validation/circuit.schemas.js";
@@ -19,25 +18,6 @@ export async function renumberCircuitSection(req: Request, res: Response) {
}
}
export async function reorderSectionCircuits(req: Request, res: Response) {
const { sectionId } = req.params;
if (typeof sectionId !== "string") {
return res.status(400).json({ error: "Invalid sectionId" });
}
const parsed = reorderSectionCircuitsSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
try {
const updatedCircuits = await circuitWriteService.reorderCircuitsInSection(sectionId, parsed.data);
return res.json({ sectionId, circuits: updatedCircuits });
} catch (error) {
return res.status(400).json({ error: error instanceof Error ? error.message : "Failed to reorder circuits." });
}
}
export async function updateSectionEquipmentIdentifiers(req: Request, res: Response) {
const { sectionId } = req.params;
if (typeof sectionId !== "string") {
@@ -1,12 +1,10 @@
import { Router } from "express";
import {
renumberCircuitSection,
reorderSectionCircuits,
updateSectionEquipmentIdentifiers,
} from "../controllers/circuit-section.controller.js";
export const circuitSectionRouter = Router();
circuitSectionRouter.post("/circuit-sections/:sectionId/renumber", renumberCircuitSection);
circuitSectionRouter.patch("/circuit-sections/:sectionId/circuits/reorder", reorderSectionCircuits);
circuitSectionRouter.patch("/circuit-sections/:sectionId/equipment-identifiers", updateSectionEquipmentIdentifiers);
-5
View File
@@ -1,9 +1,5 @@
import { z } from "zod";
export const reorderSectionCircuitsSchema = z.object({
orderedCircuitIds: z.array(z.string().min(1)).min(1),
});
export const updateSectionEquipmentIdentifiersSchema = z.object({
identifiers: z
.array(
@@ -15,5 +11,4 @@ export const updateSectionEquipmentIdentifiersSchema = z.object({
.min(1),
});
export type ReorderSectionCircuitsInput = z.infer<typeof reorderSectionCircuitsSchema>;
export type UpdateSectionEquipmentIdentifiersInput = z.infer<typeof updateSectionEquipmentIdentifiersSchema>;