Merge remote-tracking branch 'origin/dev' into sub_laptop_7
# Conflicts: # M02_MasterTemplete/M02_MasterTemplete_UI_Side.ts
This commit is contained in:
@@ -18,7 +18,6 @@ import { fetchCombo, type ComboLine } from "../M01_MasterData/M01_MasterData_UI_
|
||||
import { openLogicPicker } from "../M01_MasterData/M01_MasterData_UI_Combo_Pick";
|
||||
import { branchCombo, type BranchedCombo } from "./M02_MasterTemplete_Api_Fetch";
|
||||
import { readColumnBase, reasonOf } from "./M02_MasterTemplete_Combo_Api";
|
||||
import "../M01_MasterData/M01_MasterData_UI_Logic_Style.css"; // [로직 더하기] 창(M01 고르기) 겉틀 — M02 에서 열 때도
|
||||
import "./M02_MasterTemplete_Combo.css";
|
||||
|
||||
const TEXT = {
|
||||
|
||||
@@ -95,7 +95,12 @@ export function canEdit(layer: Layer, isAdmin: boolean): boolean {
|
||||
return layer === "project" || layer === "personal" || (layer === "system" && isAdmin);
|
||||
}
|
||||
|
||||
export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
|
||||
/** `onOpened` — 무엇을 열든(좌측 · 카드 [도면 수정] · 다시 읽기) 연 바로 뒤 부름(좌측 고름 표시) */
|
||||
export function createMain(
|
||||
isAdmin: boolean,
|
||||
onSaved?: () => void,
|
||||
onOpened?: () => void,
|
||||
): MainHandle {
|
||||
const title = el("h2", { className: "m02-main__title", text: L("M02_PickTemplate") });
|
||||
const reload = createButton({ label: L("M02_Reload"), variant: "ghost" });
|
||||
const save = createButton({ label: L("M02_Save"), variant: "filled" });
|
||||
@@ -136,7 +141,13 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
|
||||
window.addEventListener("beforeunload", guard);
|
||||
const confirmLeave = async (): Promise<boolean> => {
|
||||
if (!dirty) return true;
|
||||
if (!(await showConfirmDialog(L("M02_DiscardConfirm")))) return false;
|
||||
if (!(await showConfirmDialog(L("M02_DiscardConfirm")))) {
|
||||
// 취소 — 초점을 시트(고른 칸 입력 자리) · 집계표 · 도면으로 돌려 키보드 그대로
|
||||
host
|
||||
.querySelector<HTMLElement>(".ss-input, .ui-sheet, iframe")
|
||||
?.focus({ preventScroll: true });
|
||||
return false;
|
||||
}
|
||||
dirty = false;
|
||||
return true;
|
||||
};
|
||||
@@ -359,6 +370,7 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
|
||||
drop();
|
||||
showNotice([]);
|
||||
sel = next;
|
||||
onOpened?.();
|
||||
bar();
|
||||
if (!next) {
|
||||
title.textContent = L("M02_PickTemplate");
|
||||
@@ -437,6 +449,7 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
|
||||
drop();
|
||||
showNotice([]);
|
||||
sel = null;
|
||||
onOpened?.(); // 좌측 양식 · 열 줄 고름 지움
|
||||
bar();
|
||||
title.textContent = label;
|
||||
host.replaceChildren(node);
|
||||
|
||||
@@ -17,7 +17,11 @@ import "./M02_MasterTemplete_UI_Style.css";
|
||||
export async function renderM02MasterTemplate(root: HTMLElement): Promise<void> {
|
||||
const user = await fetchSessionUser().catch(() => null);
|
||||
const isAdmin = user?.role === "SYSTEM_ADMIN";
|
||||
const main = createMain(isAdmin, () => void side.refresh());
|
||||
const main = createMain(
|
||||
isAdmin,
|
||||
() => void side.refresh(),
|
||||
() => side.paint(),
|
||||
);
|
||||
const side = buildSide({
|
||||
isAdmin,
|
||||
onOpen: (sel) => void main.open(sel),
|
||||
|
||||
@@ -83,8 +83,8 @@ export interface SideOptions {
|
||||
export interface SideHandle {
|
||||
root: HTMLElement;
|
||||
refresh: () => Promise<void>;
|
||||
/** 좌측 고름 표시만 옮김 — 화면은 열지 않음 */
|
||||
select: (kind: Kind, name: string) => void;
|
||||
/** 고름 표시를 지금 열린 것 한 줄로 — 편집 칸이 무엇을 열든(카드 [도면 수정] 등) 부름 */
|
||||
paint: () => void;
|
||||
}
|
||||
|
||||
/** 서버 이름 규칙과 같게 — 화면에서 먼저 막음 */
|
||||
@@ -105,8 +105,6 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
let numbers: Record<string, StructureNumbers> = {};
|
||||
let seq = 0;
|
||||
|
||||
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 ui-sidebar-card is-collapsed",
|
||||
@@ -136,12 +134,7 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
confirmLeave: opt.confirmLeave,
|
||||
show: opt.showView,
|
||||
close: () => opt.onOpen(null),
|
||||
onOpen: () => {
|
||||
picked = null;
|
||||
paintList();
|
||||
paintColumns();
|
||||
paintButtons();
|
||||
},
|
||||
onOpen: () => paint(),
|
||||
});
|
||||
const matsetSection = section(matset.title, matset.body, ...matset.actions);
|
||||
// 펼칠 때마다 새로 받음 — 재료산출 옆 판이 갈라 낸 조합도 바로 보이게
|
||||
@@ -161,9 +154,8 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
|
||||
const root = el("div", { className: "m02-side ui-sidebar-panel", children: [listHost] });
|
||||
|
||||
/** 고름 표시 — `picked`(방금 누름) 이 있으면 그것 · 없으면 지금 열린 것과 비교 */
|
||||
/** 고름 표시 — 편집 칸에 지금 열린 것 하나뿐 */
|
||||
const isPicked = (kind: Kind, name: string): boolean => {
|
||||
if (picked) return picked.kind === kind && picked.name === name;
|
||||
const cur = opt.getOpen();
|
||||
return !!cur && cur.layer === layer && cur.kind === kind && cur.name === name;
|
||||
};
|
||||
@@ -220,23 +212,25 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
for (const [kind, b] of editButtons) b.copy.disabled = b.del.disabled = cur?.종류 !== kind;
|
||||
}
|
||||
|
||||
/** 고름 표시는 여기서만 — 목록 · 열 줄 · 자재 조합 줄을 함께 그려야 두 줄이 동시에 안 남음
|
||||
* (양식이 열려 있으면 자재 조합 고름은 지움 · 자재 조합 상세는 열린 양식이 없음) */
|
||||
function paint(): void {
|
||||
if (opt.getOpen()) matset.clear();
|
||||
paintList();
|
||||
paintColumns();
|
||||
paintButtons();
|
||||
}
|
||||
|
||||
// 여는 것은 편집 칸(`onOpen`) — 편집 칸이 열 때마다 `paint` 를 부름(페이지가 이음)
|
||||
async function select(info: TemplateInfo): Promise<void> {
|
||||
if (!isOpen(info) && !(await opt.confirmLeave())) return;
|
||||
picked = null;
|
||||
matset.clear();
|
||||
opt.onOpen({ layer, projectId: null, kind: info.종류, name: info.이름 });
|
||||
paintList();
|
||||
paintButtons();
|
||||
}
|
||||
|
||||
async function selectColumn(col: StructureColumn, kind: ColumnKind): Promise<void> {
|
||||
if (!isPicked(kind, col.id) && !(await opt.confirmLeave())) return;
|
||||
picked = null;
|
||||
matset.clear();
|
||||
// 제목은 편집 화면이 문서 번호를 앞에 붙임(「SD010101 돌기슭막이 …」)
|
||||
opt.onOpen({ layer, projectId: null, kind, name: col.id, label: columnHead(col) });
|
||||
paintColumns();
|
||||
paintButtons();
|
||||
}
|
||||
|
||||
async function refreshStructure(): Promise<void> {
|
||||
@@ -351,13 +345,5 @@ export function buildSide(opt: SideOptions): SideHandle {
|
||||
}
|
||||
|
||||
void refresh();
|
||||
return {
|
||||
root,
|
||||
refresh,
|
||||
select: (kind, name) => {
|
||||
picked = { kind, name };
|
||||
paintList();
|
||||
paintColumns();
|
||||
},
|
||||
};
|
||||
return { root, refresh, paint };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user