diff --git a/B05_Profile/B05_Profile_UI_ExpectedDraw.ts b/B05_Profile/B05_Profile_UI_ExpectedDraw.ts index b0b04c79b..4141e60ea 100644 --- a/B05_Profile/B05_Profile_UI_ExpectedDraw.ts +++ b/B05_Profile/B05_Profile_UI_ExpectedDraw.ts @@ -10,6 +10,7 @@ * 편집기 한 걸음(되돌리기 됨) → 페이지 [저장] = 손 편집과 같은 길 + 초안 `expected`(`expected_route_edit.csv`). * [받은 노선으로] = 받은 꼭짓점으로 다시 추적 · 초안 `expected` = [](고친 예정노선 지움) — 한 걸음 · 페이지 [초기화] 는 그대로. * 예정노선 세 벌 = 받은 노선(`expected_route.csv` · 안 덮음 · 고쳤으면 옅은 점선) · 저장본(`expected_edited`) · 이번 고침(`edit`). + * 같은 예정노선 다른 세트(635-4) = 흐린 겹 보기만(`B05_Profile_UI_PlanContext`) · 그 끝 = 긋기 · 끌기 붙을 자리 · 벗어나면 안내 한 줄. * ========================================================================== */ import { keyIs } from "../A00_Common/key_registry"; @@ -34,6 +35,7 @@ import { createPlaceFind } from "../D03_PlanAnalysis/D03_PlanAnalysis_UI_Site"; import { requestJson, type RoutePlanResponse } from "./B05_Profile_Api_Replan"; import { loadDesignTerrainGrid, type DesignTerrainGrid } from "./B05_Profile_Api_TerrainGrid"; import { fillPlanPanel } from "./B05_Profile_UI_Panel_Plan"; +import { createPlanContextLayer } from "./B05_Profile_UI_PlanContext"; import { markShown } from "./B05_Profile_UI_RouteEdit_Marks"; import { polylineLengthM } from "./B05_Profile_UI_RouteEdit_Render"; import type { RouteEditChrome } from "./B05_Profile_UI_RouteEdit_Chrome"; @@ -137,6 +139,8 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { params.redraw(); }); + const others = createPlanContextLayer(params.projectId, params.redraw); + // ── 예정노선 키트(긋기 · 고르기 · 메뉴 · 속성 판 · 칸 = 예정노선 페이지와 같은 한 벌) ── const kit = createPlanKit({ page: "b05", @@ -151,6 +155,7 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { idle: () => open, onMode, onSelect: () => (kit.props.render(), params.redraw()), + snaps: others.joints, cards: { site: { parts: [find.root] } }, }); const { draw, edit: editor, props, menu } = kit; @@ -178,10 +183,11 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { }); const compare = createText("", "muted"); const hint = createText(OFF_HINT, "muted"); + const jointHint = createText("", "muted"); const row = document.createElement("div"); row.className = "b05-routeedit__expected-row"; row.append(originalToggle.root, resetButton); - drawCard.append(row, compare, hint); + drawCard.append(row, compare, jointHint, hint); fillPlanPanel({ site: kit.cards.find((card) => card.contains(find.root)) ?? null, draw: drawCard, @@ -194,6 +200,8 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { ? `받은 노선 ${meters(received())} m → 고친 노선 ${meters(line())} m` : ""; compare.hidden = !edited; + jointHint.textContent = others.note(line()) ?? ""; + jointHint.hidden = !jointHint.textContent; hint.textContent = !open ? OFF_HINT : network.lines.length ? HINT : EMPTY_HINT; } @@ -346,6 +354,7 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { // ── 그림 ──────────────────────────────────────────────── function paint(context: CanvasRenderingContext2D): void { + others.paint(context, map()); // 다른 세트 = 흐린 겹(켬끔 상관없이 보기만) if (showOriginal && original.length > 1 && line() !== original) { context.save(); context.beginPath(); @@ -381,7 +390,9 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { selected: editor.selected()?.kind ?? null, busy, compare: compare.textContent, + joint: jointHint.textContent, }), + others: others.probe, line, original: () => original, source: () => source, @@ -396,6 +407,7 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw { saved = nextSaved; network = fromLine(); syncCard(); + void others.load().then(syncCard); void requestJson<{ expected_source?: Vertex[] }>( `/projects/${params.projectId}/route/plan/source`, {}, diff --git a/resources/tester/test_635_4_plan_context_layer.py b/resources/tester/test_635_4_plan_context_layer.py index 43e3026b6..a19c5c466 100644 --- a/resources/tester/test_635_4_plan_context_layer.py +++ b/resources/tester/test_635_4_plan_context_layer.py @@ -1,11 +1,15 @@ -"""B05 흐린 다른 세트 겹 · 이음점 붙기(PLAN 635-4 · 요구 546 · 547) — TS `logic/B05_Profile_PlanContext.ts`. +"""B05 흐린 다른 세트 겹 · 이음점 붙기(PLAN 635-4 · 요구 546 · 547). + +TS `logic/B05_Profile_PlanContext.ts` tsc 로 옮겨 Node 로 돌림. - 흐릴 세트 = 내 세트 아님 · 연결 없음 = 빈 · 꺾은선 1 점 = 안 그림. - 이음점 = 남 세트 끝 · 받을 때 이어진 이음점 = 내 받은 선 끝 1 m 안. - 벗어남 = 이어졌던 이음점에서 지금 선 끝까지 1 m 밖만 안내 · 붙이면 안내 없음. - 이름표 = 가장 긴 꺾은선 가운데. -- 지킴: 겹은 보기만(GET 만 · 파일 · 누름 칸 없음) · 기능 표 `others` = B05 보기만 · 키트가 이음점을 긋기 · 끌기에 넘김. +- 지킴: 겹은 보기만(GET 만 · 파일 · 누름 칸 없음) · 기능 표 `others` = B05 보기만 · + 키트가 이음점을 긋기 · 끌기에 넘김 · + B05 예정노선 수정이 겹을 그림 · 이음점 넘김 · 안내 줄. ./venv/Scripts/python.exe -m pytest resources/tester/test_635_4_plan_context_layer.py -q """ @@ -130,3 +134,6 @@ def test_기능_표_others_B05_보기만_키트_이음점_넘김(): assert kit.count("snaps: params.snaps") == 2 assert 'note: "이음점에 붙음"' in (D03 / "D03_PlanAnalysis_UI_Draw.ts").read_text("utf-8") assert "params.snaps?.()" in (D03 / "D03_PlanAnalysis_UI_Edit.ts").read_text("utf-8") + wire = (ROOT / "B05_Profile" / "B05_Profile_UI_ExpectedDraw.ts").read_text("utf-8") + assert "snaps: others.joints" in wire and "others.paint(context" in wire + assert "others.note(line())" in wire and "others.load()" in wire