fix(369-4 B05 배수유역): 판 홀로 서기 — 되돌리기 이음은 _Panel_Types 약속으로

- 배수유역 Live · Panel 이 종단 _Profile_History 를 직접 가져오던 것 걷음(24-2e)
- 새 약속 onPipesDrafted(관 초안 = 사진첩 한 걸음) · isReplaying(되쓰는 중) — 판을 끼우는 SideTool 이 넘김
- 되돌리기 동작 그대로 · test_349_drainage_live_flow 도우미를 새 꼴로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
2026-10-17 17:56:49 +09:00
co-authored by Claude Opus 5.5
parent c922923cec
commit 3349b53a54
5 changed files with 20 additions and 12 deletions
+1 -4
View File
@@ -42,7 +42,6 @@ import {
} from "./logic/B05_Profile_Drainage_Live";
import type { DetailRunner } from "./B05_Profile_UI_Drainage_Run";
import { createDrainageSuggest, type DrainageSuggest } from "./B05_Profile_UI_Drainage_Suggest";
import { pageHistory } from "./B05_Profile_UI_Profile_History";
const MODE_KEY = "drainage-mode";
@@ -53,7 +52,7 @@ export interface DrainageLiveDeps {
basinList: HTMLElement;
pipeRequest: () => DetailPipeInput[];
runner: DetailRunner;
/** [적용] · [자동 제안] 답이 화면에 오른 뒤 — 세션 초안에 담음. */
/** [적용] · [자동 제안] 답이 화면에 오른 뒤 — 세션 초안에 담고 사진첩 한 걸음(패널이 콜백으로 이음). */
rememberPipes: () => void;
/** 저장 배수유역 다시 받기(열 때와 같은 길 · 조용히) — 답을 화면에 올렸으면 true. */
loadSaved: () => Promise<boolean>;
@@ -117,7 +116,6 @@ export function createDrainageLive(deps: DrainageLiveDeps): DrainageLive {
.then((ok) => {
if (!ok) return;
deps.rememberPipes();
pageHistory()?.record();
});
};
const suggest = createDrainageSuggest(deps.pipeRequest, (points) =>
@@ -202,7 +200,6 @@ export function createDrainageLive(deps: DrainageLiveDeps): DrainageLive {
if (applied) stale = false;
if (applied && proposal) {
deps.rememberPipes();
pageHistory()?.record();
}
paint();
});
+4 -4
View File
@@ -34,7 +34,6 @@ import { snapStructureStation } from "../common_util/common_util_structure_stati
import { createFacilityStore } from "./B05_Profile_UI_Drainage_Facility";
import { mergeFacilityOptions } from "./logic/B05_Profile_UI_Drainage_Facility_Merge";
import { readPendingPipes, writePendingPipes } from "./B05_Profile_Api_Pipes_Draft";
import { pageReplaying } from "./B05_Profile_UI_Profile_History";
import { buildPipeReports } from "./B05_Profile_UI_Drainage_Report";
import { fillFordHeights, fordWaitsOf, waitsFordHeight } from "./B05_Profile_UI_Drainage_Ford_Fill";
import { createDrainageChrome } from "./B05_Profile_UI_Drainage_Chrome";
@@ -427,7 +426,7 @@ export function createDrainagePanel(callbacks: DrainagePanelCallbacks = {}): Dra
basinList,
pipeRequest,
runner,
rememberPipes,
rememberPipes: () => (rememberPipes(), callbacks.onPipesDrafted?.()), // + 사진첩 한 걸음(369-4)
loadSaved: () => run(loadSaved, true), // 초안 버림 = 저장분 조용히(349-0i)
});
analyzeButton.addEventListener("click", () => void analyze());
@@ -593,8 +592,9 @@ export function createDrainagePanel(callbacks: DrainagePanelCallbacks = {}): Dra
const next = reconcilePipes(pipeEditor.pipes(), chainages);
if (!next) return; // 같은 목록 — 되돌아온 것이므로 여기서 끊는다
// 되돌리기 = 그 걸음 초안의 속성 · id · 초안 없는 걸음은 저장분(369) · 구조물 폼은 속성 데려감
const pending = pageReplaying() ? readPendingPipes(projectId as string) : null;
if (pageReplaying() && !pending) return void run(loadSaved, true);
const replaying = callbacks.isReplaying?.() ?? false; // 종단쪽 약속(369-4)
const pending = replaying ? readPendingPipes(projectId as string) : null;
if (replaying && !pending) return void run(loadSaved, true);
const draft = adoptDraftPipes(pending, next);
const after = next.map((pipe) => pipe.chainage_m);
if (draft) facilityStore.replaceFromResponse(draft);
@@ -90,4 +90,9 @@ export interface DrainagePanelCallbacks {
/** 배수유역도 우클릭 빈 자리 메뉴 — 사이드 「구조물 배치」와 같은 구조물군 → 종류
* 2단 항목(2026-08-18 일원화). 선택 = 폼 자동 지정(addAt 경유). */
structureMenuItems?: (chainageM: number) => MapContextMenuItem[];
/** [자동 제안] · 제안 [적용] 관 초안이 화면에 오른 뒤 — 되돌리기 사진첩 한 걸음(346-4 · 369-4).
* 판을 세우는 종단쪽이 넘김 — 판은 종단 패널을 안 가져옴(24-2e). */
onPipesDrafted?: () => void;
/** 되돌리기 · 다시하기가 세션을 되쓰는 중인가 — 그때 관 목록은 그 걸음 초안(없으면 저장분)으로. */
isReplaying?: () => boolean;
}
@@ -6,6 +6,12 @@
import type { DesignSideFactory } from "../A00_Common/design/design_profile";
import { createDrainageSide } from "./B05_Profile_UI_Drainage_Side";
import { pageHistory, pageReplaying } from "./B05_Profile_UI_Profile_History";
/** 오른쪽 판 — 두 보기가 같은 판을 쓴다. */
export const drainageSide: DesignSideFactory = (host) => createDrainageSide(host);
/** 오른쪽 판 — 두 보기가 같은 판을 쓴다. 되돌리기 이음은 판 대신 여기서(369-4 · 판은 종단 패널을 안 가져옴). */
export const drainageSide: DesignSideFactory = (host) =>
createDrainageSide({
...host,
onPipesDrafted: () => pageHistory()?.record(),
isReplaying: pageReplaying,
});
@@ -105,7 +105,6 @@ const stubs = {
currentLanguageIndex: 0,
ui_locales: new Proxy({}, { get: (_target, key) => [key, key] }),
},
"./B05_Profile_UI_Profile_History": { pageHistory: () => ({ record: () => (records += 1) }) },
"../A00_Common/b_page_state": {
readStateRaw: (key) => state.get(key) ?? null,
writeStateRaw: (key, value) => state.set(key, value),
@@ -181,7 +180,8 @@ async function main() {
basinList: el("list"),
pipeRequest: () => pipes,
runner,
rememberPipes: () => (remembered += 1),
// 패널이 넘기는 꼴 그대로 — 초안에 담음 + 사진첩 한 걸음(369-4 · onPipesDrafted)
rememberPipes: () => ((remembered += 1), (records += 1)),
// 저장분 다시 받기(349-0i) — 답은 시험이 정할 때 옴
loadSaved: () => {
savedLoads += 1;