From 1c5a803e1b56913ea82785e23e3fa0ad7b31f0fe Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 27 Sep 2026 19:57:24 +0900 Subject: [PATCH] =?UTF-8?q?fix(M02):=20=EA=B5=AC=EC=A1=B0=EB=AC=BC=20?= =?UTF-8?q?=EB=8F=84=EB=A9=B4=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=ED=8A=B9=EC=84=B1=C2=B7=EB=8F=84=EB=A9=B4=EC=B8=B5=20=EC=88=A8?= =?UTF-8?q?=EA=B9=80=20=C2=B7=20CAD=20=EB=B9=88=20=EB=8F=84=EB=A9=B4=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구조물 도면 미리보기(도면 정보 카드)에서 CAD 특성·도면층 패널(.cad-inspector)도 같이 숨김 - B07 CAD `layers` 칸이 없는 도면(빈 구조물 도면 · 「새 도면」 빈 도면 공통)을 열면 "Cannot read properties of undefined (reading 'length')" 로 죽던 것을 고침 (`layers` 없으면 새 도면층 하나로 채움) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr --- .../import-entities-from-json.ts | 168 +++++++++--------- .../M02_MasterTemplete_Structure.ts | 3 +- 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/B07_DesignDetail/openwebcad/src/helpers/import-export-handlers/import-entities-from-json.ts b/B07_DesignDetail/openwebcad/src/helpers/import-export-handlers/import-entities-from-json.ts index 6cfbf049..f02d5cd2 100644 --- a/B07_DesignDetail/openwebcad/src/helpers/import-export-handlers/import-entities-from-json.ts +++ b/B07_DesignDetail/openwebcad/src/helpers/import-export-handlers/import-entities-from-json.ts @@ -1,22 +1,22 @@ -import { compact } from 'es-toolkit'; -import { ArcEntity, type ArcJsonData } from '../../entities/ArcEntity'; -import { CircleEntity, type CircleJsonData } from '../../entities/CircleEntity'; -import { type Entity, EntityName, type JsonEntity } from '../../entities/Entity'; -import { HatchEntity, type HatchJsonData } from '../../entities/HatchEntity'; -import { ImageEntity, type ImageJsonData } from '../../entities/ImageEntity.ts'; -import { LineEntity, type LineJsonData } from '../../entities/LineEntity'; -import { MeasurementEntity, type MeasurementJsonData } from '../../entities/MeasurementEntity.ts'; -import { PointEntity, type PointJsonData } from '../../entities/PointEntity'; -import { PolyLineEntity, type PolyLineJsonData } from '../../entities/PolyLineEntity.ts'; -import { RectangleEntity, type RectangleJsonData } from '../../entities/RectangleEntity'; -import { TableEntity, type TableJsonData } from '../../entities/TableEntity.ts'; -import { TextEntity, type TextJsonData } from '../../entities/TextEntity.ts'; -import { setActiveLayerId, setEntities, setLayers } from '../../state'; -import { getNewLayer } from '../get-new-layer.ts'; +import { compact } from "es-toolkit"; +import { ArcEntity, type ArcJsonData } from "../../entities/ArcEntity"; +import { CircleEntity, type CircleJsonData } from "../../entities/CircleEntity"; +import { type Entity, EntityName, type JsonEntity } from "../../entities/Entity"; +import { HatchEntity, type HatchJsonData } from "../../entities/HatchEntity"; +import { ImageEntity, type ImageJsonData } from "../../entities/ImageEntity.ts"; +import { LineEntity, type LineJsonData } from "../../entities/LineEntity"; +import { MeasurementEntity, type MeasurementJsonData } from "../../entities/MeasurementEntity.ts"; +import { PointEntity, type PointJsonData } from "../../entities/PointEntity"; +import { PolyLineEntity, type PolyLineJsonData } from "../../entities/PolyLineEntity.ts"; +import { RectangleEntity, type RectangleJsonData } from "../../entities/RectangleEntity"; +import { TableEntity, type TableJsonData } from "../../entities/TableEntity.ts"; +import { TextEntity, type TextJsonData } from "../../entities/TextEntity.ts"; +import { setActiveLayerId, setEntities, setLayers } from "../../state"; +import { getNewLayer } from "../get-new-layer.ts"; import type { - JsonDrawingFileDeserialized, - JsonDrawingFileSerialized, -} from './export-entities-to-json'; + JsonDrawingFileDeserialized, + JsonDrawingFileSerialized, +} from "./export-entities-to-json"; /** * Open a file selection dialog to select *.json files @@ -25,83 +25,83 @@ import type { * Set the entities in the state */ export function importEntitiesFromJsonFile(file: File | null | undefined) { - return new Promise((resolve) => { - if (!file) return; + return new Promise((resolve) => { + if (!file) return; - const reader = new FileReader(); - reader.addEventListener('load', async () => { - const json = reader.result as string; - const file = await getEntitiesAndLayersFromJsonString(json); - setEntities(file.entities); - setLayers(file.layers); - setActiveLayerId(file.layers[0].id); - resolve(); - }); - reader.readAsText(file, 'utf-8'); - }); + const reader = new FileReader(); + reader.addEventListener("load", async () => { + const json = reader.result as string; + const file = await getEntitiesAndLayersFromJsonString(json); + setEntities(file.entities); + setLayers(file.layers); + setActiveLayerId(file.layers[0].id); + resolve(); + }); + reader.readAsText(file, "utf-8"); + }); } export async function getEntitiesAndLayersFromJsonObject( - data: JsonDrawingFileSerialized + data: JsonDrawingFileSerialized, ): Promise { - const entityPromises: Promise[] = compact( - data.entities.map((entity) => { - switch (entity.type) { - case EntityName.Arc: - return ArcEntity.fromJson(entity as JsonEntity); - case EntityName.Circle: - return CircleEntity.fromJson(entity as JsonEntity); - case EntityName.Line: - return LineEntity.fromJson(entity as JsonEntity); - case EntityName.Point: - return PointEntity.fromJson(entity as JsonEntity); - case EntityName.Rectangle: - return RectangleEntity.fromJson(entity as JsonEntity); - case EntityName.Text: - return TextEntity.fromJson(entity as JsonEntity); - case EntityName.Measurement: - return MeasurementEntity.fromJson(entity as JsonEntity); - case EntityName.Image: - return ImageEntity.fromJson(entity as JsonEntity); - case EntityName.PolyLine: - return PolyLineEntity.fromJson(entity as JsonEntity); - case EntityName.Hatch: - return HatchEntity.fromJson(entity as JsonEntity); - case EntityName.Table: - return TableEntity.fromJson(entity as JsonEntity); + const entityPromises: Promise[] = compact( + data.entities.map((entity) => { + switch (entity.type) { + case EntityName.Arc: + return ArcEntity.fromJson(entity as JsonEntity); + case EntityName.Circle: + return CircleEntity.fromJson(entity as JsonEntity); + case EntityName.Line: + return LineEntity.fromJson(entity as JsonEntity); + case EntityName.Point: + return PointEntity.fromJson(entity as JsonEntity); + case EntityName.Rectangle: + return RectangleEntity.fromJson(entity as JsonEntity); + case EntityName.Text: + return TextEntity.fromJson(entity as JsonEntity); + case EntityName.Measurement: + return MeasurementEntity.fromJson(entity as JsonEntity); + case EntityName.Image: + return ImageEntity.fromJson(entity as JsonEntity); + case EntityName.PolyLine: + return PolyLineEntity.fromJson(entity as JsonEntity); + case EntityName.Hatch: + return HatchEntity.fromJson(entity as JsonEntity); + case EntityName.Table: + return TableEntity.fromJson(entity as JsonEntity); - default: - throw new Error(`Invalid entity type: ${entity.type}`); - } - }) - ); + default: + throw new Error(`Invalid entity type: ${entity.type}`); + } + }), + ); - const entities = compact(await Promise.all(entityPromises)); - // 순번이 아니라 id로 되돌린다 — compact가 null을 걷어 index가 어긋날 수 있다. - const groupIdById = new Map(data.entities.map((entity) => [entity.id, entity.groupId])); - for (const entity of entities) { - const groupId = groupIdById.get(entity.id); - if (groupId) entity.groupId = groupId; - } - let layers = data.layers; - if (data.layers.length === 0) { - layers = [getNewLayer()]; - } - return { - entities, - layers, - }; + const entities = compact(await Promise.all(entityPromises)); + // 순번이 아니라 id로 되돌린다 — compact가 null을 걷어 index가 어긋날 수 있다. + const groupIdById = new Map(data.entities.map((entity) => [entity.id, entity.groupId])); + for (const entity of entities) { + const groupId = groupIdById.get(entity.id); + if (groupId) entity.groupId = groupId; + } + let layers = data.layers; + if (!layers || layers.length === 0) { + layers = [getNewLayer()]; + } + return { + entities, + layers, + }; } export async function getEntitiesAndLayersFromJsonString( - json: string + json: string, ): Promise { - const data = JSON.parse(json) as JsonDrawingFileSerialized; + const data = JSON.parse(json) as JsonDrawingFileSerialized; - if (!data.entities) { - throw new Error('Invalid JSON file'); - } + if (!data.entities) { + throw new Error("Invalid JSON file"); + } - // TODO use map limit to avoid overloading the event loop - return await getEntitiesAndLayersFromJsonObject(data); + // TODO use map limit to avoid overloading the event loop + return await getEntitiesAndLayersFromJsonObject(data); } diff --git a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts index 0dee58a3..8d90fec8 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Structure.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Structure.ts @@ -138,7 +138,8 @@ export function createStructurePanel(opts: StructurePanelOptions): StructurePane if (!inner?.head || inner.getElementById("m02-struct-hide")) return; const style = inner.createElement("style"); style.id = "m02-struct-hide"; - style.textContent = ".cad-titlebar, .cad-ribbon { display: none !important; }"; + style.textContent = + ".cad-titlebar, .cad-ribbon, .cad-inspector { display: none !important; }"; inner.head.append(style); }; frame.addEventListener("load", apply);