fix(M02): 옛 알약 연결 이름+단위로 맞춤 · 옆 판 이은 칸 즉시 갱신 · 새 조합 이름 겹침 · 첫 자재 조합 모달 글
- 알약 막대: 키가 목록에 없는 옛 연결(로직 키)을 이름 + 단위가 같은 알약으로 이어 새 키로 바꿈 — 따로 붙던 「연결」 알약 제거 - 재료산출 옆 판: 알약을 이음 · 풂 즉시 「이은 칸」 갱신 - 새 조합 이름: 원래 이름이 구조물 이름으로 끝나면 덧붙이지 않음(일위대가 · 자재) - 자재 조합이 없는 열의 첫 생성 모달 글: 「이 열에 새 자재 조합을 만듦」 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Kyw9qnkJ94pC1A4PfpDtA
This commit is contained in:
@@ -231,8 +231,29 @@ export function mountLinks(
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 옛 키(로직 키 등)로 저장된 연결 — 키가 알약 목록에 없으면 이름 + 단위가 같은 알약으로 이어
|
||||||
|
* 연결 키를 새 키로 바꿔 둠(다음 저장 때 새 키로 나감 · 안 맞으면 그대로 두어 늘 보임) */
|
||||||
|
function align(): void {
|
||||||
|
if (opts?.모드 !== "입력") return;
|
||||||
|
const keys = new Set(items.map((i) => i.키));
|
||||||
|
const taken = new Set<string>();
|
||||||
|
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 {
|
function renderBar(): void {
|
||||||
if (!opts) return;
|
if (!opts) return;
|
||||||
|
align();
|
||||||
const map = found();
|
const map = found();
|
||||||
const shown: LinkItem[] = [];
|
const shown: LinkItem[] = [];
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
|
|||||||
@@ -95,6 +95,10 @@ export function askBranch(message: string, defaultName: string): Promise<string
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 새 조합 이름 자동 — 원래 이름 · 구조물 이름(원래 이름이 이미 구조물 이름으로 끝나면 덧붙이지 않음) */
|
||||||
|
export const branchName = (original: string, label: string): string =>
|
||||||
|
!original ? label : !label || original.endsWith(label) ? original : `${original} · ${label}`;
|
||||||
|
|
||||||
/** 결과 알림 — 새로 만듦 / 같은 조합 씀 */
|
/** 결과 알림 — 새로 만듦 / 같은 조합 씀 */
|
||||||
export const branchToast = (r: BranchedCombo): void =>
|
export const branchToast = (r: BranchedCombo): void =>
|
||||||
showToast(fill(r.새로만듦 ? TEXT.made : TEXT.reused, `${r.키} ${r.이름}`), "success");
|
showToast(fill(r.새로만듦 ? TEXT.made : TEXT.reused, `${r.키} ${r.이름}`), "success");
|
||||||
@@ -236,7 +240,7 @@ export async function buildComboBar(opts: ComboBarOptions): Promise<HTMLElement
|
|||||||
return showToast(TEXT.unchanged, "info");
|
return showToast(TEXT.unchanged, "info");
|
||||||
}
|
}
|
||||||
const message = others ? fill(TEXT.askBody, others + 1) : TEXT.askAlone;
|
const message = others ? fill(TEXT.askBody, others + 1) : TEXT.askAlone;
|
||||||
const name = await askBranch(message, `${comboName} · ${opts.label}`);
|
const name = await askBranch(message, branchName(comboName, opts.label));
|
||||||
if (name === null) return;
|
if (name === null) return;
|
||||||
apply.disabled = true;
|
apply.disabled = true;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
type MaterialCombo,
|
type MaterialCombo,
|
||||||
type MaterialItem,
|
type MaterialItem,
|
||||||
} from "./M02_MasterTemplete_Api_Fetch";
|
} from "./M02_MasterTemplete_Api_Fetch";
|
||||||
import { askBranch, branchToast } from "./M02_MasterTemplete_Combo";
|
import { askBranch, branchName, branchToast } from "./M02_MasterTemplete_Combo";
|
||||||
import { readColumnBase, reasonOf } from "./M02_MasterTemplete_Combo_Api";
|
import { readColumnBase, reasonOf } from "./M02_MasterTemplete_Combo_Api";
|
||||||
|
|
||||||
const TEXT = {
|
const TEXT = {
|
||||||
@@ -45,6 +45,7 @@ const TEXT = {
|
|||||||
loadFailed: "자재 조합을 못 읽음 — {value}",
|
loadFailed: "자재 조합을 못 읽음 — {value}",
|
||||||
askBody:
|
askBody:
|
||||||
"이 자재 조합은 열 {n} 개와 모든 프로젝트가 같이 씀 — 고친 내용으로 새 자재 조합을 만들고 이 열만 새 조합을 가리킴 · 같은 내용이면 있는 조합을 씀 · 원래 조합은 그대로",
|
"이 자재 조합은 열 {n} 개와 모든 프로젝트가 같이 씀 — 고친 내용으로 새 자재 조합을 만들고 이 열만 새 조합을 가리킴 · 같은 내용이면 있는 조합을 씀 · 원래 조합은 그대로",
|
||||||
|
askFirst: "이 열에 새 자재 조합을 만듦 — 담은 자재 목록으로 새 조합을 만들고 이 열이 가리킴",
|
||||||
askAlone:
|
askAlone:
|
||||||
"이 자재 조합은 모든 프로젝트가 같이 씀 — 고친 내용으로 새 자재 조합을 만들고 이 열만 새 조합을 가리킴 · 같은 내용이면 있는 조합을 씀",
|
"이 자재 조합은 모든 프로젝트가 같이 씀 — 고친 내용으로 새 자재 조합을 만들고 이 열만 새 조합을 가리킴 · 같은 내용이면 있는 조합을 씀",
|
||||||
failed: "자재 조합을 못 고침 — {value}",
|
failed: "자재 조합을 못 고침 — {value}",
|
||||||
@@ -96,6 +97,8 @@ export interface MaterialPanel {
|
|||||||
root: HTMLElement;
|
root: HTMLElement;
|
||||||
/** 알약 막대에서 목록이 바뀜 — 표만 다시 그림(알약은 이미 맞음) */
|
/** 알약 막대에서 목록이 바뀜 — 표만 다시 그림(알약은 이미 맞음) */
|
||||||
setItems: (items: MaterialItem[]) => void;
|
setItems: (items: MaterialItem[]) => void;
|
||||||
|
/** 연결이 바뀜(이음 · 풂 · 되돌리기) — 이은 칸을 다시 그림 */
|
||||||
|
refresh: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MaterialPanelOptions {
|
export interface MaterialPanelOptions {
|
||||||
@@ -272,11 +275,12 @@ export function buildMaterialPanel(opts: MaterialPanelOptions): MaterialPanel {
|
|||||||
if (sig(items) !== sig(saved)) {
|
if (sig(items) !== sig(saved)) {
|
||||||
const apply = createButton({ label: TEXT.apply, variant: "filled", size: "sm" });
|
const apply = createButton({ label: TEXT.apply, variant: "filled", size: "sm" });
|
||||||
apply.addEventListener("click", async () => {
|
apply.addEventListener("click", async () => {
|
||||||
const message = others ? fill(TEXT.askBody, { n: others + 1 }) : TEXT.askAlone;
|
const message = !key
|
||||||
const name = await askBranch(
|
? TEXT.askFirst
|
||||||
message,
|
: others
|
||||||
`${combo?.이름 ?? ""} · ${opts.label}`.replace(/^ · /, ""),
|
? fill(TEXT.askBody, { n: others + 1 })
|
||||||
);
|
: TEXT.askAlone;
|
||||||
|
const name = await askBranch(message, branchName(combo?.이름 ?? "", opts.label));
|
||||||
if (name === null) return;
|
if (name === null) return;
|
||||||
apply.disabled = true;
|
apply.disabled = true;
|
||||||
try {
|
try {
|
||||||
@@ -318,5 +322,6 @@ export function buildMaterialPanel(opts: MaterialPanelOptions): MaterialPanel {
|
|||||||
items = [...list];
|
items = [...list];
|
||||||
paint();
|
paint();
|
||||||
},
|
},
|
||||||
|
refresh: paint,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,10 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
|
|||||||
{
|
{
|
||||||
readOnly,
|
readOnly,
|
||||||
tabs: false, // 시트 하나 · 탭 줄 없음
|
tabs: false, // 시트 하나 · 탭 줄 없음
|
||||||
onChange: () => (dirty = !readOnly),
|
onChange: () => {
|
||||||
|
dirty = !readOnly;
|
||||||
|
matPanel?.refresh(); // 알약을 이음 · 풂 — 옆 판 「이은 칸」 바로 갱신
|
||||||
|
},
|
||||||
links,
|
links,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user