diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index 8c7d44ae4..71ae02077 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -487,6 +487,8 @@ ative-standard.js에 표준시장단가 원천(SilJukDat)과 내역 행(EstMainD - 남음: 구성비·요율 전환(CalcBase), 약어 표시(SName), 제비율 기준 문서 보기(원본 한글 파일). - [x] 수량산출서 검색·전체보기(원본 TFRMMULLANG btnSerch·btnAllDisplay — 빈칸·|·괄호 무시 포함 검색) — 고르기 줄을 `native-quantity-sheets.js` 로 옮겨 700줄 제한 유지. - 검증완료: `test_est_quantity_sheets.py` 검색 시험 포함 수량 시험 22개 통과. ORCA 브라우저에서 「집수」 검색 → 항목에 집수정이 있는 「배수」만·선택 이동, 전체보기 → 3개 복귀, 샘플 복구. + - [x] 블럭 파일로 저장하기·블럭 파일에서 붙여넣기(원본 mnuBlockSaveToFile·mnuLoadFromFile) — 복사·잘라낸 행 묶음을 `.estblock.json`(종류 est-web-block-1, 표 이름·행)으로 내려받고, 파일을 읽어 같은 종류 화면에 붙여넣음(다른 공사로 옮기기). + - 검증완료: 바인딩 시험 통과. ORCA 브라우저에서 자재 2행 복사 → 파일 저장(2,559 바이트) → 같은 내용 읽어 붙여넣기 30→32행, 잘못된 파일 거부, 샘플 복구. - [x] 인쇄 용지 A0·A1·B4 와 인쇄 기본양식(원본 TFRMSCHEDULE mnuA0~B4 · TFRMESTPREVIEW2 mnuFormatSave·mnuFromatOpen) — 용지 A4·A3·B4·A1·A0(A0·A1 은 mm 크기, 가로면 바꿔 씀), 인쇄 창 「기본양식저장」(용지·여백·글자·줄 수 등, 서식 고르기·본문 글 제외 — 양식 보관함 종류 print) · 「기본양식열기」. - 검증완료: 바인딩·양식 시험 3개 통과. ORCA 브라우저에서 A1 가로 → @page 841mm 594mm, 기본양식 저장 뒤 A4 로 바꾸고 열기 → A1 복원, 양식·설정 지워 복구. - [x] 원가계산서 내용 삭제·기본양식으로 저장(원본 TFRMWONGABASE popupContentDel A7 · popupSaveAsMain) — 원가계산서(W) 「선택 줄 내용 삭제」: 연결·금액·비율·요율·산출근거·자리 비움(이름·기호 유지, 재계산 없음). 양식 목록 「기본양식으로 저장」: 이름 「기본양식」 — 새 내역서를 만들 때 원가계산서로 씀. diff --git a/tools/est-test/index.html b/tools/est-test/index.html index 4a83a9aad..40873be90 100644 --- a/tools/est-test/index.html +++ b/tools/est-test/index.html @@ -57,6 +57,7 @@ + @@ -131,7 +132,9 @@ > + >
diff --git a/tools/est-test/native-actions.js b/tools/est-test/native-actions.js index a61124e6d..d01a765b0 100644 --- a/tools/est-test/native-actions.js +++ b/tools/est-test/native-actions.js @@ -685,5 +685,7 @@ const EstActions = (() => { EstAttachments.install(); EstStandard.install(); } - return { install, form, undo }; + const clip = () => ({ table: clipboardTable, rows: clipboard }); + const setClip = (table, rows) => ((clipboardTable = table), (clipboard = structuredClone(rows))); + return { install, form, undo, clip, setClip }; })(); diff --git a/tools/est-test/native-block-file.js b/tools/est-test/native-block-file.js new file mode 100644 index 000000000..1ddd0c056 --- /dev/null +++ b/tools/est-test/native-block-file.js @@ -0,0 +1,48 @@ +// 원본 「블럭 파일로 저장하기」(mnuBlockSaveToFile)·「블럭 파일에서 붙여넣기」(mnuLoadFromFile) — 복사·잘라낸 행 묶음을 +// 파일(.estblock.json)로 내려받고, 파일을 읽어 복사판에 올린 뒤 현재 화면에 붙여넣는다(같은 종류 자료만). +const EstBlockFile = (() => { + const KIND = "est-web-block-1"; + function save() { + const { table, rows } = EstActions.clip(); + if (!rows.length) throw Error("먼저 행을 복사하거나 잘라내세요."); + EstApp.download( + `${EstApp.state.project.name || "블럭"}.${table}.estblock.json`, + JSON.stringify({ kind: KIND, table, rows }, null, 1), + ); + } + function parse(text) { + const data = JSON.parse(text); + if (data?.kind !== KIND || !Array.isArray(data.rows) || !data.rows.length || !data.table) + throw Error("블럭 파일이 아닙니다."); + if (data.rows.some((r) => !r || typeof r !== "object" || Array.isArray(r))) + throw Error("블럭 파일 행이 올바르지 않습니다."); + return data; + } + function load(state) { + const picker = document.createElement("input"); + picker.type = "file"; + picker.accept = ".json"; + picker.addEventListener("change", async () => { + try { + const file = picker.files[0]; + if (!file) return; + const data = parse(await file.text()); + if (data.table !== state.view) + throw Error("블럭 파일과 같은 종류의 자료 화면에서 붙여넣으세요."); + EstActions.setClip(data.table, data.rows); + document.querySelector('[data-action="paste-row"]')?.click(); + } catch (error) { + state.notice = error.message; + EstApp.render(); + } + }); + picker.click(); + } + function handle(name, state) { + if (name === "block-save-file") save(); + else if (name === "block-load-file") load(state); + else return false; + return true; + } + return { parse, handle }; +})(); diff --git a/tools/est-test/native-business-actions.js b/tools/est-test/native-business-actions.js index 1f660b9c5..830cd5aa2 100644 --- a/tools/est-test/native-business-actions.js +++ b/tools/est-test/native-business-actions.js @@ -628,7 +628,8 @@ const EstBusinessActions = (() => { (typeof EstCodeChangeView !== "undefined" && EstCodeChangeView.handle(name, state, node)) || (typeof EstSources !== "undefined" && EstSources.handle(name, state)) || (typeof EstDocEditor !== "undefined" && EstDocEditor.handle(name, state, node)) || - (typeof EstDocForms !== "undefined" && EstDocForms.handle(name, state, node)) + (typeof EstDocForms !== "undefined" && EstDocForms.handle(name, state, node)) || + (typeof EstBlockFile !== "undefined" && EstBlockFile.handle(name, state)) ) { EstApp.render(); } else if (name === "load-contract" || name === "load-bid") { diff --git a/tools/est-test/server.cjs b/tools/est-test/server.cjs index b8033f970..4d376bfb0 100644 --- a/tools/est-test/server.cjs +++ b/tools/est-test/server.cjs @@ -78,6 +78,7 @@ const allowed = new Set([ "native-doc-editor.js", "native-docs.js", "native-doc-forms.js", + "native-block-file.js", "native-wonga-tools.js", "native-estimate-print.js", "native-xml-check.js",