diff --git a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Api.ts b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Api.ts index 1c0d6a27d..f833c9eac 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Api.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Api.ts @@ -307,18 +307,6 @@ export interface SangeunBuilt { 위층같음?: { 번: number; 층: string; 주인: string | null; 키: string }[]; } -/** 고른 기초(블록 번 → 로직) · 729-4 잇기 */ -export type SangeunPick = Record< - number, - { - 로직?: string; - 입력값?: Record; - 환산?: { 계수?: number }; - /** 그 블록 잇기 전부(부를 때마다 다시 셈 · 앞 잇기 안 남음) */ - 잇기?: SangeunLink[]; - } ->; - /** 확인한 줄 — 대상 목록 또는 뺌 까닭 */ export interface BuildLine { 차례: number; @@ -522,17 +510,6 @@ export const leftOf = (error: unknown): HopyoLeft[] | null => { return Array.isArray(got) ? (got as HopyoLeft[]) : null; }; -/** [단가산출 만들기](729-1) — 산근 블록마다 기초 · SK · 고름 대기 · `바탕` = 고른 기초 */ -export const makeSangeun = ( - scope: HopyoScope, - key: string, - 바탕?: SangeunPick, -): Promise => - call(at(scope, `/hopyo/${enc(key)}/sangeun`), { - method: "POST", - body: JSON.stringify(바탕 ? { 바탕 } : {}), - }); - export const listHopyoPicks = async (scope: HopyoScope): Promise => (await call<{ 줄: HopyoPickRow[] }>(at(scope, "/hopyo-picks"))).줄; diff --git a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Left.ts b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Left.ts index b5a8ed811..93ae6bc21 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Left.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Left.ts @@ -5,7 +5,7 @@ * · 고름 = 확인 창 캐시(`Hopyo_Check` draft) 대상 · 뺌 — [저장] · [생성] 몸이 그대로 씀(새 저장 꼴 없음) * [고르기] = 확인 창 고르기 창(후보 · 기초 · 자재 찾기 · 옵션은 서버 `guess`) · [찾기] = 기초 · 노임(LB) · 자재(MT) · * [기계] = M01 기계(EQ) · % 줄 = 밑수 비목 · [우리에 없음] = 엑셀 숫자 그대로(사용자가 고른 것) - * · 단가산출 고름 대기 줄 = 후보 기초 고름 → [SK 만들기](서버 `sangeun` 바탕 · 엑셀 차이 보존) → 그 줄은 SK 참조 + * · 단가산출 줄(참조 `단산`) = [단가산출 걸음에서 확인 ▸](`onSk` — 마법사 단가산출 칸 그 블록 펼침) — 기초 고르기 · SK 만들기 없음(778-5 D-3 · 줄로만) * · 못옮김 남은 SK 를 쓰는 줄(729-4 `단산` · `SK` · `못옮김`) = [못옮김 잇기 (n)] → `Hopyo_Lost` 창 * · 남은 수 = 안 만든 호표만(만든 호표는 서버가 남은 줄 있으면 안 만듦) — 마법사 [끝내기] 막음 · 띠 * 계산 · 판정은 서버 — 화면은 보이기 · 고름만. @@ -22,7 +22,6 @@ import { guessHopyo, leftHopyo, leftOf, - makeSangeun, readHopyoOne, type BuildLine, type HopyoLeft, @@ -31,7 +30,6 @@ import { type HopyoPart, type HopyoScope, type LinkBase, - type SangeunCand, isElem, } from "./M02_MasterTemplete_Hopyo_Api"; import { bodyOf, draftKey, loadDraft, saveDraft, toTarget } from "./M02_MasterTemplete_Hopyo_Check"; @@ -121,7 +119,7 @@ function pickedText(at: LeftScope, no: number, 차례: number): string { /** 남은 줄 창 — `map` 이 없으면 `nos` 를 서버에 물어 채움 · 닫을 때 `onClose(map)` */ export function openLeft( - at: LeftScope & { 파일: string; nos?: number[]; map?: LeftMap }, + at: LeftScope & { 파일: string; nos?: number[]; map?: LeftMap; onSk?: (block: number) => void }, onClose?: (map: LeftMap) => void, ): void { const map: LeftMap = at.map ?? new Map(); @@ -135,7 +133,7 @@ export function openLeft( onClose?.(map); return true; }, - mount: (body) => { + mount: (body, close) => { const head = el("div"); const list = el("div"); body.append(createText(L("M02_LeftHint"), "hint", 14), head, list); @@ -177,38 +175,21 @@ export function openLeft( link(no, line.차례, e.종류 === "인력" ? { 노임: e.코드 } : { 자재: e.코드 }, e.이름), machine: (e) => link(no, line.차례, { 기계: e.코드 }, e.이름), }); - const makeSk = async (no: number, block: number, 로직: string): Promise => { - try { - const got = await makeSangeun(at.scope, at.key, { [block]: { 로직 } }); - const sk = got.만듦.find((x) => x.번 === block); - showToast(sk ? `${sk.키} · ${sk.갈래}` : L("M02_LeftSkNone"), sk ? "success" : "warning"); - } catch (error) { - showToast(why(error), "error"); - } - await again(no); - }; - const actions = (no: number, row: HopyoLeft, line: HopyoLine | undefined): HTMLElement => { const box = el("div", { className: "ui-toolbar" }); - const bases = row.후보.filter((c): c is SangeunCand => !isElem(c)); const block = (line as { 참조?: { 종류?: string; 번?: number } } | undefined)?.참조; - if (bases.length && block?.종류 === "단산" && block.번 !== undefined) { - const pick = createSelectField({ - options: bases.map((c) => ({ - value: c.로직, - text: `${c.이름} [${c.단위}] · ${c.판정}${c.글 && c.글 !== c.판정 ? ` · ${c.글}` : ""}`, - })), - compact: true, - size: 24, - ariaLabel: L("M02_LeftBase"), - }); + if (at.onSk && block?.종류 === "단산" && block.번 !== undefined) { const go = createButton({ - label: L("M02_LeftMakeSk"), + label: L("M02_LeftSkGo"), size: 24, - onClick: () => void makeSk(no, block.번!, pick.select.value), + onClick: () => { + close(); + onClose?.(map); + at.onSk!(block.번!); + }, }); go.dataset.leftSk = String(block.번); - box.append(pick.root, go); + box.append(go); } if (row.못옮김?.length && row.단산 !== undefined && row.SK) { const lost = createButton({ diff --git a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Wizard.ts b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Wizard.ts index a1ce89673..0885832b0 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Wizard.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_Wizard.ts @@ -212,11 +212,13 @@ export function buildHopyoWizard(): HopyoWizard { let nos: number[] = []; let map: LeftMap | null = null; let sk: SkStep | null = null; // 단가산출 칸 — 막힘 글 「확인 안 한 블록 n · 고를 줄 m」 + const onSk = (번: number): void => sk?.show(번); const pick = createButton({ label: L("M02_LeftOpen"), variant: "ghost", size: 28, - onClick: () => openLeft({ ...at, 파일: file.파일, nos, ...(map ? { map } : {}) }, paint), + onClick: () => + openLeft({ ...at, 파일: file.파일, nos, onSk, ...(map ? { map } : {}) }, paint), }); pick.dataset.hopyoLeftOpen = ""; /** 띠 — 남은 줄 있으면 [끝내기] 막음 · 까닭 · 남은 수 */ @@ -280,7 +282,7 @@ export function buildHopyoWizard(): HopyoWizard { } if (leftCount(got).줄) { showToast(L("M02_LeftBlocked"), "warning"); - openLeft({ ...at, 파일: file.파일, nos, map: got }, paint); + openLeft({ ...at, 파일: file.파일, nos, onSk, map: got }, paint); return steps.set("2"); } const loose = [...got.values()].filter( diff --git a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_WizardSk.ts b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_WizardSk.ts index 6c569d8a8..6b44b044a 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Hopyo_WizardSk.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Hopyo_WizardSk.ts @@ -48,6 +48,8 @@ export interface SkStep { root: HTMLElement; /** 아직 안 옮긴 블록 · 고를 줄 — 판정 전 null */ count: () => { 블록: number; 줄: number } | null; + /** 그 블록 펼치고 화면에 보임(안 이은 줄 창 [단가산출 걸음에서 확인]) */ + show: (번: number) => void; } /** ② 단가산출 칸 — `파일` = 엑셀 보기 창 머리 · `onChange` = 판정 · 옮김 뒤(끝내기 글) */ @@ -246,5 +248,10 @@ export function sangeunStep( return { root, count: () => (got ? waiting(load(), got.판정) : null), + show: (번) => { + open.add(번); + draw(); + out.querySelector(`[data-sk-block="${번}"]`)?.scrollIntoView({ block: "center" }); + }, }; } diff --git a/resources/tester/test_721_find_pick.py b/resources/tester/test_721_find_pick.py index d13084ff0..e4a9225bd 100644 --- a/resources/tester/test_721_find_pick.py +++ b/resources/tester/test_721_find_pick.py @@ -26,7 +26,9 @@ def _text(path: Path) -> str: def test_721_1_단추_이름과_자리(): detail = _text(M02 / "M02_MasterTemplete_Sangeun_Detail.ts") - assert "children: [views.root, addButton]" in detail # 750-2 「시험 계산 = 바탕」 안내 걷음 + assert ( + "children: [views.root, addButton, rateButton]" in detail + ) # 750-2 안내 걷음 · 778-4 율 줄 추가 assert "M02_SangeunPickBase" not in detail # 727-2 단추 걷음 locale = _text(ROOT / "ui_template" / "ui_template_locale_m2.ts") assert "M02_SangeunPickBase" not in locale diff --git a/resources/tester/test_729_3_hopyo_left_screen.py b/resources/tester/test_729_3_hopyo_left_screen.py index d78d62a23..a5c73e782 100644 --- a/resources/tester/test_729_3_hopyo_left_screen.py +++ b/resources/tester/test_729_3_hopyo_left_screen.py @@ -106,6 +106,10 @@ def test_마법사_끝내기_막음_단가산출_칸_목록_열(): assert "row.못옮김?.length && row.단산 !== undefined && row.SK" in _text( "M02_MasterTemplete_Hopyo_Left.ts" ) + left = _text( + "M02_MasterTemplete_Hopyo_Left.ts" + ) # 778-5 D-3 — 기초 고르기 · SK 만들기 걷고 걸음 이동 + assert "makeSangeun" not in left and 'L("M02_LeftSkGo")' in left and "at.onSk" in left lib = _text("M02_MasterTemplete_Library_List.ts") assert 'L("M02_LibUnlinked"), (r) => (r.안이은줄' in lib assert "unlinkedBar(doc, edit)" in _text("M02_MasterTemplete_Labor_Grid.ts") diff --git a/resources/tester/test_746_2_hopyo_compare_screen.py b/resources/tester/test_746_2_hopyo_compare_screen.py index b9d45f72e..c9cbb3bdf 100644 --- a/resources/tester/test_746_2_hopyo_compare_screen.py +++ b/resources/tester/test_746_2_hopyo_compare_screen.py @@ -17,9 +17,7 @@ def _src(name: str) -> str: def test_안_이은_줄_창이_요소_후보_단추를_붙임(): left = _src("Left") assert "elemChoices(row.후보.filter(isElem)" in left - assert ( - "row.후보.filter((c): c is SangeunCand => !isElem(c))" in left - ) # 기초 후보 칸에는 요소 후보 안 듦 + assert "SangeunCand" not in left # 778-5 D-3 — 기초 고르기 걷음 def test_서버_응답_칸_이름_그대로(): diff --git a/ui_template/ui_template_locale_m2.ts b/ui_template/ui_template_locale_m2.ts index 06393e1c7..48bc0c242 100644 --- a/ui_template/ui_template_locale_m2.ts +++ b/ui_template/ui_template_locale_m2.ts @@ -307,8 +307,7 @@ export const ui_locales_m2 = { M02_LeftPicked: ["고른 것", "Picked"], M02_LeftPick: ["고름", "Pick"], M02_LeftBase: ["기초", "Base"], - M02_LeftMakeSk: ["SK 만들기", "Make SK"], - M02_LeftSkNone: ["만든 단가산출 없음 — 고름 대기 그대로", "Nothing made — still waiting"], + M02_LeftSkGo: ["단가산출 걸음에서 확인 ▸", "Check in the Sangeun step ▸"], M02_LeftChoose: ["고르기", "Pick"], M02_HopyoKid: ["하위 제{n}호표 {key}(사본 담음)", "Sub sheet {n} {key} (copy inside)"], M02_HopyoKidNew: ["함께 만듦", "made together"],