Merge remote-tracking branch 'origin/sub_laptop_7' into main_laptop_1
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
import { createButton, el, showToast } from "@ui/ui_template_elements";
|
||||
import { attachCollapsible } from "@ui/ui_template_collapsible";
|
||||
import { showLoading } from "@ui/ui_template_loading";
|
||||
import type { SpreadsheetHandle, Workbook } from "../A00_Common/spreadsheet/spreadsheet";
|
||||
import type { StructureDoc, StructureNumbers } from "./M02_MasterTemplete_Api_Fetch";
|
||||
import {
|
||||
@@ -254,10 +255,13 @@ export function createItemCards(opts: ItemCardsOptions): ItemCardsHandle {
|
||||
c.host.replaceChildren();
|
||||
}
|
||||
const source = opts.source();
|
||||
// 0.3초 넘으면 카드마다 칸 안 「불러오는 중」(PLAN 30-6) · 못 읽은 것은 아래 그대로(알림 · 「없음」)
|
||||
const stops = [previewHost, ...sheets.map((c) => c.host)].map((host) => showLoading(host));
|
||||
const [drawing, ...books] = await Promise.allSettled([
|
||||
source.read("structure", col.id),
|
||||
...sheets.map((c) => source.read(c.kind, col.id)),
|
||||
]);
|
||||
stops.forEach((stop) => stop());
|
||||
if (mine !== seq) return;
|
||||
if (drawing.status === "fulfilled") doc = drawing.value.문서 as StructureDoc;
|
||||
// 도번 목록에 있는 열인데 못 읽으면 알림 — 없는 열은 그냥 「도면 없음」
|
||||
|
||||
@@ -158,7 +158,14 @@ export function buildLaborLibrary(opt: LaborLibraryOptions): LaborLibrary {
|
||||
if (editor.isDirty() && !(await showConfirmDialog(tc("BackAsk")))) return;
|
||||
editor.showList();
|
||||
},
|
||||
refresh: () => tree.refresh(),
|
||||
refresh: async () => {
|
||||
const stop = editor.loading(); // 조합 목록 칸에도 「불러오는 중」(나무 칸은 나무 부품이 · PLAN 30-6)
|
||||
try {
|
||||
await tree.refresh();
|
||||
} finally {
|
||||
stop();
|
||||
}
|
||||
},
|
||||
tools: editor.newButton,
|
||||
bind: (fn) => (setDirty = fn),
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ import { openLogicPicker } from "./M02_MasterTemplete_Labor_Pick";
|
||||
import { buildPreview } from "./M02_MasterTemplete_Labor_Preview";
|
||||
import { tc } from "./M02_MasterTemplete_Labor_Text";
|
||||
import { matchText } from "./M02_MasterTemplete_TreePanel_Model";
|
||||
import { loadingError, showLoading } from "@ui/ui_template_loading";
|
||||
import "../M01_MasterData/M01_MasterData_UI_Logic_Style.css";
|
||||
import "../M01_MasterData/M01_MasterData_UI_LogicLab_Style.css";
|
||||
import "@ui/ui_template_general_layout.css";
|
||||
@@ -83,6 +84,8 @@ export interface LaborEditor {
|
||||
current: () => string | null;
|
||||
/** 라이브러리 찾기 칸 글 — 목록을 같은 규칙(`matchText`)으로 거름 */
|
||||
setQuery: (text: string) => void;
|
||||
/** 조합 목록을 새로 받는 동안 칸 안 「불러오는 중」(목록 화면일 때만 · 돌려받은 함수 = 끝) */
|
||||
loading: () => () => void;
|
||||
}
|
||||
|
||||
export function createLaborEditor(opt: LaborEditOptions): LaborEditor {
|
||||
@@ -167,17 +170,26 @@ export function createLaborEditor(opt: LaborEditOptions): LaborEditor {
|
||||
};
|
||||
|
||||
const open = async (key: string): Promise<void> => {
|
||||
const my = ++nav;
|
||||
const stop = showLoading(view); // 0.3초 넘으면 상세 칸 안에 「불러오는 중」(PLAN 30-6)
|
||||
try {
|
||||
const my = ++nav;
|
||||
const one = await fetchCombo(key);
|
||||
await logicsReady;
|
||||
if (my !== nav) return;
|
||||
stop();
|
||||
draw(one.combo, one.version);
|
||||
} catch (error) {
|
||||
showToast(error instanceof Error ? error.message : tc("Load_Failed"), "error");
|
||||
if (my !== nav) return;
|
||||
stop();
|
||||
view.replaceChildren(loadingError(reason(error), () => void open(key)));
|
||||
} finally {
|
||||
stop();
|
||||
}
|
||||
};
|
||||
|
||||
/** 조합 목록을 새로 받는 동안 — 목록 화면일 때만 칸 안 표시(돌려받은 함수 = 끝) */
|
||||
const loading = (): (() => void) => (current ? () => {} : showLoading(view));
|
||||
|
||||
const startNew = (path: string[]): void => draw(blankCombo(path), "");
|
||||
|
||||
/* --- 상세 --- */
|
||||
@@ -390,5 +402,6 @@ export function createLaborEditor(opt: LaborEditOptions): LaborEditor {
|
||||
isDirty: dirty,
|
||||
current: () => current?.combo.키 ?? null,
|
||||
setQuery,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
import "./M02_MasterTemplete_TreePanel.css";
|
||||
import { createInputField, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
||||
import { loadingError, showLoading } from "@ui/ui_template_loading";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import {
|
||||
createTreeRow,
|
||||
@@ -393,6 +394,7 @@ export function createTreePanel(opt: TreePanelOptions): TreePanelHandle {
|
||||
|
||||
async function refresh(): Promise<void> {
|
||||
const mine = ++seq;
|
||||
const stop = showLoading(body); // 0.3초 넘으면 나무 칸 안에 「불러오는 중」(PLAN 30-6)
|
||||
try {
|
||||
const got = await api.fetch(opt.layer, owner);
|
||||
if (mine !== seq) return;
|
||||
@@ -400,8 +402,11 @@ export function createTreePanel(opt: TreePanelOptions): TreePanelHandle {
|
||||
} catch (error) {
|
||||
if (mine !== seq) return;
|
||||
view = null;
|
||||
body.replaceChildren(hint(L("M02_PickerLoadFailed").replace("{value}", why(error))));
|
||||
stop();
|
||||
body.replaceChildren(loadingError(why(error), () => void refresh()));
|
||||
return;
|
||||
} finally {
|
||||
stop(); // 늦게 온 옛 요청의 표시도 걷음
|
||||
}
|
||||
paint();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import { setLeaveGuard } from "../A00_Common/router";
|
||||
import { createButton, el, showConfirmDialog, showToast } from "@ui/ui_template_elements";
|
||||
import { loadingError, showLoading } from "@ui/ui_template_loading";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import {
|
||||
readFilled,
|
||||
@@ -463,6 +464,7 @@ export function createMain(
|
||||
return empty("");
|
||||
}
|
||||
title.textContent = isCombo(next) ? L("M02_KindTable") : (next.label ?? next.name); // 26-7a
|
||||
const stop = showLoading(host); // 0.3초 넘으면 상세 칸 안에 「불러오는 중」(PLAN 30-6)
|
||||
try {
|
||||
const got = await readTemplate(next.layer, next.kind, next.name, next.projectId);
|
||||
if (mine !== seq) return;
|
||||
@@ -481,12 +483,15 @@ export function createMain(
|
||||
const field = NUMBER_FIELD[next.kind];
|
||||
const number = field && (got.문서 as Record<string, unknown> | null)?.[field];
|
||||
if (number) title.textContent = `${String(number)} ${next.label ?? next.name}`;
|
||||
stop();
|
||||
await mount(shown, next);
|
||||
} catch (error) {
|
||||
if (mine !== seq) return;
|
||||
empty("");
|
||||
stop();
|
||||
const why = error instanceof Error ? error.message : "";
|
||||
showToast(L("M02_LoadFailed").replace("{value}", why), "error");
|
||||
host.replaceChildren(loadingError(why, () => void open(next))); // 그 자리에 까닭 + 다시 불러오기
|
||||
} finally {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user