diff --git a/M02_MasterTemplete/M02_MasterTemplete_AreaDrawing.ts b/M02_MasterTemplete/M02_MasterTemplete_AreaDrawing.ts index 9a274dd26..b1ae795f5 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_AreaDrawing.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_AreaDrawing.ts @@ -160,7 +160,6 @@ export function createAreaDrawing( originMarker: true, noArea: true, frame: true, - noImport: true, pickTabs: true, }); frame = stage.querySelector("iframe"); diff --git a/M02_MasterTemplete/M02_MasterTemplete_CardHelp.ts b/M02_MasterTemplete/M02_MasterTemplete_CardHelp.ts index d44febe33..46020e95a 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_CardHelp.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_CardHelp.ts @@ -40,7 +40,7 @@ export const CARD_HELP: Record<"structure" | "labor" | "area", CardHelp> = { features: [ SAVE, take("도면"), - ["수정", "도면 상세(전체 편집 화면)를 엶 — 파일 업로드(DXF · DWG)는 여기"], + ["수정", "도면 상세(전체 편집 화면)를 엶 — DWG 불러오기(CAD [삽입])는 여기"], clear("도면"), FOLD, ], @@ -98,7 +98,7 @@ export const CARD_HELP: Record<"structure" | "labor" | "area", CardHelp> = { /** 상세에만 있는 단추 줄(49-7) — 카드 도움말 글 한 벌 뒤에 더함 */ const DETAIL_ONLY: Record = { - structure: [["파일 업로드", "DXF · DWG 파일을 도면으로 불러옴(상세 머리 [파일 업로드])"]], + structure: [["DWG 불러오기", "DWG · DXF 파일을 지금 도면에 더함(CAD 리본 [삽입])"]], labor: [], area: [["도면으로 보내기", "고른 범위를 도면 표로 보냄(상세 머리)"]], }; diff --git a/M02_MasterTemplete/M02_MasterTemplete_Drawing.css b/M02_MasterTemplete/M02_MasterTemplete_Drawing.css index 02d2c40af..157e61d99 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Drawing.css +++ b/M02_MasterTemplete/M02_MasterTemplete_Drawing.css @@ -67,13 +67,6 @@ gap: var(--spacing-8); } -.m02-drawing__actions { - display: flex; - gap: var(--spacing-8); - margin-left: auto; - white-space: nowrap; -} - .m02-pop { display: block; background-color: transparent; /* 단추 아래 뜨는 작은 창 — 뒤를 가리지 않음 */ diff --git a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts index fc082800e..dd9de6500 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Drawing.ts @@ -39,7 +39,7 @@ export interface DrawingTemplateOptions { projectId?: string | null; /** 저장 안 한 고침이 생기면 true — CAD 편집 · 작도 영역 값 바꿈. */ onChanged?: (dirty: boolean) => void; - /** 페이지 제목 줄 안의 빈 칸 — 있으면 작도 영역 칸 · [파일 업로드]를 거기 한 줄로 놓는다. */ + /** 페이지 제목 줄 안의 빈 칸 — 있으면 작도 영역 칸을 거기 한 줄로 놓는다. */ headerSlot?: HTMLElement; /** CAD 좌측 패널(특성 · 도면층)을 접힌 채로 연다 — 누르면 펼침(구조물 도면 미리보기). */ panelsCollapsed?: boolean; @@ -51,8 +51,6 @@ export interface DrawingTemplateOptions { noArea?: boolean; /** B07 도각을 외곽 좌하단 (0,0) 에 얹음 — 잠금 층 · 보여주기만(돌려줄 때 뺌 · 저장 안 됨). */ frame?: boolean; - /** [파일 업로드] 단추를 안 둠 — 집계표 카드 미리보기(불러오기는 도면 상세에서만). */ - noImport?: boolean; /** 장id(82-1) — 자동백업 칸을 장마다 나눔(1장 = 빈 값 · 옛 칸 그대로) */ sheet?: string; /** 장 도번(82-2) — 얹은 도각 `{{도면번호}}` 자리 */ @@ -142,25 +140,6 @@ function withoutFrame(drawing: DrawingTemplateDoc): DrawingTemplateDoc { }; } -async function importDrawingFile( - file: File, -): Promise<{ drawing: DrawingTemplateDoc; entity_count: number }> { - const form = new FormData(); - form.append("file", file); - const response = await fetch(`${API_BASE_URL}/m02/drawing-import`, { - method: "POST", - credentials: "include", - body: form, - }); - const payload = (await response.json()) as { - drawing: DrawingTemplateDoc; - entity_count: number; - message?: string; - }; - if (!response.ok) throw new Error(payload.message ?? `HTTP ${response.status}`); - return payload; -} - export function mountDrawingTemplate( container: HTMLElement, doc: DrawingTemplateDoc, @@ -292,45 +271,6 @@ export function mountDrawingTemplate( after?.(); }; - const actions = document.createElement("div"); - actions.className = "m02-drawing__actions"; - const canImport = !readOnly && options.noImport !== true; - if (canImport) { - const fileInput = document.createElement("input"); - fileInput.type = "file"; - fileInput.accept = ".dxf,.dwg"; - fileInput.hidden = true; - fileInput.addEventListener("change", () => { - const file = fileInput.files?.[0]; - fileInput.value = ""; - if (!file) return; - importButton.disabled = true; - importDrawingFile(file) - .then((response) => { - // 불러온 도각은 아직 저장하지 않는다 — 자리표를 놓고 [저장]을 눌러야 양식이 된다. - void load(response.drawing); - options.onChanged?.(true); // 불러온 것은 아직 저장 전 — 떠날 때 묻게 함 - showToast(`도형 ${response.entity_count}개를 불러왔습니다.`, "success"); - }) - .catch((error) => - showToast( - error instanceof Error ? error.message : "도각 파일을 불러오지 못했습니다.", - "error", - ), - ) - .finally(() => (importButton.disabled = false)); - }); - const importButton = createButton({ - label: "파일 업로드", - variant: "filled", - onClick: () => fileInput.click(), - }); - // 구조물 조합 층 단추([마스터])와 같은 꼴 — 실무자료 [파일 업로드]와 같은 종류(362-2) - importButton.classList.add("m02-layers__btn"); - importButton.title = importButton.ariaLabel = "파일 업로드 (DXF · DWG)"; - actions.append(importButton, fileInput); - } - const getDoc = async (): Promise => { const { drawing: saved } = await cad.requestSave(); const drawing = options.frame ? withoutFrame(saved) : saved; @@ -345,13 +285,14 @@ export function mountDrawingTemplate( }; // 한 줄 — 페이지가 머리 칸(headerSlot)을 주면 거기, 아니면 그림 칸 위에 작게. - toolbar.append(...(noArea ? [] : [areaButton]), actions); + // DWG · DXF 불러오기 = CAD 리본 [삽입 → DWG 불러오기] · 끌어다 놓기 한 길(495-2) + toolbar.append(...(noArea ? [] : [areaButton])); const tabs = options.tabs ? [options.tabs] : []; if (options.headerSlot) { toolbar.classList.add("m02-drawing__toolbar--slot"); options.headerSlot.append(toolbar); root.append(...tabs, cad.element); - } else root.append(...(noArea && !canImport ? [] : [toolbar]), ...tabs, cad.element); + } else root.append(...(noArea ? [] : [toolbar]), ...tabs, cad.element); container.append(root); void load(doc); diff --git a/M02_MasterTemplete/M02_MasterTemplete_DrawingCard.ts b/M02_MasterTemplete/M02_MasterTemplete_DrawingCard.ts index 35e7f6764..099adde23 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_DrawingCard.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_DrawingCard.ts @@ -85,7 +85,6 @@ function mountStructure( originMarker: true, // 좌표 0,0 기준점 십자 noArea: true, // 작도 영역 칸 없음 frame: true, // 도각 = 보여주기만 · 외곽 좌하단 (0,0)(56장) - noImport: true, // 파일 업로드는 도면 상세에서만(47-2) pickTabs: true, ...hooks, }); diff --git a/resources/tester/test_m02_card_shell.py b/resources/tester/test_m02_card_shell.py index ec645f62b..49976ec1e 100644 --- a/resources/tester/test_m02_card_shell.py +++ b/resources/tester/test_m02_card_shell.py @@ -117,10 +117,12 @@ def test_도움말_제목_옆_네_절(): def test_미리보기_파일_불러오기_없음(): - """47-2 — 도면 카드 미리보기엔 [파일 업로드] 없음 · 도면 상세(전체 편집)는 그대로.""" + """47-2 · 495-2 — M02 [파일 업로드] 없음(카드 · 상세 모두) · DWG = CAD [삽입 → DWG 불러오기] 한 길.""" drawing = _text("M02_MasterTemplete_Drawing.ts") - assert "const canImport = !readOnly && options.noImport !== true;" in drawing - assert "noImport: true," in _text("M02_MasterTemplete_DrawingCard.ts") + for gone in ("noImport", "canImport", "importDrawingFile", "/m02/drawing-import"): + assert gone not in drawing + for name in ("M02_MasterTemplete_DrawingCard.ts", "M02_MasterTemplete_AreaDrawing.ts"): + assert "noImport" not in _text(name) def test_일위대가_줄_고름과_옵션_단추(): @@ -181,10 +183,10 @@ def test_옵션_줄_구분_이름_별칭_병합(): def test_도면_상세_머리_파일_업로드_단추(): - """362-2 — 도면 상세 머리 📂 → 글 단추 [파일 업로드](구조물 조합 층 단추 꼴 · 실무자료와 같은 종류).""" + """362-2 → 495-2 — 도면 상세 머리 [파일 업로드] 지움 · 도움말 = CAD [삽입] DWG 불러오기.""" drawing = _text("M02_MasterTemplete_Drawing.ts") - assert 'label: "파일 업로드",' in drawing and 'variant: "filled",' in drawing - assert 'importButton.classList.add("m02-layers__btn");' in drawing - assert '"파일 업로드 (DXF · DWG)"' in drawing + assert "파일 업로드" not in drawing and "importButton" not in drawing assert "📂" not in drawing and "파일 불러오기 (DXF" not in drawing + help_ = _text("M02_MasterTemplete_CardHelp.ts") + assert "파일 업로드" not in help_ and '["DWG 불러오기",' in help_ assert "📂" not in _text("M02_MasterTemplete_CardHelp.ts") diff --git a/resources/tester/ui_checks/47-1_카드_도움말.js b/resources/tester/ui_checks/47-1_카드_도움말.js index 302ffbe11..322a91eec 100644 --- a/resources/tester/ui_checks/47-1_카드_도움말.js +++ b/resources/tester/ui_checks/47-1_카드_도움말.js @@ -1,4 +1,4 @@ -/* 47-1 · 47-2 — 구조물 조합 카드 셋 [?] = 제목 바로 옆 · 도움말 네 절 · 도면 미리보기 [파일 업로드] 없음 · 도면 상세 [파일 업로드] 있음 +/* 47-1 · 47-2 — 구조물 조합 카드 셋 [?] = 제목 바로 옆 · 도움말 네 절 · 도면 미리보기 · 도면 상세 [파일 업로드] 없음(495-2 · DWG = CAD [삽입]) * 시작 화면: M02 마스터 템플릿 · 마스터 층(#/m02-master-template?open=구조물조합&root=master) · 시스템 관리자 · * 나무에 item1(구조물 조합)이 있음 * 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌 · 20초 안) @@ -6,7 +6,7 @@ * 기대 수치: * - cards = 3(도면 정보 · 일위대가 · 면적산출) · 카드마다 nextToTitle = true(? 가 제목 글 바로 다음) · * inTools = false · parts = ["about","keys","features","steps"] · opened = true · closed = true - * - previewImport = 0(카드 미리보기 [파일 업로드]) · detailImport = 1(도면 상세 [파일 업로드]) · back = true(카드 화면으로 돌아옴) + * - previewImport = 0(카드 미리보기 [파일 업로드]) · detailImport = 0(도면 상세 [파일 업로드] · 495-2 지움) · back = true(카드 화면으로 돌아옴) */ (async () => { const w = (ms) => new Promise((r) => setTimeout(r, ms)); @@ -57,10 +57,14 @@ if (!edit) return JSON.stringify({ ...out, error: "도면 [수정] 없음" }); const hash = location.hash; edit.click(); - out.detailImport = (await until(() => imports(), 8000)) || 0; - [...document.querySelectorAll("button")] - .find((b) => vis(b) && b.innerText.trim() === "돌아가기") - ?.click(); + const back = () => + [...document.querySelectorAll("button")].find( + (b) => vis(b) && b.innerText.trim() === "돌아가기", + ); + await until(back, 8000); + await w(2500); + out.detailImport = imports(); + back()?.click(); out.back = !!(await until( () => location.hash === hash && document.querySelector(".m02-struct__card"), ));