5 changed files with 61 additions and 246762 deletions
@@ -11,6 +11,7 @@ import {
showConfirmDialog,
showToast,
} from "@ui/ui_template_elements";
import { attachCollapsible } from "@ui/ui_template_collapsible";
import { t as L } from "@ui/ui_template_locale";
import { openModal } from "@ui/ui_template_modal";
import {
@@ -24,6 +25,8 @@ import {
} from "./M02_MasterTemplete_Api_Fetch";
import { canEdit, type Selection } from "./M02_MasterTemplete_UI_Main";
/** 서버 종류 추가 전까지 `Kind` 에 없음 — 목록 응답에 있을 때만 그림 */
const STRUCTURE = "structure" as Kind;
const KINDS: { kind: Kind; label: () => string }[] = [
{ kind: "table", label: () => L("M02_KindTable") },
{ kind: "drawing", label: () => L("M02_KindDrawing") },
@@ -55,6 +58,8 @@ export interface SideOptions {
export interface SideHandle {
root: HTMLElement;
refresh: () => Promise<void>;
/** 좌측 고름 표시만 옮김 — 화면은 열지 않음 */
select: (kind: Kind, name: string) => void;
}
/** 서버 이름 규칙과 같게 — 화면에서 먼저 막음 */
@@ -70,7 +75,31 @@ export function buildSide(opt: SideOptions): SideHandle {
let items: TemplateInfo[] = [];
let seq = 0;
const listHost = el("div", { className: "m02-side__lists" });
let picked: { kind: Kind; name: string } | null = null;
const section = (title: string, body: HTMLElement, ...more: HTMLElement[]): HTMLElement =>
el("section", {
className: "m02-side__group ui-collapsible ui-sidebar-section",
children: [el("h3", { className: "ui-collapsible__title", text: title }), body, ...more],
});
const bodies = new Map<Kind, HTMLElement>(
[...KINDS.map((k) => k.kind), STRUCTURE].map((k) => [
k,
el("div", { className: "m02-side__items" }),
]),
);
const listHost = el("div", {
className: "m02-side__lists",
children: [
section(L("M02_KindTable"), bodies.get("table")!),
section(
L("M02_KindDrawing"),
bodies.get("drawing")!,
section(L("M02_KindStructure"), bodies.get(STRUCTURE)!),
),
],
});
attachCollapsible(listHost);
const btnNew = createButton({ label: L("M02_New"), variant: "filled" });
const btnCopy = createButton({ label: L("M02_Copy"), variant: "ghost" });
@@ -80,6 +109,7 @@ export function buildSide(opt: SideOptions): SideHandle {
const root = el("div", { className: "m02-side", children: [listHost, editRow] });
const isOpen = (info: TemplateInfo): boolean => {
if (picked) return picked.kind === info.종류 && picked.name === info.이름;
const cur = opt.getOpen();
return !!cur && cur.layer === layer && cur.kind === info.종류 && cur.name === info.이름;
};
@@ -90,28 +120,22 @@ export function buildSide(opt: SideOptions): SideHandle {
};
function paintList(): void {
listHost.replaceChildren(
...KINDS.map(({ kind, label }) => {
const mine = items.filter((i) => i.종류 === kind);
return el("div", {
className: "m02-side__group",
children: [
el("h4", { text: label() }),
...(mine.length
? mine.map((info) => {
const b = el("button", {
className: `m02-side__item${isOpen(info) ? " is-active" : ""}`,
text: info.이름,
attrs: { type: "button", title: info.수정일 },
});
b.addEventListener("click", () => void select(info));
return b;
})
: [el("p", { className: "m02-side__empty", text: L("M02_NoTemplates") })]),
],
});
}),
);
for (const [kind, body] of bodies) {
const mine = items.filter((i) => i.종류 === kind);
body.replaceChildren(
...(mine.length
? mine.map((info) => {
const b = el("button", {
className: `m02-side__item${isOpen(info) ? " is-active" : ""}`,
text: info.이름,
attrs: { type: "button", title: info.수정일 },
});
b.addEventListener("click", () => void select(info));
return b;
})
: [el("p", { className: "m02-side__empty", text: L("M02_NoTemplates") })]),
);
}
}
function paintButtons(): void {
@@ -123,6 +147,7 @@ export function buildSide(opt: SideOptions): SideHandle {
async function select(info: TemplateInfo): Promise<void> {
if (!isOpen(info) && !(await opt.confirmLeave())) return;
picked = null;
opt.onOpen({ layer, projectId: null, kind: info.종류, name: info.이름 });
paintList();
paintButtons();
@@ -218,5 +243,12 @@ export function buildSide(opt: SideOptions): SideHandle {
});
void refresh();
return { root, refresh };
return {
root,
refresh,
select: (kind, name) => {
picked = { kind, name };
paintList();
},
};
}
@@ -12,10 +12,10 @@
gap: var(--spacing-4);
}
.m02-side__group h4 {
margin: 0;
color: var(--color-text-muted);
font-size: var(--text-body-sm);
.m02-side__items {
display: flex;
flex-direction: column;
gap: var(--spacing-4);
}
.m02-side__item {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -8,6 +8,7 @@ export const ui_locales_m2 = {
M02_Title: ["마스터 템플릿", "Master Templates"],
M02_KindTable: ["표 양식", "Table templates"],
M02_KindDrawing: ["도면 양식", "Drawing templates"],
M02_KindStructure: ["구조물 도면", "Structure drawings"],
M02_NoTemplates: ["양식 없음", "None"],
M02_New: ["새로", "New"],
M02_Copy: ["본떠 만들기", "Copy as new"],