feat(B03,B05,B06): 초기 계산 끝까지 업로드 잠금 + 자료 없으면 대시보드로 (결함 3·6 화면측)
업로드 잠금(결함 3) - 종전에는 전처리(B04)만 끝나면 버튼이 풀려, 노선·횡단이 도는 동안 자료를 또 올릴 수 있었다. isInitialPipelineRunning()/pollInitialPipeline()을 두어 **횡단 단계가 열릴 때까지**(3단계가 NOT_STARTED를 벗어날 때까지) 잠근다. - relockWhileInitialPipelineRuns(): 새로고침·재진입해도 계산이 도는 중이면 다시 잠그고 스피너를 붙인다. 잠금이 화면 상태로만 있으면 새로고침 한 번에 풀렸다. - 보관함 연결 경로도 같은 대기 흐름을 탄다. 자료 없으면 대시보드(결함 6) - b_missing_data_guard 신설 — 근거 자료가 없으면 한 줄 안내 후 B01로 보낸다. 새 자료가 올라오면 서버가 옛 산출물을 지우므로, 열어 둔 뒷단계 화면은 빈 화면이 아니라 대시보드로 나가야 한다(2026-08-08 사용자 지시). - B05: 확정 지표면이 없으면 이동. B06: 노선 또는 종단면이 없으면 이동. 검증: 자료가 없는 신규 프로젝트로 B05 진입 → 안내 후 #/b01-account 로 이동함을 헤드리스 크롬으로 확인. typecheck·prettier 통과, 정적 번들 재빌드. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,8 @@ import {
|
||||
import { restoreB03ProjectState } from "./B03_FileInput_State";
|
||||
import {
|
||||
confirmReplaceUpload,
|
||||
pollWF1Analysis,
|
||||
isInitialPipelineRunning,
|
||||
pollInitialPipeline,
|
||||
renderUploadResults,
|
||||
uploadOneFile,
|
||||
} from "./B03_FileInput_UI_Upload";
|
||||
@@ -466,7 +467,7 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
|
||||
|
||||
/** 분석 대기 — 자동 확정이 보류되면 그 사유를 화면과 알림으로 남긴다. */
|
||||
const pollAnalysis = (projectId: string): Promise<boolean> =>
|
||||
pollWF1Analysis(projectId, (message) => {
|
||||
pollInitialPipeline(projectId, (message) => {
|
||||
pageError.textContent = message;
|
||||
showToast(message, "warning");
|
||||
});
|
||||
@@ -508,6 +509,29 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 새로고침·재진입해도 초기 자동 계산이 도는 중이면 업로드 버튼을 다시 잠근다.
|
||||
* 잠금이 화면 상태로만 남아 있으면 새로고침 한 번으로 풀려 자료를 겹쳐 올릴 수 있다.
|
||||
*/
|
||||
async function relockWhileInitialPipelineRuns(): Promise<void> {
|
||||
if (!activeProjectId || isUploading) return;
|
||||
try {
|
||||
const state = await fetchWorkflowState(activeProjectId);
|
||||
if (!isInitialPipelineRunning(state)) return;
|
||||
} catch {
|
||||
return; // 상태를 못 읽으면 잠그지 않는다 — 서버가 막아 준다.
|
||||
}
|
||||
setUploading(true);
|
||||
showToast(L("B03_File_Analysis_InProgress"), "info");
|
||||
try {
|
||||
const done = await pollAnalysis(activeProjectId);
|
||||
if (done) showToast(L("B03_File_Upload_Success"), "success");
|
||||
} finally {
|
||||
setUploading(false);
|
||||
void applyUploadOverview();
|
||||
}
|
||||
}
|
||||
|
||||
async function startChunkedUpload(targetStates = selectedStates()): Promise<void> {
|
||||
if (isUploading) return;
|
||||
// 보관함에서 불러온 자료가 지정돼 있으면 그것을 옮기는 것이 이 버튼의 동작이다.
|
||||
@@ -670,6 +694,7 @@ export async function renderB03FileInput(root: HTMLElement): Promise<void> {
|
||||
root.replaceChildren(layout.root);
|
||||
|
||||
for (const slot of slots.keys()) renderSlot(slot);
|
||||
void relockWhileInitialPipelineRuns();
|
||||
void registerB03ServiceWorker();
|
||||
void applyUploadOverview();
|
||||
void detectPausedUploads();
|
||||
|
||||
Reference in New Issue
Block a user