From fb93c149438f89eff58582194a37afada4474ffd Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 16 Oct 2026 20:29:55 +0900 Subject: [PATCH] =?UTF-8?q?feat(B05):=20352-2=20=EB=90=98=EB=8F=8C?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=C2=B7=20=EB=8B=A4=EC=8B=9C=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EA=B8=B0=ED=98=B8=20=EB=8B=A8=EC=B6=94=20=C2=B7=20?= =?UTF-8?q?[=EC=A0=80=EC=9E=A5=20=EC=A0=84=EC=9C=BC=EB=A1=9C]=20=EC=99=80?= =?UTF-8?q?=20reset=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ↶ ↷ 글 없이 기호 + aria-label · title(단축키) - 저장 전으로 단추 · history.reset · 초안 다리 reset 지움 - 시험 chrome_modal · 346_4 · 346_1 고쳐 씀 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn --- B05_Profile/B05_Profile_UI_RouteEdit.ts | 7 ------- .../B05_Profile_UI_RouteEdit_Chrome.ts | 10 ++++------ B05_Profile/B05_Profile_UI_RouteEdit_Draft.ts | 9 ++------- .../B05_Profile_UI_RouteEdit_History.ts | 13 +------------ .../tester/helper_346_1_pipeline_page.cjs | 13 +------------ resources/tester/helper_346_4_one_undo.cjs | 5 ----- resources/tester/test_346_1_pipeline_page.py | 2 +- resources/tester/test_346_4_one_undo.py | 5 ----- .../tester/test_b05_routeedit_chrome_modal.py | 19 ++++++++++++------- 9 files changed, 21 insertions(+), 62 deletions(-) diff --git a/B05_Profile/B05_Profile_UI_RouteEdit.ts b/B05_Profile/B05_Profile_UI_RouteEdit.ts index 224bbfb60..b971bc532 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit.ts @@ -284,13 +284,6 @@ export async function mountRouteEditor( planMinRadiusM: () => minRadiusM, apply: (snapshot, message) => restoreSnapshot(snapshot, message, true), }); - // [저장 전으로] — 마지막 저장(페이지를 세운 때) 노선 · 그 걸음의 「현재 추천」으로. 되돌리기로 다시 살림. - overlay.querySelector('[data-act="cancel"]')!.addEventListener("click", () => { - const snapshot = history?.reset(); - if (!snapshot) return showToast("반영 뒤 고친 노선이 없습니다.", "info"); - initial.restoreTag(snapshot.rec); - restoreSnapshot(snapshot, "반영 전 노선으로 되돌렸습니다.", false); - }); function resize(): void { if (closed || !overlay.isConnected) return; diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts index cf375a5ed..bac5493ed 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Chrome.ts @@ -13,8 +13,8 @@ import { bindFootprintToggle } from "./B05_Profile_UI_RouteEdit_Footprint"; * 아래. 메인 창은 왼쪽으로 밀고 오른쪽 세로 칸에 횡단 두 판이 앉는다. * * 자리(345-3) — 모달이 아니라 종단 보기 가운데 위 본문(옛 3D 자리)에 붙는다. 덮개 · 전체 화면 · - * 닫기 단추는 걷었다 · [취소] → [저장 전으로] · [확인] · [노선 반영]은 없앰(346-3 — 노선은 페이지 [저장]이 - * 맨 앞에서 보냄) · 오른쪽 횡단 칸은 접는 칸. + * 닫기 단추는 걷었다 · [취소] · [확인] · [노선 반영] · [저장 전으로]는 없앰(346-3 · 352-2 — 노선은 페이지 + * [저장]이 맨 앞에서 보냄) · 오른쪽 횡단 칸은 접는 칸. * 머리 `tools` 자리에 부른 쪽 단추([3D])가 앉는다. [노선 추천] · 현재 추천 · [초기화]는 좌측 * 「노선 추천」 칸으로 옮겼다(345-4 · `_Panel_Recommend`). * ========================================================================== */ @@ -84,11 +84,9 @@ export function createRouteEditChrome( title="도로 끝 · 비탈 끝(깎기 붉음 · 쌓기 파랑)을 평면에 겹칩니다">발자국 + title="되돌리기 (Ctrl+Z)" aria-label="되돌리기" disabled>↶ - + title="다시하기 (Ctrl+Y)" aria-label="다시하기" disabled>↷
diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_Draft.ts b/B05_Profile/B05_Profile_UI_RouteEdit_Draft.ts index a9fdd9ebe..de49bffad 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_Draft.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_Draft.ts @@ -1,14 +1,14 @@ /* ============================================================================= * B05_Profile_UI_RouteEdit_Draft.ts * 노선 편집기 ↔ 계산 묶음 다리(PLAN 346-1) — 노선을 한 번 고칠 때마다(놓기 · 더함 · 지움 · 곡선 · - * 되돌리기 · 다시하기 · [저장 전으로] · 추천 [적용]) 노선 초안을 넘김. 끄는 동안은 넘기지 않음 + * 되돌리기 · 다시하기 · 추천 [적용]) 노선 초안을 넘김. 끄는 동안은 넘기지 않음 * (사진첩에 쌓이는 때 = 손을 놓은 때). * * 편집기는 사진첩(`_History`)을 `watch` 로 감싸기만 함 — 고친 줄 하나. 저장 안 한 초안은 * 다리가 캐시 칸(`route-draft`)에 두고, 편집기가 자료를 읽은 뒤 `restore` 로 한 번 되살림 * (새로고침 · 보기 전환에도 남음). 계산 · 가게는 `A00_Common/design/design_pipeline_page.ts` 몫. * - * 되돌리기 줄(346-4) — 페이지 사진첩(`_Profile_History`)이 있으면 쌓기 · [저장 전으로] 뒤 사진첩에 한 걸음 · + * 되돌리기 줄(346-4) — 페이지 사진첩(`_Profile_History`)이 있으면 쌓기 · * [되돌리기] · [다시하기]는 사진첩이 함(평면 · 종단 · 횡단 · 관 · 구조물 한 줄) · 사진첩이 되쓴 노선 * 초안은 `fromPage` 로 편집기 새 걸음이 됨. 사진첩이 없으면 편집기 사진 그대로. * ========================================================================== */ @@ -99,11 +99,6 @@ export function watch( album.redo(); return null; }, - reset: () => { - const snapshot = tell(history.reset()); - if (snapshot) pageHistory()?.record(); - return snapshot; - }, canUndo: () => pageHistory()?.canUndo() ?? history.canUndo(), canRedo: () => pageHistory()?.canRedo() ?? history.canRedo(), fromPage, diff --git a/B05_Profile/B05_Profile_UI_RouteEdit_History.ts b/B05_Profile/B05_Profile_UI_RouteEdit_History.ts index 1a2added5..4c2f2273b 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit_History.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit_History.ts @@ -11,7 +11,7 @@ * * 되돌리기 줄은 페이지 사진첩 하나(`_Profile_History` · 346-4) — 계산 묶음 다리가 있으면(`_Draft.watch`) * [되돌리기] · [다시하기] · Ctrl+Z · Y 는 사진첩이 받고, 여기 사진은 고정 · 추천 꼬리표 · 고른 점을 - * 되살리는 기록(`match`)과 [저장 전으로](`reset`) · 고친 것 있음(`isDirty`)에만 씀. + * 되살리는 기록(`match`) · 고친 것 있음(`isDirty`)에만 씀. * ========================================================================== */ import { onPageHistory } from "./B05_Profile_UI_Profile_History"; @@ -44,8 +44,6 @@ export interface RouteEditHistory { undo: () => RouteEditSnapshot | null; /** 한 걸음 앞으로. 없으면 null. */ redo: () => RouteEditSnapshot | null; - /** 창을 연 상태로. 이미 그 상태면 null. */ - reset: () => RouteEditSnapshot | null; canUndo: () => boolean; canRedo: () => boolean; /** 창을 연 뒤로 고친 것이 있나 — [초기화]를 켤지 정한다. */ @@ -115,15 +113,6 @@ export function createRouteEditHistory(initial: RouteEditSnapshot): RouteEditHis at += 1; return clone(steps[at]); }, - reset() { - // 이미 연 상태 그대로면 할 일이 없다 — 눌러도 걸음만 늘어난다. - if (sameRoute(steps[at], steps[0])) return null; - // 초기화도 **되돌릴 수 있어야** 한다 — 첫 사진을 새 걸음으로 쌓는다. - steps.length = at + 1; - steps.push(clone(steps[0])); - at = steps.length - 1; - return clone(steps[at]); - }, canUndo: () => at > 0, canRedo: () => at < steps.length - 1, isDirty: () => !sameRoute(steps[at], steps[0]), diff --git a/resources/tester/helper_346_1_pipeline_page.cjs b/resources/tester/helper_346_1_pipeline_page.cjs index 7f177fc8b..03151b31f 100644 --- a/resources/tester/helper_346_1_pipeline_page.cjs +++ b/resources/tester/helper_346_1_pipeline_page.cjs @@ -243,7 +243,7 @@ async function run() { // ③ 편집기 다리 — 사진첩 감싸기 · 초안 되살림 { const told = []; - let dirty = true; + const dirty = true; const fake = { commit: () => undefined, undo: () => ({ @@ -259,15 +259,6 @@ async function run() { picked: -1, }), redo: () => null, - reset: () => ({ - planned: [[0, 0]], - curveOn: [true], - curveRadius: [null], - curveLock: [null], - curveArc: [null], - apexLock: [false], - picked: -1, - }), canUndo: () => true, canRedo: () => false, isDirty: () => dirty, @@ -287,8 +278,6 @@ async function run() { }); watched.undo(); watched.redo(); - dirty = false; - watched.reset(); const restored = []; draftLink.restore(bridge, (snap, message, record) => restored.push([snap.planned.length, record]), diff --git a/resources/tester/helper_346_4_one_undo.cjs b/resources/tester/helper_346_4_one_undo.cjs index 5471833af..963db4efd 100644 --- a/resources/tester/helper_346_4_one_undo.cjs +++ b/resources/tester/helper_346_4_one_undo.cjs @@ -151,11 +151,6 @@ const snap = (nodes, lock = false) => ({ out.redo3 = state(); out.editorAfterRedo = editor.slice(out.editorAfterUndo.length); out.profileReads = profileReads; - // [반영 전으로] — 사진첩 한 걸음 · 되돌리면 옮긴 노선 - history.reset(); - out.reset = state(); - pageAlbum.undo(); - out.resetUndo = state(); controls.dispose(); process.stdout.write(JSON.stringify(out)); })(); diff --git a/resources/tester/test_346_1_pipeline_page.py b/resources/tester/test_346_1_pipeline_page.py index f100e72c2..a10480a78 100644 --- a/resources/tester/test_346_1_pipeline_page.py +++ b/resources/tester/test_346_1_pipeline_page.py @@ -173,7 +173,7 @@ def test_늦은_응답_버림(r): def test_편집기_다리(r): d = r["draftLink"] - assert d["told"] == [3, 2, None] # 쌓기 · 되돌리기 · 열 때로(null) — 다시하기 없음은 안 알림 + assert d["told"] == [3, 2] # 쌓기 · 되돌리기 — 다시하기 없음은 안 알림 assert d["restored"] == [ [r["n"], True] ] # 저장 안 한 초안 = 새 걸음으로 되살림 · 없으면 안 부름 diff --git a/resources/tester/test_346_4_one_undo.py b/resources/tester/test_346_4_one_undo.py index 2fa120d9a..f2423b500 100644 --- a/resources/tester/test_346_4_one_undo.py +++ b/resources/tester/test_346_4_one_undo.py @@ -54,11 +54,6 @@ def test_다시하기는_앞으로(out) -> None: assert out["profileReads"] == 6 # 종단도도 걸음마다 다시 읽음 -def test_반영_전으로도_한_걸음(out) -> None: - assert out["reset"]["route"] is None and out["reset"]["cross"] # 노선만 열 때로 - assert out["resetUndo"]["route"] == 70 - - def test_단축키는_사진첩_한_곳(): tools = (ROOT / "B05_Profile/B05_Profile_UI_Profile_Panel_Tools.ts").read_text(encoding="utf-8") assert "undoOwner" not in tools diff --git a/resources/tester/test_b05_routeedit_chrome_modal.py b/resources/tester/test_b05_routeedit_chrome_modal.py index d07655715..4d1234e5d 100644 --- a/resources/tester/test_b05_routeedit_chrome_modal.py +++ b/resources/tester/test_b05_routeedit_chrome_modal.py @@ -1,7 +1,7 @@ """계획노선 편집 겉틀 — 345-3 부터 모달이 아니라 종단 보기 가운데 위 본문(PLAN 127-1 의 공용 모달 조각은 걷음). · 덮개(`ui-modal__backdrop`) · 전체 화면 · 닫기 단추 없음 · 부모를 받아 붙음(`document.body` 아님) -· [취소] → [반영 전으로](이력 처음으로) · [확인] → [노선 반영] · 머리 끝 `tools` 자리([3D]) +· [저장 전으로] 없음(352-2) · ↶ ↷ 는 기호 단추 · 머리 끝 `tools` 자리([3D]) · 오른쪽 횡단 미리보기 = 접는 칸 · 재계산 대기 막은 화면 전체(fixed) · R 라벨은 칸 안 절대 위치 · 바깥 누름 · Esc 로 안 닫힘(모달 아님) """ @@ -33,13 +33,16 @@ def test_겉틀은_본문_칸(): assert 'overlay.className = "b05-routeedit";' in chrome assert "b05-routeedit__close" not in chrome and 'data-slot="close"' not in chrome assert '"tools"' in chrome and "replaceWith(...tools)" in chrome - # 346-3 — [노선 반영] 없앰(노선은 페이지 [저장]이 맨 앞에서 보냄) · [취소] = [저장 전으로] - assert ">저장 전으로" in chrome and 'data-act="apply"' not in chrome - assert "노선 반영" not in chrome + # 346-3 — [노선 반영] 없앰(노선은 페이지 [저장]이 맨 앞에서 보냄) · 352-2 — [저장 전으로] 없앰 + assert 'data-act="apply"' not in chrome and 'data-act="cancel"' not in chrome + assert ">저장 전으로" not in chrome and "노선 반영" not in chrome assert ">취소" not in chrome and ">확인" not in chrome + # 352-2 — 되돌리기 · 다시하기 = 글 없이 기호 + aria-label · title(단축키) + assert 'aria-label="되돌리기" disabled>↶' in chrome + assert 'aria-label="다시하기" disabled>↷' in chrome + assert 'title="되돌리기 (Ctrl+Z)"' in chrome and 'title="다시하기 (Ctrl+Y)"' in chrome # 시험 · 배선이 집는 자리는 남김 - for hook in ('data-act="cancel"', "b05-routeedit__measure-close"): - assert hook in chrome + assert "b05-routeedit__measure-close" in chrome assert 'data-act="side-toggle"' in chrome and "is-collapsed" in chrome @@ -67,7 +70,9 @@ def test_페이지_수명_닫기_없음(): assert "new ResizeObserver(" in main assert "host.onDispose(dispose);" in main assert "historyControls.listen(host.visible());" in main - assert "history?.reset();" in main # [반영 전으로] + assert "history?.reset()" not in main # 352-2 — [저장 전으로] 지움 + hist = _read("B05_Profile_UI_RouteEdit_History.ts") + assert "reset" not in hist.split("export interface RouteEditHistory", 1)[1].split("}", 1)[0] assert len(main.splitlines()) <= 700 label = _read("B05_Profile_UI_RouteEdit_Label.ts") assert "document.body.append" not in label and "container.append(root);" in label