feat(M02): CAD 표 놓기 · 칸 갈기 호스트 함수 — cad_host placeTable · updateTable · 도면 손잡이 (41-2)
- cad_host: placeTable(entity, link) · updateTable(link, cells) → 바꾼 표 수 · 도면이 열리기 전이면 열린 뒤 보냄(싣기가 덮지 않게) · 5 초 넘으면 실패 - M02_MasterTemplete_Drawing: DrawingTemplateHandle 에 같은 함수 둘 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
This commit is contained in:
@@ -77,6 +77,9 @@ function migrateOldRecovery(options: DrawingTemplateOptions, scope: string): voi
|
||||
|
||||
export interface DrawingTemplateHandle {
|
||||
getDoc: () => Promise<DrawingTemplateDoc>;
|
||||
/** 표 놓기 · 칸 갈기(41장) — `cad_host` 그대로 */
|
||||
placeTable: (entity: Record<string, unknown>, link: string) => void;
|
||||
updateTable: (link: string, cells: unknown[][]) => Promise<number>;
|
||||
destroy: () => void;
|
||||
}
|
||||
|
||||
@@ -277,6 +280,8 @@ export function mountDrawingTemplate(
|
||||
|
||||
return {
|
||||
getDoc,
|
||||
placeTable: cad.placeTable,
|
||||
updateTable: cad.updateTable,
|
||||
destroy: () => {
|
||||
areaModal?.close();
|
||||
cad.destroy();
|
||||
|
||||
@@ -28,6 +28,10 @@ const CAD_HOST_SAVE_MESSAGE = "aislo:b08:host-save";
|
||||
* CAD 안 react-toastify는 모양·자리가 달라 한 화면에 두 종류가 섞여 보였다. */
|
||||
const CAD_TOAST_MESSAGE = "aislo:b08:toast";
|
||||
const CAD_TOAST_ACTION_MESSAGE = "aislo:b08:toast-action";
|
||||
/** 표(M02 41장) — 짝 = CAD `integration/aislo-table-bridge.ts` */
|
||||
const CAD_PLACE_TABLE_MESSAGE = "aislo:b08:place-table";
|
||||
const CAD_UPDATE_TABLE_MESSAGE = "aislo:b08:update-table";
|
||||
const CAD_TABLE_UPDATED_MESSAGE = "aislo:b08:table-updated";
|
||||
|
||||
/** CAD 가 주고받는 도면 JSON — 도형·층 밖의 칸은 페이지마다 다르다. */
|
||||
export interface CadHostDrawing {
|
||||
@@ -93,6 +97,11 @@ export interface CadHost<D extends CadHostDrawing, M, Q> {
|
||||
) => void;
|
||||
/** CAD 의 지금 편집본을 받는다. */
|
||||
requestSave: () => Promise<CadSaveResult<D, Q>>;
|
||||
/** 표 놓기(41장) — `entity` = 표 JSON(TableEntity 꼴) · CAD 가 `style.연결 = link` 로 커서에 붙여 놓게 함.
|
||||
* 도면이 아직 안 열렸으면 열린 뒤 보냄 · 놓기는 사용자가 누를 때 · 저장은 [저장]. */
|
||||
placeTable: (entity: Record<string, unknown>, link: string) => void;
|
||||
/** 표 칸 갈기(41장) — `style.연결 === link` 인 표의 칸만(자리 · 크기 그대로) · 돌려받는 수 = 바꾼 표 수(0 = 없음). */
|
||||
updateTable: (link: string, cells: unknown[][]) => Promise<number>;
|
||||
/** 메시지 듣기를 멈춘다 — 페이지를 떠날 때. */
|
||||
destroy: () => void;
|
||||
}
|
||||
@@ -177,6 +186,35 @@ export function createCadHost<D extends CadHostDrawing, M = unknown, Q = unknown
|
||||
frame.contentWindow?.postMessage(message, window.location.origin);
|
||||
};
|
||||
|
||||
/** 도면이 열린 뒤에만 보낼 것(표) — 열리기 전에 보내면 싣기가 덮어씀 */
|
||||
let drawingLoaded = false;
|
||||
let afterLoad: Record<string, unknown>[] = [];
|
||||
const postAfterLoad = (message: Record<string, unknown>): void => {
|
||||
if (drawingLoaded) post(message);
|
||||
else afterLoad.push(message);
|
||||
};
|
||||
const tableWaits = new Map<string, ((count: number) => void)[]>();
|
||||
|
||||
const placeTable: CadHost<D, M, Q>["placeTable"] = (entity, link) =>
|
||||
postAfterLoad({ type: CAD_PLACE_TABLE_MESSAGE, entity, link });
|
||||
|
||||
const updateTable: CadHost<D, M, Q>["updateTable"] = (link, cells) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const waits = tableWaits.get(link) ?? [];
|
||||
waits.push(resolve);
|
||||
tableWaits.set(link, waits);
|
||||
postAfterLoad({ type: CAD_UPDATE_TABLE_MESSAGE, link, cells });
|
||||
window.setTimeout(() => {
|
||||
const left = tableWaits.get(link) ?? [];
|
||||
if (!left.includes(resolve)) return;
|
||||
tableWaits.set(
|
||||
link,
|
||||
left.filter((one) => one !== resolve),
|
||||
);
|
||||
reject(new Error("CAD 표 갈기 응답 시간이 초과되었습니다."));
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
const load: CadHost<D, M, Q>["load"] = (
|
||||
drawing,
|
||||
meta,
|
||||
@@ -185,6 +223,7 @@ export function createCadHost<D extends CadHostDrawing, M = unknown, Q = unknown
|
||||
extra = {},
|
||||
) => {
|
||||
pendingLoad = { drawing, meta, frameEdit, frameFields, extra };
|
||||
drawingLoaded = false; // 새로 싣는 중 — 표는 열린 뒤에
|
||||
if (!cadReady) return;
|
||||
post({ type: CAD_LOAD_MESSAGE, drawing, meta, frameEdit, frameFields, ...extra });
|
||||
pendingLoad = undefined;
|
||||
@@ -215,6 +254,8 @@ export function createCadHost<D extends CadHostDrawing, M = unknown, Q = unknown
|
||||
text?: string;
|
||||
actionId?: string;
|
||||
durationMs?: number;
|
||||
link?: string;
|
||||
count?: number;
|
||||
};
|
||||
if (message.type === CAD_TOAST_MESSAGE) {
|
||||
const kind = (["info", "success", "warning", "error"] as const).find(
|
||||
@@ -240,6 +281,14 @@ export function createCadHost<D extends CadHostDrawing, M = unknown, Q = unknown
|
||||
} else if (message.type === CAD_LOADED_MESSAGE) {
|
||||
stopLoadWatchdog();
|
||||
element.dataset.loading = "false";
|
||||
drawingLoaded = true;
|
||||
const queued = afterLoad;
|
||||
afterLoad = [];
|
||||
queued.forEach(post);
|
||||
} else if (message.type === CAD_TABLE_UPDATED_MESSAGE && message.link) {
|
||||
const [first, ...rest] = tableWaits.get(message.link) ?? [];
|
||||
tableWaits.set(message.link, rest);
|
||||
first?.(message.count ?? 0);
|
||||
} else if (message.type === CAD_ERROR_MESSAGE) {
|
||||
stopLoadWatchdog();
|
||||
showFailure(message.detail ?? "CAD 도면을 표시하지 못했습니다.");
|
||||
@@ -272,6 +321,8 @@ export function createCadHost<D extends CadHostDrawing, M = unknown, Q = unknown
|
||||
},
|
||||
load,
|
||||
requestSave,
|
||||
placeTable,
|
||||
updateTable,
|
||||
destroy: () => {
|
||||
stopLoadWatchdog();
|
||||
window.removeEventListener("message", onMessage);
|
||||
|
||||
Reference in New Issue
Block a user