파일을 아직 올리지 않은 새 프로젝트에서 대시보드 -> 파일 입력으로 이동하면 준비 화면(B11)이 확정 지표면을 찾다 실패해 "담당자에게 연락" 장애 안내를 띄웠다. 파일 입력 화면은 3D 지표면을 쓰지 않으므로 준비 자체가 필요 없다. - goToWorkflowStage: 담아 둔 지표면을 실제로 쓰는 B04/B05로 갈 때만 준비 화면 경유, 나머지(B03/B06~B09)는 바로 이동 - 확정 지표면이 없을 때는 장애가 아니라 순서 문제이므로 전용 표식(PRELOAD_NO_SURFACE)을 던지고, 준비 화면은 안내 문구 + [파일 입력 화면으로] 버튼을 보여 준다 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
118 lines
4.5 KiB
TypeScript
118 lines
4.5 KiB
TypeScript
import { CURRENT_PROJECT_ID_KEY, ROUTES, type RoutePath } from "@config/config_frontend";
|
|
import { createButton } from "@ui/ui_template_elements";
|
|
import { createGeneralLayout } from "@ui/ui_template_general_layout";
|
|
import { t } from "@ui/ui_template_locale";
|
|
import { createProgressCircle } from "@ui/ui_template_progress";
|
|
import {
|
|
markProjectPreloaded,
|
|
preloadSurfaceAssets,
|
|
PRELOAD_NO_SURFACE,
|
|
purgeOtherProjects,
|
|
readPreloadTarget,
|
|
} from "../A00_Common/b_asset_cache";
|
|
import { navigateTo } from "../A00_Common/router";
|
|
import "./B11_Status_UI_Style.css";
|
|
|
|
/* =============================================================================
|
|
* 자료 준비 화면 (B11)
|
|
*
|
|
* 대시보드에서 프로젝트를 골라 작업 화면으로 들어갈 때, 먼저 이 화면이 3D 지표면과
|
|
* 등고선을 브라우저에 담아 둔다. 담아 두면 B04·B05가 그것을 그대로 쓰므로 화면이 바로 뜬다.
|
|
* 이미 담겨 있으면 순식간에 지나간다.
|
|
*
|
|
* 자료를 준비하지 못하면(분석 실패·저장 경로 문제) 넘어가지 않고 사유를 알린다.
|
|
* ========================================================================== */
|
|
|
|
/** 준비에 실패한 채 그냥 넘어갔을 때 남기는 표식 — 어떤 확정 구성과도 일치하지 않는다. */
|
|
const PRELOAD_SKIPPED_SIGNATURE = "skipped";
|
|
|
|
export async function renderB11Loading(root: HTMLElement): Promise<void> {
|
|
const projectId = localStorage.getItem(CURRENT_PROJECT_ID_KEY);
|
|
const target = (readPreloadTarget() ?? ROUTES.B03_FILE_INPUT) as RoutePath;
|
|
|
|
const progress = createProgressCircle({ label: t("B11_Loading_Start"), size: 96 });
|
|
const message = document.createElement("p");
|
|
message.className = "b11-loading__message";
|
|
message.textContent = t("B11_Loading_Message");
|
|
|
|
const actions = document.createElement("div");
|
|
actions.className = "b11-loading__actions";
|
|
|
|
const body = document.createElement("div");
|
|
body.className = "b11-loading__body";
|
|
body.append(progress.root, message, actions);
|
|
|
|
const layout = createGeneralLayout({
|
|
pageClass: "b11-status",
|
|
title: t("B11_Loading_Title"),
|
|
subtitle: t("B11_Loading_Subtitle"),
|
|
content: [body],
|
|
});
|
|
root.replaceChildren(layout.root);
|
|
|
|
if (!projectId) {
|
|
showFailure(t("B11_Loading_NoProject"));
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 다른 프로젝트 자료가 남아 있으면 지운다 — 프로젝트끼리 섞이면 안 된다.
|
|
await purgeOtherProjects(projectId);
|
|
const signature = await preloadSurfaceAssets(projectId, (label, ratio) => {
|
|
progress.set(ratio, label);
|
|
});
|
|
// 표식은 담아 둔 구성 그대로 남긴다 — 확정이 바뀌면 다음 진입에서 다시 준비한다.
|
|
markProjectPreloaded(projectId, signature);
|
|
navigateTo(target);
|
|
} catch (error) {
|
|
// 확정 지표면이 아직 없는 것은 고장이 아니라 순서 문제다 — 장애 안내 대신 할 일을 알린다.
|
|
if (error instanceof Error && error.message === PRELOAD_NO_SURFACE) {
|
|
showNoSurface();
|
|
return;
|
|
}
|
|
const detail = error instanceof Error ? ` (${error.message})` : "";
|
|
showFailure(`${t("B11_Loading_Failed")}${detail}`);
|
|
}
|
|
|
|
function showNoSurface(): void {
|
|
progress.root.hidden = true;
|
|
message.textContent = t("B11_Loading_NoSurface");
|
|
actions.replaceChildren(
|
|
createButton({
|
|
label: t("B11_Loading_Btn_FileInput"),
|
|
variant: "filled",
|
|
onClick: () => navigateTo(ROUTES.B03_FILE_INPUT),
|
|
}),
|
|
createButton({
|
|
label: t("B11_Loading_Btn_Dashboard"),
|
|
variant: "ghost",
|
|
onClick: () => navigateTo(ROUTES.B01_ACCOUNT),
|
|
}),
|
|
);
|
|
}
|
|
|
|
function showFailure(text: string): void {
|
|
progress.root.hidden = true;
|
|
message.textContent = text;
|
|
message.classList.add("b11-loading__message--error");
|
|
actions.replaceChildren(
|
|
createButton({
|
|
label: t("B11_Loading_Btn_Continue"),
|
|
variant: "ghost",
|
|
// 준비를 못 했어도 같은 세션에서 다시 붙잡지 않도록 표시해 둔다.
|
|
// 확정 구성을 모르는 상태이므로 전용 표식을 남긴다 — 확정이 정상화되면 표식이
|
|
// 어긋나 준비 화면이 다시 뜬다.
|
|
onClick: () => {
|
|
if (projectId) markProjectPreloaded(projectId, PRELOAD_SKIPPED_SIGNATURE);
|
|
navigateTo(target);
|
|
},
|
|
}),
|
|
createButton({
|
|
label: t("B11_Loading_Btn_Dashboard"),
|
|
variant: "filled",
|
|
onClick: () => navigateTo(ROUTES.B01_ACCOUNT),
|
|
}),
|
|
);
|
|
}
|
|
}
|