Add editable project floors and rooms
This commit is contained in:
@@ -3,8 +3,10 @@ import type { SerializedProjectCommand } from "./project-command.model.js";
|
||||
|
||||
export const projectFloorInsertCommandType = "project-floor.insert" as const;
|
||||
export const projectFloorDeleteCommandType = "project-floor.delete" as const;
|
||||
export const projectFloorUpdateCommandType = "project-floor.update" as const;
|
||||
export const projectRoomInsertCommandType = "project-room.insert" as const;
|
||||
export const projectRoomDeleteCommandType = "project-room.delete" as const;
|
||||
export const projectRoomUpdateCommandType = "project-room.update" as const;
|
||||
export const projectLocationStructureCommandSchemaVersion = 1 as const;
|
||||
|
||||
export interface ProjectFloorSnapshot {
|
||||
@@ -30,6 +32,16 @@ interface ProjectRoomStructureCommandPayload {
|
||||
room: ProjectRoomSnapshot;
|
||||
}
|
||||
|
||||
interface ProjectFloorUpdateCommandPayload {
|
||||
expected: ProjectFloorSnapshot;
|
||||
target: ProjectFloorSnapshot;
|
||||
}
|
||||
|
||||
interface ProjectRoomUpdateCommandPayload {
|
||||
expected: ProjectRoomSnapshot;
|
||||
target: ProjectRoomSnapshot;
|
||||
}
|
||||
|
||||
export interface ProjectFloorInsertProjectCommand
|
||||
extends SerializedProjectCommand<ProjectFloorStructureCommandPayload> {
|
||||
schemaVersion: typeof projectLocationStructureCommandSchemaVersion;
|
||||
@@ -42,6 +54,12 @@ export interface ProjectFloorDeleteProjectCommand
|
||||
type: typeof projectFloorDeleteCommandType;
|
||||
}
|
||||
|
||||
export interface ProjectFloorUpdateProjectCommand
|
||||
extends SerializedProjectCommand<ProjectFloorUpdateCommandPayload> {
|
||||
schemaVersion: typeof projectLocationStructureCommandSchemaVersion;
|
||||
type: typeof projectFloorUpdateCommandType;
|
||||
}
|
||||
|
||||
export interface ProjectRoomInsertProjectCommand
|
||||
extends SerializedProjectCommand<ProjectRoomStructureCommandPayload> {
|
||||
schemaVersion: typeof projectLocationStructureCommandSchemaVersion;
|
||||
@@ -54,11 +72,19 @@ export interface ProjectRoomDeleteProjectCommand
|
||||
type: typeof projectRoomDeleteCommandType;
|
||||
}
|
||||
|
||||
export interface ProjectRoomUpdateProjectCommand
|
||||
extends SerializedProjectCommand<ProjectRoomUpdateCommandPayload> {
|
||||
schemaVersion: typeof projectLocationStructureCommandSchemaVersion;
|
||||
type: typeof projectRoomUpdateCommandType;
|
||||
}
|
||||
|
||||
export type ProjectLocationStructureProjectCommand =
|
||||
| ProjectFloorInsertProjectCommand
|
||||
| ProjectFloorDeleteProjectCommand
|
||||
| ProjectFloorUpdateProjectCommand
|
||||
| ProjectRoomInsertProjectCommand
|
||||
| ProjectRoomDeleteProjectCommand;
|
||||
| ProjectRoomDeleteProjectCommand
|
||||
| ProjectRoomUpdateProjectCommand;
|
||||
|
||||
export function createProjectFloorSnapshot(
|
||||
projectId: string,
|
||||
@@ -138,6 +164,30 @@ export function createProjectRoomDeleteProjectCommand(
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectFloorUpdateProjectCommand(
|
||||
expected: ProjectFloorSnapshot,
|
||||
target: ProjectFloorSnapshot
|
||||
): ProjectFloorUpdateProjectCommand {
|
||||
assertMatchingFloorUpdate(expected, target);
|
||||
return {
|
||||
schemaVersion: projectLocationStructureCommandSchemaVersion,
|
||||
type: projectFloorUpdateCommandType,
|
||||
payload: { expected, target },
|
||||
};
|
||||
}
|
||||
|
||||
export function createProjectRoomUpdateProjectCommand(
|
||||
expected: ProjectRoomSnapshot,
|
||||
target: ProjectRoomSnapshot
|
||||
): ProjectRoomUpdateProjectCommand {
|
||||
assertMatchingRoomUpdate(expected, target);
|
||||
return {
|
||||
schemaVersion: projectLocationStructureCommandSchemaVersion,
|
||||
type: projectRoomUpdateCommandType,
|
||||
payload: { expected, target },
|
||||
};
|
||||
}
|
||||
|
||||
export function assertProjectFloorInsertProjectCommand(
|
||||
command: SerializedProjectCommand<unknown>
|
||||
): asserts command is ProjectFloorInsertProjectCommand {
|
||||
@@ -174,6 +224,59 @@ export function assertProjectRoomDeleteProjectCommand(
|
||||
);
|
||||
}
|
||||
|
||||
export function assertProjectFloorUpdateProjectCommand(
|
||||
command: SerializedProjectCommand<unknown>
|
||||
): asserts command is ProjectFloorUpdateProjectCommand {
|
||||
if (
|
||||
command.schemaVersion !== projectLocationStructureCommandSchemaVersion ||
|
||||
command.type !== projectFloorUpdateCommandType ||
|
||||
!isPlainObject(command.payload) ||
|
||||
Object.keys(command.payload).length !== 2
|
||||
) {
|
||||
throw new Error("Unsupported project-floor update command.");
|
||||
}
|
||||
assertMatchingFloorUpdate(command.payload.expected, command.payload.target);
|
||||
}
|
||||
|
||||
export function assertProjectRoomUpdateProjectCommand(
|
||||
command: SerializedProjectCommand<unknown>
|
||||
): asserts command is ProjectRoomUpdateProjectCommand {
|
||||
if (
|
||||
command.schemaVersion !== projectLocationStructureCommandSchemaVersion ||
|
||||
command.type !== projectRoomUpdateCommandType ||
|
||||
!isPlainObject(command.payload) ||
|
||||
Object.keys(command.payload).length !== 2
|
||||
) {
|
||||
throw new Error("Unsupported project-room update command.");
|
||||
}
|
||||
assertMatchingRoomUpdate(command.payload.expected, command.payload.target);
|
||||
}
|
||||
|
||||
function assertMatchingFloorUpdate(expected: unknown, target: unknown) {
|
||||
assertProjectFloorSnapshot(expected);
|
||||
assertProjectFloorSnapshot(target);
|
||||
if (
|
||||
expected.id !== target.id ||
|
||||
expected.projectId !== target.projectId ||
|
||||
expected.sortOrder !== target.sortOrder ||
|
||||
expected.name === target.name
|
||||
) {
|
||||
throw new Error("Project-floor update must change only the name.");
|
||||
}
|
||||
}
|
||||
|
||||
function assertMatchingRoomUpdate(expected: unknown, target: unknown) {
|
||||
assertProjectRoomSnapshot(expected);
|
||||
assertProjectRoomSnapshot(target);
|
||||
if (
|
||||
expected.id !== target.id ||
|
||||
expected.projectId !== target.projectId ||
|
||||
sameSnapshot(expected, target)
|
||||
) {
|
||||
throw new Error("Project-room update must change room values.");
|
||||
}
|
||||
}
|
||||
|
||||
export function assertProjectFloorSnapshot(
|
||||
floor: unknown
|
||||
): asserts floor is ProjectFloorSnapshot {
|
||||
@@ -257,3 +360,9 @@ function assertNormalizedNonEmptyString(
|
||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
return value !== null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function sameSnapshot(left: object, right: object) {
|
||||
return Object.entries(left).every(
|
||||
([key, value]) => (right as Record<string, unknown>)[key] === value
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,12 +72,16 @@ import {
|
||||
import {
|
||||
assertProjectFloorDeleteProjectCommand,
|
||||
assertProjectFloorInsertProjectCommand,
|
||||
assertProjectFloorUpdateProjectCommand,
|
||||
assertProjectRoomDeleteProjectCommand,
|
||||
assertProjectRoomInsertProjectCommand,
|
||||
assertProjectRoomUpdateProjectCommand,
|
||||
projectFloorDeleteCommandType,
|
||||
projectFloorInsertCommandType,
|
||||
projectFloorUpdateCommandType,
|
||||
projectRoomDeleteCommandType,
|
||||
projectRoomInsertCommandType,
|
||||
projectRoomUpdateCommandType,
|
||||
} from "../models/project-location-structure-project-command.model.js";
|
||||
import {
|
||||
assertProjectStateRestoreCommand,
|
||||
@@ -470,6 +474,10 @@ export class ProjectCommandService implements ProjectCommandExecutor {
|
||||
command: input.command,
|
||||
}).revision;
|
||||
}
|
||||
case projectFloorUpdateCommandType: {
|
||||
assertProjectFloorUpdateProjectCommand(input.command);
|
||||
return this.projectLocationStructureStore.execute({ ...input, command: input.command }).revision;
|
||||
}
|
||||
case projectRoomInsertCommandType: {
|
||||
assertProjectRoomInsertProjectCommand(input.command);
|
||||
return this.projectLocationStructureStore.execute({
|
||||
@@ -484,6 +492,10 @@ export class ProjectCommandService implements ProjectCommandExecutor {
|
||||
command: input.command,
|
||||
}).revision;
|
||||
}
|
||||
case projectRoomUpdateCommandType: {
|
||||
assertProjectRoomUpdateProjectCommand(input.command);
|
||||
return this.projectLocationStructureStore.execute({ ...input, command: input.command }).revision;
|
||||
}
|
||||
case circuitSectionReorderCommandType: {
|
||||
assertCircuitSectionReorderProjectCommand(input.command);
|
||||
return this.circuitSectionReorderStore.execute({
|
||||
|
||||
Reference in New Issue
Block a user