- 순서 칸 = 단추 묶음 두 줄(공용 ui-btn-group 간격) · 카드 갈래는 아래 줄만 - 단가승격 줄 [옵션] = 승격 문서 넣을 값 모달 · [저장] = 서고 저장 길 · 머리 한 줄 알림(쓰는 모든 구조물에 따라감) - 일위조합 줄 [수정] = 사전조합 상세 모달(서고 모드 표 · 옵션 · 수량 · 순서 · 삭제 · 추가) · [저장] = 서고 원본 · 취소 = 버림 물음 - 자기 층 서고만 고침(위 층 = 읽기만) · 닫으면 구조물 일위대가 다시 셈 - 확인 시나리오 resources/tester/ui_checks/51-14_순서칸_2행_옵션수정.js Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
135 lines
4.8 KiB
TypeScript
135 lines
4.8 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Labor_RefEdit.ts
|
|
* 일위대가 참조 줄 모달(51-14) — 서고 원본(50-3)을 그 자리에서 고침 · [저장] = 서고 저장 길(`saveTemplate`) ·
|
|
* 그 문서를 쓰는 모든 구조물에 따라감(머리 한 줄 알림) · 그 층을 못 고치면 읽기만.
|
|
* · 단가승격 [옵션] = 승격 문서 로직 한 줄의 넣을 값 모달(`Labor_Input`)
|
|
* · 일위조합 [수정] = 사전조합 상세(서고 모드 표 · 안 줄 [옵션] · 수량 · 위로 · 아래로 · 삭제 · 추가)
|
|
* 닫으면(저장 · 취소 모두) `closed` — 부르는 쪽이 구조물 일위대가 표를 다시 셈.
|
|
* ========================================================================== */
|
|
|
|
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
|
import { openModal } from "@ui/ui_template_modal";
|
|
import { readTemplate, saveTemplate, type Layer } from "./M02_MasterTemplete_Api_Fetch";
|
|
import { fetchLogicInputs, type LaborRow } from "./M02_MasterTemplete_Labor_Api";
|
|
import type { LaborRef } from "./M02_MasterTemplete_Labor_Calc";
|
|
import { openLaborInput } from "./M02_MasterTemplete_Labor_Input";
|
|
import { tc } from "./M02_MasterTemplete_Labor_Text";
|
|
import { keepKnown } from "./M02_Labor_Values_Model";
|
|
|
|
export interface RefEditOptions {
|
|
ref: LaborRef;
|
|
/** 「SP-000001 메쌓기」 */
|
|
title: string;
|
|
readOnly: boolean;
|
|
closed: () => void;
|
|
}
|
|
|
|
const fail = (error: unknown, key: "Load_Failed" | "Lib_SaveFailed"): void =>
|
|
showToast(error instanceof Error ? error.message : tc(key), "error");
|
|
|
|
export async function openRefEdit(opt: RefEditOptions): Promise<void> {
|
|
const kind = opt.ref.키.startsWith("SP-") ? "promote" : "precombo";
|
|
const layer = opt.ref.층 as Layer;
|
|
let doc: { 담은로직?: LaborRow[] };
|
|
let 판: string;
|
|
try {
|
|
const got = await readTemplate(layer, kind, opt.ref.키, null);
|
|
doc = got.문서 as typeof doc;
|
|
판 = got.판 ?? "";
|
|
} catch (error) {
|
|
return fail(error, "Load_Failed");
|
|
}
|
|
const save = (body: unknown): Promise<unknown> =>
|
|
saveTemplate(layer, kind, opt.ref.키, null, 판, body).then(() =>
|
|
showToast(tc("Saved"), "success"),
|
|
);
|
|
const notice = opt.readOnly ? `${tc("Ref_Shared")} · ${tc("Ref_ReadOnly")}` : tc("Ref_Shared");
|
|
|
|
if (kind === "promote") {
|
|
const row = doc.담은로직?.[0];
|
|
if (!row) return fail(null, "Load_Failed");
|
|
const logic = row.로직
|
|
? ((await fetchLogicInputs([row.로직]).catch(() => null))?.로직[0] ?? null)
|
|
: null;
|
|
return openLaborInput({
|
|
title: opt.title,
|
|
logic,
|
|
values: row.입력값,
|
|
memo: row.메모,
|
|
readOnly: opt.readOnly,
|
|
notice,
|
|
okLabel: tc("Save"),
|
|
done: (next) => {
|
|
row.입력값 = logic ? keepKnown(logic.입력, next.입력값).kept : next.입력값;
|
|
row.메모 = next.메모;
|
|
void save(doc)
|
|
.catch((error) => fail(error, "Lib_SaveFailed"))
|
|
.finally(opt.closed);
|
|
},
|
|
});
|
|
}
|
|
|
|
// 사전조합 — 상세와 같은 부품(서로 부르므로 늦게 받음)
|
|
const { mountLaborDetail } = await import("./M02_MasterTemplete_Labor_Detail");
|
|
let dirty = false;
|
|
let handle: ReturnType<typeof mountLaborDetail> | null = null;
|
|
const finish = (): void => {
|
|
handle?.destroy();
|
|
opt.closed();
|
|
};
|
|
openModal({
|
|
title: opt.title,
|
|
closeLabel: tc("In_Close"),
|
|
dialogClass: "m02-modal m02-labref",
|
|
beforeClose: async () => {
|
|
if (dirty && !(await showConfirmDialog(tc("Ref_Discard")))) return false;
|
|
finish();
|
|
return true;
|
|
},
|
|
mount: (body, close) => {
|
|
const host = el("div", { attrs: { "data-labor-ref": opt.ref.키 } });
|
|
handle = mountLaborDetail(host, doc, {
|
|
layer,
|
|
column: opt.ref.키,
|
|
readOnly: opt.readOnly,
|
|
onChanged: (d) => (dirty = d && !opt.readOnly),
|
|
goArea: null,
|
|
mode: "precombo",
|
|
});
|
|
const cancel = createButton({
|
|
label: tc(opt.readOnly ? "In_Close" : "In_Cancel"),
|
|
variant: "ghost",
|
|
onClick: async () => {
|
|
if (dirty && !(await showConfirmDialog(tc("Ref_Discard")))) return;
|
|
close();
|
|
finish();
|
|
},
|
|
});
|
|
const ok = createButton({
|
|
label: tc("Save"),
|
|
variant: "filled",
|
|
onClick: () =>
|
|
void save(handle?.getDoc()).then(
|
|
() => {
|
|
close();
|
|
finish();
|
|
},
|
|
(error) => fail(error, "Lib_SaveFailed"),
|
|
),
|
|
});
|
|
body.append(
|
|
el("p", {
|
|
className: "m02-labin__muted",
|
|
text: notice,
|
|
attrs: { "data-labor-notice": "" },
|
|
}),
|
|
host,
|
|
el("div", {
|
|
className: "m02-labin__foot",
|
|
children: opt.readOnly ? [cancel] : [cancel, ok],
|
|
}),
|
|
);
|
|
},
|
|
});
|
|
}
|