From 1fd2521e82c3d6497db488669e2c5c926b95d910 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 5 Oct 2026 12:22:39 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore(plan):=2010-5=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EC=9E=91=EC=97=85=20=EC=9B=90=EB=AC=B8(M02=20=EB=8B=A8?= =?UTF-8?q?=EC=B6=94=20=EC=96=91=EC=8B=9D=20=C2=B7=20=EC=A2=8C=EC=B8=A1=20?= =?UTF-8?q?=ED=95=98=EC=9C=84=20=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=20?= =?UTF-8?q?=C2=B7=20=EB=B6=84=EB=A5=98=20=ED=91=9C=20=ED=82=A4=20=EC=A4=84?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FJqWQpoB1RE7hiaQ2wH8qV --- docs/raw/사용자요구/2026-10-05_수정요구.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/raw/사용자요구/2026-10-05_수정요구.md b/docs/raw/사용자요구/2026-10-05_수정요구.md index eec77747b..305ec2bf6 100644 --- a/docs/raw/사용자요구/2026-10-05_수정요구.md +++ b/docs/raw/사용자요구/2026-10-05_수정요구.md @@ -29,3 +29,9 @@ - CAD 프로그램 : 한글입력 안됨. 계획서를 작성하고 코드작업을 진행해줘. 난 이제 자리를 비워야하니까 참고해. + +## 추가작업 (10-5 · 원문 그대로) + +1. M02 페이지의 전체영역에서 알약 템플릿으로 프론트엔드에 사용중인데 버튼들은 기본 버튼 템플릿을 사용하게 변경해서 알약 템플릿은 알약에만 사용하는게 맞아. +2. M02 페이지의 좌측패널 내부 별도의 서브 컨테이너로 구조물도면, 일위대가, 면적산출 구성되어 있는데 이건 필요없어 보임 접근은 구조물 조합을 선택하면 바로 3개의 항목 연결이 보이니 불필요해보여. +3. 구조물 조합 상세 페이지의 구조물 분류 테이블에 일위대가 도면 면적산출 행에 키값들을 노출하고 있는데 이건 필요없어보여. From 40ff4a551c066975509d9d47768b42938ea60347 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 5 Oct 2026 12:23:19 +0900 Subject: [PATCH 2/3] auto: 2026-10-05 12:23 (ESD_LAPTOP) --- docs/raw/사용자요구/2026-10-05_수정요구.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/raw/사용자요구/2026-10-05_수정요구.md b/docs/raw/사용자요구/2026-10-05_수정요구.md index eec77747b..305ec2bf6 100644 --- a/docs/raw/사용자요구/2026-10-05_수정요구.md +++ b/docs/raw/사용자요구/2026-10-05_수정요구.md @@ -29,3 +29,9 @@ - CAD 프로그램 : 한글입력 안됨. 계획서를 작성하고 코드작업을 진행해줘. 난 이제 자리를 비워야하니까 참고해. + +## 추가작업 (10-5 · 원문 그대로) + +1. M02 페이지의 전체영역에서 알약 템플릿으로 프론트엔드에 사용중인데 버튼들은 기본 버튼 템플릿을 사용하게 변경해서 알약 템플릿은 알약에만 사용하는게 맞아. +2. M02 페이지의 좌측패널 내부 별도의 서브 컨테이너로 구조물도면, 일위대가, 면적산출 구성되어 있는데 이건 필요없어 보임 접근은 구조물 조합을 선택하면 바로 3개의 항목 연결이 보이니 불필요해보여. +3. 구조물 조합 상세 페이지의 구조물 분류 테이블에 일위대가 도면 면적산출 행에 키값들을 노출하고 있는데 이건 필요없어보여. From 1ca99ed3ae5fea6fe4a1c0b251f377f2fa80cb4a Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 5 Oct 2026 12:25:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix(M01):=20=EB=A1=9C=EC=A7=81=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=98=A4=EB=A5=B8=EC=AA=BD=20=EB=91=90=20=ED=8C=A8?= =?UTF-8?q?=EB=84=90=20=EA=B3=B5=EC=9A=A9=20=EC=A0=91=EA=B8=B0=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=A1=9C=20=E2=80=94=20=EC=A0=9C=EB=AA=A9=20=ED=96=89?= =?UTF-8?q?=20=EB=88=84=EB=A6=84=20=C2=B7=20=EC=BA=90=EB=9F=BF=20=C2=B7=20?= =?UTF-8?q?=ED=95=98=EB=82=98=EB=A7=8C=20=EC=97=B4=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 흐름도 · 원문 = ui-collapsible 카드(M02 면적산출 오른쪽 패널 꼴) · attachCollapsible 토글 위에 하나만 열림 규칙 - 따로 만든 원문 토글 단추 · 얇은 띠 제거 · 흐름도 패널 자체 접기 단추는 M01 에서 숨김 - 둘 다 접힘 = 제목 행 둘(칸 140px) · 취향 기억(m01-logic-panel) 그대로 - 44-4 화면 시험 카드 꼴로 고침 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK --- .../M01_MasterData_UI_LogicLab_Side.css | 24 +++--- .../M01_MasterData_UI_LogicLab_Side.ts | 77 ++++++++++--------- .../tester/ui_checks/44-4_로직상세_패널.js | 27 ++++--- 3 files changed, 74 insertions(+), 54 deletions(-) diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Side.css b/M01_MasterData/M01_MasterData_UI_LogicLab_Side.css index 711326450..853a55b29 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Side.css +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Side.css @@ -1,22 +1,28 @@ -/* 로직 상세 오른쪽 두 패널 — 흐름도 · 원문 · 접힌 패널은 얇은 띠 */ +/* 로직 상세 오른쪽 두 패널 — 흐름도 · 원문 · 공용 접기 카드(접힌 카드 = 제목 행) */ .m01lab-side { - display: flex; - align-items: stretch; min-width: 0; } +.m01lab-side__card, .m01lab-side__slot { - flex: 0 0 40px; min-width: 0; } -.m01lab-side__slot.is-open { - flex: 1 1 auto; +/* 카드 제목 행이 접기 단추 — 흐름도 패널 자체 접기 단추 · 테두리는 뺌 */ +.m01lab-side .m02-dfp__toggle { + display: none; } -/* 접힌 흐름도 자리 — 띠만(기다림 글 · 변환 알림은 숨김) */ -.m01lab-side__slot:not(.is-open) > :not(.m01lab-flow__panel, .m01lab-src) { - display: none; +.m01lab-side .m02-dfp { + border-left: 0; + background: none; +} + +.m01lab-src { + display: flex; + flex-direction: column; + gap: var(--spacing-8); + min-width: 0; } .m01lab-src__body { diff --git a/M01_MasterData/M01_MasterData_UI_LogicLab_Side.ts b/M01_MasterData/M01_MasterData_UI_LogicLab_Side.ts index 13f8da260..3077d01bb 100644 --- a/M01_MasterData/M01_MasterData_UI_LogicLab_Side.ts +++ b/M01_MasterData/M01_MasterData_UI_LogicLab_Side.ts @@ -1,12 +1,14 @@ /* ============================================================================= * M01_MasterData_UI_LogicLab_Side.ts * 로직 상세 오른쪽 두 패널 — 「흐름도」(다이어그램 · 상세 내용 = M02_DF_Panel) · 「원문」(품셈 본문 절) - * 둘 중 하나만 열림(하나 열면 다른 하나 접힘) · 둘 다 접기 됨 · 접힌 패널 = 얇은 띠(머리 단추 그대로) + * 공용 접기 카드(`ui-collapsible` · 제목 행 누름 · 캐럿) 두 장 — attachCollapsible 토글 위에 하나만 열림 규칙 + * 둘 다 접기 됨 · 접힌 카드 = 제목 행만 * 열린 패널은 계정 취향(`m01-logic-panel`)으로 기억 · 원문은 출처 글로 서버가 찾음(`GET /m01/logic/source`) * ========================================================================== */ import { currentLanguageIndex } from "@ui/ui_template_locale"; -import { createButton, el } from "@ui/ui_template_elements"; +import { attachCollapsible } from "@ui/ui_template_collapsible"; +import { el } from "@ui/ui_template_elements"; import { API_BASE_URL } from "@config/config_frontend"; import { readStateRaw, writeStateRaw } from "../A00_Common/b_page_state"; import type { SplitHandle } from "./M01_MasterData_UI_LogicLab_Flow"; @@ -14,9 +16,8 @@ import "../M02_MasterTemplete/DataFlow/M02_DF_Panel.css"; import "./M01_MasterData_UI_LogicLab_Side.css"; const TEXT = { - Toggle: ["원문", "Source"], - Open: ["원문 펴기", "Open the source panel"], - Close: ["원문 접기", "Collapse the source panel"], + Flow: ["흐름도", "Flow"], + Source: ["원문", "Source"], Loading: ["원문 찾는 중", "Looking up the source"], None: ["원문 연결 없음", "No linked source"], From: ["출처", "Source"], @@ -27,8 +28,8 @@ const TEXT = { const ts = (key: keyof typeof TEXT, v = ""): string => TEXT[key][currentLanguageIndex === 1 ? 1 : 0].replace("{v}", v); -/** 접힌 띠 너비 — M02_DF_Panel 의 STRIP_WIDTH 와 같음(패널 모듈은 늦게 받으므로 따로 둠) */ -const STRIP = 40; +/** 둘 다 접힘 — 제목 행 둘이 들어가는 칸 너비 */ +const FOLDED = 140; export type PanelPick = "flow" | "source" | "none"; @@ -86,21 +87,28 @@ export function buildLogicSide(split: SplitHandle): LogicSide { const flowSlot = el("div", { className: "m01lab-side__slot" }); const body = el("div", { className: "m01lab-src__body" }); const title = el("strong", { className: "m02-dfp__title" }); - const toggle = createButton({ - label: ts("Toggle"), - size: "sm", - variant: "ghost", - onClick: () => pick(now === "source" ? "none" : "source"), - }); - toggle.classList.add("m02-dfp__toggle"); - const head = el("header", { className: "m02-dfp__head", children: [toggle, title] }); - const open = el("div", { className: "m02-dfp__open", children: [head, body] }); - const strip = el("div", { className: "m02-dfp__strip" }); - const source = el("aside", { className: "m02-dfp m01lab-src", children: [open, strip] }); - const sourceSlot = el("div", { className: "m01lab-side__slot", children: [source] }); - split.right.replaceChildren( - el("div", { className: "m01lab-side", children: [flowSlot, sourceSlot] }), + const card = (label: string, inner: HTMLElement): HTMLElement => + el("section", { + className: "m01lab-side__card ui-collapsible ui-sidebar-section ui-sidebar-card", + children: [el("h3", { className: "ui-collapsible__title", text: label }), inner], + }); + const flowCard = card(ts("Flow"), flowSlot); + const sourceCard = card( + ts("Source"), + el("div", { className: "m01lab-src", children: [title, body] }), ); + const side = el("div", { + className: "m01lab-side ui-sidebar-panel", + children: [flowCard, sourceCard], + }); + attachCollapsible(side); + // 공용 토글 뒤 — 연 카드만 남기고 다른 카드는 접음(접었으면 둘 다 닫힘) + side.addEventListener("click", (ev) => { + const at = (ev.target as HTMLElement).closest(".ui-collapsible__title")?.parentElement; + if (at !== flowCard && at !== sourceCard) return; + pick(at.classList.contains("is-collapsed") ? "none" : at === flowCard ? "flow" : "source"); + }); + split.right.replaceChildren(side); let now = readPick(); let flowPx: number | null = null; @@ -108,14 +116,22 @@ export function buildLogicSide(split: SplitHandle): LogicSide { let want = ""; let shown: string | null = null; - /** 칸 너비 — 원문(또는 흐름도가 아직 안 뜸) = 두 칸 비율 · 흐름도 = 패널 너비 + 띠 · 둘 다 접힘 = 띠 둘 */ + /** 카드 안팎 여백(좌우 안쪽 + 테두리) — 흐름도 패널 너비에 더함 */ + const pad = (): number => { + const s = getComputedStyle(flowCard); + return ["paddingLeft", "paddingRight", "borderLeftWidth", "borderRightWidth"].reduce( + (n, k) => n + (parseFloat(s[k as "paddingLeft"]) || 0), + 0, + ); + }; + /** 칸 너비 — 원문(또는 흐름도가 아직 안 뜸) = 두 칸 비율 · 흐름도 = 패널 너비 + 카드 여백 · 둘 다 접힘 = 제목 행 */ const width = (): void => split.setRight( now === "source" || (now === "flow" && flowPx === null) ? null : now === "flow" - ? (flowPx ?? 0) + STRIP - : STRIP * 2, + ? (flowPx ?? 0) + pad() + : FOLDED, ); const load = (): void => { @@ -149,21 +165,12 @@ export function buildLogicSide(split: SplitHandle): LogicSide { }); }; - const fold = (on: boolean): void => { - open.hidden = on; - strip.hidden = !on; - (on ? strip : head).prepend(toggle); - toggle.setAttribute("aria-expanded", String(!on)); - toggle.title = ts(on ? "Open" : "Close"); - }; - const pick = (next: PanelPick): void => { if (next !== now) writeStateRaw("m01-logic-panel", next); now = next; flowFold?.(now !== "flow"); // 칸을 줄이기 전에 — 흐름도 패널이 접기 전 너비를 재어 둠 - flowSlot.classList.toggle("is-open", now === "flow"); - sourceSlot.classList.toggle("is-open", now === "source"); - fold(now !== "source"); + flowCard.classList.toggle("is-collapsed", now !== "flow"); + sourceCard.classList.toggle("is-collapsed", now !== "source"); width(); load(); }; diff --git a/resources/tester/ui_checks/44-4_로직상세_패널.js b/resources/tester/ui_checks/44-4_로직상세_패널.js index 682c0204e..df8d948c0 100644 --- a/resources/tester/ui_checks/44-4_로직상세_패널.js +++ b/resources/tester/ui_checks/44-4_로직상세_패널.js @@ -4,10 +4,11 @@ * 로직 GC000277(건설품셈 토목 1-1-2 유도선 설치 및 해체)을 엶 · 고치지 않음 · 끝에 패널 취향을 처음 값으로 되돌림. * 기대 수치: * order = ["기본정보","시험 계산","단가산출 상세","텍스트 수식"](흐름 로직이면 셋째 · 넷째는 흐름 보기 안) - * flow = {flow:true, source:false, pref:"flow"} · 오른쪽 칸 너비 > 300 - * source = {flow:false, source:true, pref:"source"} · srcHead 에 「1-1-2 유도선」 · srcTable 에 「특별인부」 - * none = {flow:false, source:false, pref:"none"} · 오른쪽 칸 너비 = 80(띠 둘) - * back = {flow:true, source:false, pref:"flow"}(흐름도 띠 단추로 다시 폄) + * 두 패널 = 공용 접기 카드(ui-collapsible · 제목 행 누름) · 흐름도 패널 자체 접기 단추는 안 보임(dfpToggle 0) + * flow = {flow:true, source:false, pref:"flow", caret:["▾","▸"]} · 오른쪽 칸 너비 > 300 + * source = {flow:false, source:true, pref:"source", caret:["▸","▾"]} · srcHead 에 「1-1-2 유도선」 · srcTable 에 「특별인부」 + * none = {flow:false, source:false, pref:"none", caret:["▸","▸"]} · 오른쪽 칸 너비 = 140(제목 행 둘) + * back = {flow:true, source:false, pref:"flow"}(흐름도 제목 행으로 다시 폄) * noLink = 「원문 연결 없음」 + 「출처 · …」(서버가 빈 목록을 줄 때 · fetch 를 잠시 바꿔 봄) * restored = 처음 취향 값 */ @@ -43,17 +44,23 @@ out.order = $$(".m01lab-flow__left .m01lab__box > .m01-logic__section-head h3").map((h) => h.innerText.trim(), ); - const slots = () => $$(".m01lab-side__slot"); + const cards = () => $$(".m01lab-side__card"); + const heads = () => cards().map((c) => $(".ui-collapsible__title", c)); + const shown = (n) => !!n && n.getBoundingClientRect().height > 0; const state = () => ({ flow: - slots()[0].classList.contains("is-open") && - !$(".m02-dfp", slots()[0]).classList.contains("is-folded"), - source: slots()[1].classList.contains("is-open") && !$(".m02-dfp__open", slots()[1]).hidden, + !cards()[0].classList.contains("is-collapsed") && + shown($(".m02-dfp__open", cards()[0])) && + !$(".m02-dfp", cards()[0]).classList.contains("is-folded"), + source: !cards()[1].classList.contains("is-collapsed") && shown($(".m01lab-src", cards()[1])), pref: localStorage.getItem(PREF), + caret: heads().map((h) => getComputedStyle(h, "::after").content.replace(/"/g, "")), width: Math.round($(".m01lab-flow__right").getBoundingClientRect().width), }); - const flowToggle = () => $(".m02-dfp__toggle", slots()[0]); - const srcToggle = () => $(".m02-dfp__toggle", slots()[1]); + const flowToggle = () => heads()[0]; + const srcToggle = () => heads()[1]; + out.titles = heads().map((h) => h.innerText.trim()); + out.dfpToggle = $$(".m01lab-side .m02-dfp__toggle").filter(shown).length; // 처음 = 흐름도 열림으로 맞춤 if (!state().flow) { if (state().source) srcToggle().click();