From af5d6a46d30b0397c3f7c07f5cc6f6f7a6523e5c Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 15 Nov 2026 13:32:24 +0900 Subject: [PATCH] =?UTF-8?q?feat(836-3):=20=EA=B3=B5=EC=9A=A9=20=EB=8B=A8?= =?UTF-8?q?=EA=B0=80=EC=82=B0=EC=B6=9C=20=EB=B3=B4=EA=B8=B0=20=EA=B3=A0?= =?UTF-8?q?=EB=A5=B4=EA=B8=B0=EC=97=90=EC=84=9C=20=E3=80=8C=EB=8B=A8?= =?UTF-8?q?=EA=B0=80=EC=82=B0=EC=B6=9C=20=EC=83=81=EC=84=B8=E3=80=8D=20?= =?UTF-8?q?=ED=83=AD=20=EA=B1=B7=EC=9D=8C=20=E2=80=94=20=EC=88=98=EC=8B=9D?= =?UTF-8?q?=20=EB=B3=B4=EA=B8=B0=20=ED=95=98=EB=82=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - M01 단가산출 기초 · M02 단가산출 · 일위대가 줄 모달 머리의 보기 고르기 단추 없음 - 수식 문서 없는 줄(일위대가 로직 줄 등)은 단가산출 상세 몸만 보임(빈 화면 없음) - 낡은 시험 여섯(보기 둘 확인) = 보기 고르기 없음 확인으로 고침 --- M01_MasterData/M01_MasterData_UI_LogicLab.ts | 9 +--- .../M01_MasterData_UI_LogicLab_View.ts | 31 +---------- .../M02_MasterTemplete_Labor_RowModal.ts | 8 +-- .../M02_MasterTemplete_Sangeun_Detail.ts | 4 +- .../M02_MasterTemplete_Sangeun_Tabs.ts | 54 +++++-------------- resources/tester/test_796_2b_m02_equation.py | 7 ++- resources/tester/test_799_2_old_tabs_gone.py | 6 ++- resources/tester/test_804_2_line_stack.py | 4 +- .../tester/test_804_6_formula_tab_gone.py | 3 +- resources/tester/test_804_7_line_stack_fix.py | 2 +- resources/tester/test_806_1_labor_view.py | 4 +- 11 files changed, 36 insertions(+), 96 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab.ts b/M01_MasterData/M01_MasterData_UI_LogicLab.ts index 7f1f1d0d8..2e60bc6e8 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab.ts @@ -47,7 +47,6 @@ import { tl } from "./M01_MasterData_UI_LogicLab_Text"; import { askBasicInfo } from "./M01_MasterData_UI_LogicLab_Basic"; import { saveRevised } from "./M01_MasterData_UI_LogicLab_Revise"; import { buildLogicSide } from "./M01_MasterData_UI_LogicLab_Side"; -import { createViewPicker } from "./M01_MasterData_UI_LogicLab_View"; import { createStackScreen } from "../A00_Common/line_stack_screen"; import { buildHeadBar } from "./M01_MasterData_UI_Head"; import { fetchSessionUser } from "../A06_Login/A06_Login_Api_Fetch"; @@ -123,10 +122,7 @@ export async function mountM01LogicLab( const editor = el("div", { className: "m01-logic__editor" }); // 로직 상세 — 왼쪽 지금 내용 · 오른쪽 접는 패널 「원문」 const panes = buildLogicSide(editor); - // 보기 고르기 — 머리줄 [신규 로직] 왼쪽 - const views = createViewPicker(editor, (v) => { - if (v === "stack") stack.draw(opened?.origKey ?? "", true); - }); + editor.dataset.view = "stack"; // 보기 = 수식 하나(836-3) — 「단가산출 상세」 덩이는 CSS 로 숨김 const errors = el("div", { className: "ui-banner ui-banner--danger m01-logic__reasons", attrs: { hidden: "" }, @@ -233,7 +229,7 @@ export async function mountM01LogicLab( list.root.hidden = !listing || !loaded; waiting.hidden = loaded; panes.root.hidden = !opened; - back.hidden = views.root.hidden = listing; + back.hidden = listing; // 로직을 골라야 뜻 있는 단추 = 목록에선 숨김(요구 693 · [신규 로직]만 보임) copyButton.hidden = deleteButton.hidden = discardButton.hidden = saveButton.hidden = listing; if (!opened) return; @@ -542,7 +538,6 @@ export async function mountM01LogicLab( title: tx("Title"), status: [pending], buttons: [ - views.root, createButton({ label: tl("New"), variant: "filled", diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_View.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_View.ts index 3c0691704..9dabc3291 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_View.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_View.ts @@ -1,16 +1,11 @@ /* ============================================================================= * M01_MasterData_UI_LogicLab_View.ts - * 「단가산출 로직」 상세 보기 고르기 — 머리줄 [신규 로직] 왼쪽 「분할 고르기 | 세로 나눔선」 - * 보기 둘 = 수식(기본 · 줄 쌓기 화면 `A00_Common/line_stack_screen.ts` · 804-6 옛 수식 문서 탭 걷음) · 단가산출 상세 — 고른 덩이만 보임 + * 「단가산출 로직」 상세 보기 이름표 — 보기 = 수식(줄 쌓기 `A00_Common/line_stack_screen.ts`) 하나 · 고르기 단추 없음(836-3) + * 그릇 `data-view="stack"` 고정 — `data-block="ho"` 덩이(단가산출 상세 표)는 CSS 로 숨김 * 덩이 = `data-block` 이름표 · 숨김 = 그릇 `data-view` + CSS(`LogicLab_Style.css`) — 다시 그려도 고름 유지 * 셈 구동은 화면 칸 없이 `_Logic_Drive.ts` · 기본정보는 이름표 없음(늘 맨 위) - * 기억 = 이 화면 안에서만(로직을 바꿔도 유지 · 새로 들어오면 수식) * ========================================================================== */ -import { createSegment } from "@ui/ui_template_segment"; -import { createToolbar } from "@ui/ui_template_toolbar"; -import { tl } from "./M01_MasterData_UI_LogicLab_Text"; - export type LabView = "stack" | "ho"; /** 덩이에 보기 이름표를 붙여 돌려줌 */ @@ -18,25 +13,3 @@ export const block = (node: T, view: LabView): T => { node.dataset.block = view; return node; }; - -/** 보기 고르기 — `host`(상세 그릇)에 `data-view` 를 둠 · `root` 는 머리줄에 놓음 */ -export function createViewPicker( - host: HTMLElement, - onChange?: (v: LabView) => void, -): { root: HTMLElement } { - host.dataset.view = "stack"; - const segment = createSegment({ - options: [ - { value: "stack", label: tl("View_Equation") }, - { value: "ho", label: tl("Ho_Title") }, - ], - value: "stack", - size: 32, - ariaLabel: tl("View_Label"), - onChange: (v) => { - host.dataset.view = v; - onChange?.(v as LabView); - }, - }); - return { root: createToolbar({ items: [segment.root, "divider"], label: tl("View_Label") }) }; -} diff --git a/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts b/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts index f00457903..abb8bef2d 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Labor_RowModal.ts @@ -2,11 +2,11 @@ * M02_MasterTemplete_Labor_RowModal.ts * 일위대가표 줄 누름 모달(PLAN 723-2 · 723-3 · 요구서_내역16 2장 4 · 5) — 일위대가표에서 빠진 줄 동작을 모달 안으로. * · 로직 줄(단가산출 문서 없음) · 셈 주입 SK 줄 = 머리(이름 · 「1 ㎡ 당」) · - * 단가산출 상세 줄 모드(717-2b · `Labor_RowSk` · 보기 고르기 = 모달 머리 · 옛 [항목 추가] · [율 줄 추가] 없음) · + * 단가산출 상세 줄 모드(717-2b · `Labor_RowSk` · 수식 보기 하나(836-3) · 옛 [항목 추가] · [율 줄 추가] 없음) · * 로직 자재(바꾸기 · 기본 · 세 칸 · `Labor_LogicMats`) * · [적용] = 그 줄 덮개(M02 변경 항목) + 옵션(상세 옵션 칸 → 그 줄 입력값) * · 808-1(요구 701-4 · 5) — 옛 [옵션] · [단가산출로도 저장] · [항목 추가] · [율 줄 추가] 걷음 · 일위대가 줄 = 저장 때 - * M01 로직 줄 + 고침으로 펼쳐 담김(740-1 · `본뜬` = 온 단가산출) → 수식 문서 없음 = 수식 탭 · 보기 고르기 없이 단가산출 상세만 + + * M01 로직 줄 + 고침으로 펼쳐 담김(740-1 · `본뜬` = 온 단가산출) → 수식 문서 없음 = 수식 보기 없이 단가산출 상세 몸만 + * 안내(온 단가산출 이름 · 수식은 그 단가산출에서 고쳐 다시 담음) * · 사용자 자재 줄 = 자재 모달(세 칸 · `Labor_MatTable` 한 줄) * · 고침 = 그 줄 화면 캐시(저장은 [저장]) · 금액은 표가 다시 셈 → `watch` 로 받아 다시 그림 @@ -128,7 +128,7 @@ export function openRowModal(o: RowModalOptions): void { return false; } - // 단가산출 상세 줄 모드(723-3) — 셈 주입(프로젝트 복사본)엔 없음 · 보기 고르기 = 모달 머리(808-1) + // 단가산출 상세 줄 모드(723-3) — 셈 주입(프로젝트 복사본)엔 없음 · 수식 단추 = 모달 머리(808-1) const slot = el("span", { className: "m02-main__tools" }); const skHost = el("div", { attrs: { "data-row-sk-host": "" } }); let sk: RowSkHandle | null = null; @@ -185,7 +185,7 @@ export function openRowModal(o: RowModalOptions): void { closeLabel: tc("In_Close"), width: "1100px", wide: true, - actions: row.참조 ? [slot, ...tools] : tools, // 로직 줄 = 보기 고르기 없음(상세만) + actions: row.참조 ? [slot, ...tools] : tools, // 로직 줄 = 머리 단추 없음(상세만) beforeClose: async () => { if (sk?.take() && !(await askConfirm({ message: t("Discard"), danger: true }))) return false; finish(); diff --git a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts index 79f9a69ab..7407270bb 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Detail.ts @@ -198,7 +198,7 @@ export function mountSangeunDetail( : [ el("div", { className: "m02-sk__head", - children: [tabs.picker, tabs.tools, addButton, rateButton], + children: [tabs.tools, addButton, rateButton], }), ]), tabs.host, @@ -207,7 +207,7 @@ export function mountSangeunDetail( }); host.replaceChildren(side ? side.wrap(main) : main); opt.slot?.replaceChildren( - el("span", { className: "ui-toolbar m02-main__tools", children: [tabs.picker, tabs.tools] }), + el("span", { className: "ui-toolbar m02-main__tools", children: [tabs.tools] }), ); const opened = (): boolean => (doc.열린입력 ?? []).length > 0; diff --git a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts index b7861ad5b..da4bf9e81 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts @@ -1,22 +1,18 @@ /* ============================================================================= * M02_MasterTemplete_Sangeun_Tabs.ts - * M02 단가산출(SK) 상세 보기 고르기(PLAN 799-2 · 804-2 · 804-6 · 요구 686-1) — 수식(첫 탭 · 줄 쌓기) · 단가산출 상세. + * M02 단가산출(SK) 상세 보기(PLAN 799-2 · 804-2 · 804-6 · 836-3) — 수식(줄 쌓기) 하나 · 보기 고르기 단추 없음. * 수식 = 공용 줄 쌓기 화면(`A00_Common/line_stack_screen.ts` · M01 과 같은 꼴) — 길 앞머리만 M02 사본 길 * (`/m02/layers/{층}/sangeun/{키}/doc` · 802-4a) · 층 쓰기 권한 없으면 읽기만 * 저장(804-8 · `page` 있음 = 단가산출 화면) = 페이지 [저장] · [되돌림] 한 번에 — 탭 위 저장 단추 없음(M01 과 같음) - * 옛 수식 문서 탭(802-4b-2)은 804-6 에 걷음 · 단가산출 상세 = 상세가 쥔 `editor`(수식일 때 숨김) + * 수식 문서 없는 줄(일위대가 줄 모달 등) = 상세가 쥔 `editor`(단가산출 상세 몸)만 보임 — 빈 화면 없음 * 저장 안 한 SK(일위대가 줄 모달 · 새 SK) = 「저장한 단가산출만」 글 - * [단가 갱신] · [재생성](808-1 · 요구 701-3) = `tools` — 보기 고르기 옆 머리 줄(수식 보기일 때만) + * [단가 갱신] · [재생성](808-1 · 요구 701-3) = `tools` — 머리 줄(수식 보기일 때만) * ========================================================================== */ -import { createSegment } from "@ui/ui_template_segment"; import { createStackScreen } from "../A00_Common/line_stack_screen"; import { el } from "@ui/ui_template_elements"; -import { tl } from "../M01_MasterData/M01_MasterData_UI_LogicLab_Text"; import type { Layer } from "./M02_MasterTemplete_Api_Fetch"; -type View = "stack" | "ho"; - export interface SkEquationOptions { scope: { layer: Layer; owner: string | null }; edit: boolean; @@ -36,13 +32,12 @@ export function skDocPath(scope: SkEquationOptions["scope"], key: string, path: return ask ? `${at}?${ask}` : at; } -/** 보기 고르기 · 수식 그릇 — `editor` = 단가산출 상세 그릇(수식일 때 숨김) */ +/** 수식 그릇 — `editor` = 단가산출 상세 그릇(수식 문서 있을 때 숨김) */ export function createSangeunTabs( editor: HTMLElement, opt: SkEquationOptions, ): { - picker: HTMLElement; - /** 수식 화면 단추([단가 갱신] · [재생성]) — 보기 고르기 옆(머리 줄) */ + /** 수식 화면 단추([단가 갱신] · [재생성]) — 머리 줄 */ tools: HTMLElement; host: HTMLElement; /** 저장한 SK 키(빈 키 = 저장 전) */ @@ -62,41 +57,20 @@ export function createSangeunTabs( page: opt.page, tools, }); - let key = ""; - let view: View = "stack"; - const show = (v: View): void => { - view = v; - stack.root.hidden = tools.hidden = v !== "stack"; - editor.hidden = v !== "ho"; - if (!editor.hidden) editor.dataset.view = v; + const show = (doc: boolean): void => { + stack.root.hidden = tools.hidden = !doc; + editor.hidden = doc; + if (!doc) editor.dataset.view = "ho"; }; - const picker = createSegment({ - options: [ - { value: "stack", label: tl("View_Equation") }, - { value: "ho", label: tl("Ho_Title") }, - ], - value: "stack", - size: 32, - ariaLabel: tl("View_Label"), - onChange: (v) => { - show(v as View); - if (v === "stack") stack.draw(key, true); - }, - }); - picker.root.dataset.skViews = ""; - show("stack"); + show(true); return { - picker: picker.root, tools, host: el("div", { className: "m02-sk__views", children: [stack.root] }), draw: (k: string) => { - key = k; - // 문서 없는 줄(일위대가 로직 줄 모달 등 · 페이지 아님) = 단가산출 상세부터(808-1 · 수식은 문서가 있어야) - if (!k && !opt.page && view === "stack") { - picker.set("ho"); - return show("ho"); - } - if (view === "stack") stack.draw(k); + // 문서 없는 줄(일위대가 로직 줄 모달 등 · 페이지 아님) = 단가산출 상세 몸만(808-1 · 수식은 문서가 있어야) + const doc = !!k || !!opt.page; + show(doc); + if (doc) stack.draw(k); }, canLeave: () => stack.canLeave(), dirty: () => stack.dirty(), diff --git a/resources/tester/test_796_2b_m02_equation.py b/resources/tester/test_796_2b_m02_equation.py index 5bddc1dcf..097b23212 100644 --- a/resources/tester/test_796_2b_m02_equation.py +++ b/resources/tester/test_796_2b_m02_equation.py @@ -185,7 +185,6 @@ def test_screen_same_part_first_tab(): root = Path(__file__).resolve().parents[2] / "M02_MasterTemplete" assert not (root / "M02_MasterTemplete_Sangeun_Equation.ts").exists() tabs = (root / "M02_MasterTemplete_Sangeun_Tabs.ts").read_text(encoding="utf-8") - views = re.findall(r'\{ value: "(\w+)", label: ', tabs) - # 799-2 — 시트 · 인력·재료·경비 · 시험 계산 · 텍스트 수식 걷음 - assert views == ["equation", "ho"] - assert 'show("equation");' in tabs + # 799-2 · 836-3 — 시트 · 인력·재료·경비 · 시험 계산 · 텍스트 수식 · 보기 고르기(단가산출 상세 탭) 걷음 + assert not re.findall(r'\{ value: "(\w+)", label: ', tabs) and "createSegment" not in tabs + assert "show(true);" in tabs diff --git a/resources/tester/test_799_2_old_tabs_gone.py b/resources/tester/test_799_2_old_tabs_gone.py index 8fe3201cd..671be4d3c 100644 --- a/resources/tester/test_799_2_old_tabs_gone.py +++ b/resources/tester/test_799_2_old_tabs_gone.py @@ -56,11 +56,13 @@ def test_걷은_파일_없고_부르는_곳_없음(): ) -def test_보기는_수식_단가산출상세_둘(): +def test_보기는_수식_하나_고르기_없음(): m01 = _text(M01 / "M01_MasterData_UI_LogicLab_View.ts") m02 = _text(M02 / "M02_MasterTemplete_Sangeun_Tabs.ts") for src in (m01, m02): - assert re.findall(r'\{ value: "(\w+)", label: ', src) == ["stack", "ho"] # 804-6 + assert not re.findall(r'\{ value: "(\w+)", label: ', src) and "createSegment" not in src + assert "createViewPicker" not in _text(M01 / "M01_MasterData_UI_LogicLab.ts") # 836-3 + assert 'editor.dataset.view = "stack";' in _text(M01 / "M01_MasterData_UI_LogicLab.ts") assert 'export type LabView = "stack" | "ho";' in m01 css = _text(M01 / "M01_MasterData_UI_LogicLab_Style.css") assert '[data-view="ho"] [data-block]:not([data-block="ho"])' in css diff --git a/resources/tester/test_804_2_line_stack.py b/resources/tester/test_804_2_line_stack.py index 6755f524f..67385f733 100644 --- a/resources/tester/test_804_2_line_stack.py +++ b/resources/tester/test_804_2_line_stack.py @@ -240,9 +240,7 @@ def test_화면_이음(): 'base: "/m01/logic/doc",' in lab and 'cache: "m01_doc_drafts",' in lab ) # 804-7 page = 페이지 [저장] assert "stack: stack.root" in lab and "=> stack.canLeave();" in lab # 804-6 수식 탭 = 줄 쌓기 - assert '{ value: "stack", label: tl("View_Equation") }' in _src( - "M01_MasterData/M01_MasterData_UI_LogicLab_View.ts" - ) + assert 'editor.dataset.view = "stack";' in lab # 836-3 보기 고르기 없음 · 수식 하나 assert '[data-view="stack"]' in _src("M01_MasterData/M01_MasterData_UI_LogicLab_Style.css") tabs = _src("M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts") assert 'cache: "m02_sk_doc_drafts"' in tabs and tabs.count("skDocPath(opt.scope, k, p)") == 1 diff --git a/resources/tester/test_804_6_formula_tab_gone.py b/resources/tester/test_804_6_formula_tab_gone.py index 07da9c42b..032cbaecd 100644 --- a/resources/tester/test_804_6_formula_tab_gone.py +++ b/resources/tester/test_804_6_formula_tab_gone.py @@ -56,8 +56,7 @@ def test_보기_수식은_줄쌓기_첫탭(): "M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts", ): src = _text(rel) - assert '{ value: "stack", label: tl("View_Equation") },' in src, rel - assert 'value: "stack",\n' in src and '"equation"' not in src, rel + assert "createSegment" not in src and '"equation"' not in src, rel # 836-3 고르기 없음 lab = _text("M01_MasterData/M01_MasterData_UI_LogicLab.ts") assert "createStackScreen({" in lab and "createDocScreen" not in lab diff --git a/resources/tester/test_804_7_line_stack_fix.py b/resources/tester/test_804_7_line_stack_fix.py index 3a144e911..0fa570788 100644 --- a/resources/tester/test_804_7_line_stack_fix.py +++ b/resources/tester/test_804_7_line_stack_fix.py @@ -340,7 +340,7 @@ def test_808_1_수량_칸_식_글_꼬리표_글꼴_머리(): assert "opt.tools?.replaceChildren(...tools);" in screen assert "children: opt.tools ? [] : tools" in screen tabs = _src("M02_MasterTemplete/M02_MasterTemplete_Sangeun_Tabs.ts") - assert 'stack.root.hidden = tools.hidden = v !== "stack";' in tabs + assert "stack.root.hidden = tools.hidden = !doc;" in tabs assert 'Reset: ["M01 값으로", "To M01"]' in _src( "M02_MasterTemplete/M02_MasterTemplete_Main_Actions.ts" ) diff --git a/resources/tester/test_806_1_labor_view.py b/resources/tester/test_806_1_labor_view.py index 5f769b4e2..271195ff3 100644 --- a/resources/tester/test_806_1_labor_view.py +++ b/resources/tester/test_806_1_labor_view.py @@ -134,7 +134,7 @@ def test_808_1_모달_머리_일원화(): assert "slot: o.slot," in _src("M02_MasterTemplete_Labor_RowSk.ts") detail = _src("M02_MasterTemplete_Sangeun_Detail.ts") assert "...(opt.slot\n ? []" in detail # 머리 칸 있으면 옛 단추 줄 없음 - assert "children: [tabs.picker, tabs.tools]" in detail + assert "children: [tabs.tools]" in detail and "tabs.picker" not in detail assert r"/^SK-(?!0{6})\d{6}$/" in detail tabs = _src("M02_MasterTemplete_Sangeun_Tabs.ts") - assert 'if (!k && !opt.page && view === "stack")' in tabs + assert "const doc = !!k || !!opt.page;" in tabs # 836-3 문서 없는 줄 = 상세 몸만