feat(M02): 새 구조물 조합 두 단추 — 「새 항목」 → 상세 칸 [새로 만들기] [복사 생성] · 복사 생성 = 탭 + 목록 → 지금 층 · 고른 폴더 · 새 키 · 새 번호

39-5 H4 — 나무 copyIn(붙여넣기 길 · 새 열 하나면 그 열 고름) · folder 손잡이 · ItemPick buildTwoWay(빈 카드도 씀).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
2026-10-04 17:37:46 +09:00
co-authored by Claude Opus 5.5
parent af92f0553e
commit 364d22ff6f
4 changed files with 135 additions and 8 deletions
@@ -43,8 +43,13 @@ import {
import { canEdit, createMain, newItemButton, type Selection } from "./M02_MasterTemplete_UI_Main";
import { buildSide, type AllKind } from "./M02_MasterTemplete_UI_Side";
import { buildAllItems } from "./M02_MasterTemplete_ItemList";
import { buildTwoWay, pickedName } from "./M02_MasterTemplete_ItemPick";
import "./M02_MasterTemplete_UI_Style.css";
const NEW_NOTE = "새 항목이 들어갈 자리 — {value} · 나무에서 폴더를 고르면 그 안";
const NEW_ASK =
"{from} 「{name}」 을(를) 복사해 「{to}」 에 새 항목으로 만듦 — 새 번호 · 원래 이름";
/** 「전체 항목」 화면 제목 앞마디 — 하위 이름 */
const ALL_TITLE = {
structure: "M02_KindStructure",
@@ -130,8 +135,8 @@ export async function renderM02MasterTemplate(root: HTMLElement): Promise<Mounte
{
top: readOnlyBar?.root,
search: tree.search,
// 「새 항목」(30-5) — 제목 줄 오른쪽 끝 · 쓸 수 있는 층만 · 나무 「항목 추가」와 같은 창
...(canEdit(layer, isAdmin) ? { newItem: newItemButton(() => tree.newItem()) } : {}),
// 「새 항목」(30-5) — 제목 줄 오른쪽 끝 · 쓸 수 있는 층만 · 상세 칸에 [새로 만들기] [복사 생성](39-5)
...(canEdit(layer, isAdmin) ? { newItem: newItemButton(() => openNew()) } : {}),
onColumn: (column) => {
readOnlyBar?.setColumn(column);
tree.select(column);
@@ -145,6 +150,26 @@ export async function renderM02MasterTemplate(root: HTMLElement): Promise<Mounte
: {}),
},
);
/** 새 구조물 조합(39-5 · 답 2) — 새로 만들기 = 나무 「항목 추가」 창 · 복사 생성 = 탭 + 목록 →
* 지금 보는 층 · 나무에서 고른 폴더(없으면 맨 위) · 원래 이름(겹치면 「(2)」) · 새 키 · 새 번호 */
const openNew = (): void => {
const where = (): string => tree.folder().join(" / ") || L("M02_TreeTop");
main.showView(
L("M02_TreeNewItem"),
buildTwoWay({
note: NEW_NOTE.replace("{value}", where()),
onNew: () => tree.newItem(),
picker: { user, company, kind: "item" },
ask: (picked) =>
NEW_ASK.replace("{name}", pickedName(picked))
.replace("{from}", picked.from.label)
.replace("{to}", where()),
onCopy: async (picked) => {
if ("row" in picked) await tree.copyIn(picked.from, picked.row.key, tree.folder());
},
}),
);
};
// 첫 화면 · 닫은 뒤(양식 지움 · 자재 조합 상세 닫음) = 구조물집계표 — 빈 화면 없음
const home: Selection = {
layer,