refactor(778-5 D-3 덧): 안 이은 줄 창 기초 고르기 · SK 만들기 걷고 [단가산출 걸음에서 확인 ▸] 단추로 교체
- Hopyo_Left: 단산 줄 기초 select · makeSk 걷음 → 단추 하나(onSk — 마법사 단가산출 칸 그 블록 펼침 · 화면 가운데로) - Hopyo_WizardSk: SkStep.show(번) 손잡이 추가 · Hopyo_Wizard: openLeft 에 onSk 연결 - Hopyo_Api: 옛 몸(`바탕`) makeSangeun · SangeunPick 걷음(서버 새 몸은 Hopyo_SkApi) - locale: M02_LeftMakeSk · M02_LeftSkNone 걷고 M02_LeftSkGo 추가 - test_721_find_pick: 낡은 단언 `[views.root, addButton]` → 778-4 율 줄 추가 단추 포함 꼴 - test_746_2: 걷힌 기초 후보 필터 단언 → 걷음 단언 · test_729_3: 새 단추 단언 추가 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -307,18 +307,6 @@ export interface SangeunBuilt {
|
||||
위층같음?: { 번: number; 층: string; 주인: string | null; 키: string }[];
|
||||
}
|
||||
|
||||
/** 고른 기초(블록 번 → 로직) · 729-4 잇기 */
|
||||
export type SangeunPick = Record<
|
||||
number,
|
||||
{
|
||||
로직?: string;
|
||||
입력값?: Record<string, unknown>;
|
||||
환산?: { 계수?: 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<SangeunBuilt> =>
|
||||
call(at(scope, `/hopyo/${enc(key)}/sangeun`), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(바탕 ? { 바탕 } : {}),
|
||||
});
|
||||
|
||||
export const listHopyoPicks = async (scope: HopyoScope): Promise<HopyoPickRow[]> =>
|
||||
(await call<{ 줄: HopyoPickRow[] }>(at(scope, "/hopyo-picks"))).줄;
|
||||
|
||||
|
||||
@@ -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<void> => {
|
||||
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({
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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" });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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_서버_응답_칸_이름_그대로():
|
||||
|
||||
@@ -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"],
|
||||
|
||||
Reference in New Issue
Block a user