diff --git a/A00_Common/spreadsheet/spreadsheet_links.ts b/A00_Common/spreadsheet/spreadsheet_links.ts index 72dde7a1..0be3ca67 100644 --- a/A00_Common/spreadsheet/spreadsheet_links.ts +++ b/A00_Common/spreadsheet/spreadsheet_links.ts @@ -231,8 +231,29 @@ export function mountLinks( return b; } + /** 옛 키(로직 키 등)로 저장된 연결 — 키가 알약 목록에 없으면 이름 + 단위가 같은 알약으로 이어 + * 연결 키를 새 키로 바꿔 둠(다음 저장 때 새 키로 나감 · 안 맞으면 그대로 두어 늘 보임) */ + function align(): void { + if (opts?.모드 !== "입력") return; + const keys = new Set(items.map((i) => i.키)); + const taken = new Set(); + for (const sheet of ctx.book.시트) + for (const l of sheet.연결 ?? []) if (keys.has(l.키)) taken.add(l.키); + for (const sheet of ctx.book.시트) + for (const l of sheet.연결 ?? []) { + if (keys.has(l.키)) continue; + const hit = items.find( + (i) => !taken.has(i.키) && i.이름 === l.이름 && (i.단위 ?? "") === (l.단위 ?? ""), + ); + if (!hit) continue; + l.키 = hit.키; + taken.add(hit.키); + } + } + function renderBar(): void { if (!opts) return; + align(); const map = found(); const shown: LinkItem[] = []; const seen = new Set(); diff --git a/M02_MasterTemplete/M02_MasterTemplete_Combo.ts b/M02_MasterTemplete/M02_MasterTemplete_Combo.ts index 873ebeb9..1fe94d9f 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Combo.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Combo.ts @@ -95,6 +95,10 @@ export function askBranch(message: string, defaultName: string): Promise + !original ? label : !label || original.endsWith(label) ? original : `${original} · ${label}`; + /** 결과 알림 — 새로 만듦 / 같은 조합 씀 */ export const branchToast = (r: BranchedCombo): void => showToast(fill(r.새로만듦 ? TEXT.made : TEXT.reused, `${r.키} ${r.이름}`), "success"); @@ -236,7 +240,7 @@ export async function buildComboBar(opts: ComboBarOptions): Promise void; + /** 연결이 바뀜(이음 · 풂 · 되돌리기) — 이은 칸을 다시 그림 */ + refresh: () => void; } export interface MaterialPanelOptions { @@ -272,11 +275,12 @@ export function buildMaterialPanel(opts: MaterialPanelOptions): MaterialPanel { if (sig(items) !== sig(saved)) { const apply = createButton({ label: TEXT.apply, variant: "filled", size: "sm" }); apply.addEventListener("click", async () => { - const message = others ? fill(TEXT.askBody, { n: others + 1 }) : TEXT.askAlone; - const name = await askBranch( - message, - `${combo?.이름 ?? ""} · ${opts.label}`.replace(/^ · /, ""), - ); + const message = !key + ? TEXT.askFirst + : others + ? fill(TEXT.askBody, { n: others + 1 }) + : TEXT.askAlone; + const name = await askBranch(message, branchName(combo?.이름 ?? "", opts.label)); if (name === null) return; apply.disabled = true; try { @@ -318,5 +322,6 @@ export function buildMaterialPanel(opts: MaterialPanelOptions): MaterialPanel { items = [...list]; paint(); }, + refresh: paint, }; } diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts b/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts index 93e60594..207d4218 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Main.ts @@ -217,7 +217,10 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle { { readOnly, tabs: false, // 시트 하나 · 탭 줄 없음 - onChange: () => (dirty = !readOnly), + onChange: () => { + dirty = !readOnly; + matPanel?.refresh(); // 알약을 이음 · 풂 — 옆 판 「이은 칸」 바로 갱신 + }, links, }, );