feat(B05): 352-2 되돌리기 · 다시하기 기호 단추 · [저장 전으로] 와 reset 삭제
- ↶ ↷ 글 없이 기호 + aria-label · title(단축키) - 저장 전으로 단추 · history.reset · 초안 다리 reset 지움 - 시험 chrome_modal · 346_4 · 346_1 고쳐 씀 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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="도로 끝 · 비탈 끝(깎기 붉음 · 쌓기 파랑)을 평면에 겹칩니다">발자국</button>
|
||||
<i class="b05-routeedit__divider" aria-hidden="true"></i>
|
||||
<button type="button" class="ui-btn ui-btn--ghost" data-act="undo"
|
||||
title="되돌리기 (Ctrl+Z)" disabled>↶ 되돌리기</button>
|
||||
title="되돌리기 (Ctrl+Z)" aria-label="되돌리기" disabled>↶</button>
|
||||
<button type="button" class="ui-btn ui-btn--ghost" data-act="redo"
|
||||
title="다시하기 (Ctrl+Y)" disabled>↷ 다시하기</button>
|
||||
<button type="button" class="ui-btn ui-btn--ghost" data-act="cancel"
|
||||
title="마지막 [저장] 뒤 고친 노선을 버리고 그때 노선으로 되돌립니다 — 되돌리기로 다시 살릴 수 있습니다">저장 전으로</button>
|
||||
title="다시하기 (Ctrl+Y)" aria-label="다시하기" disabled>↷</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="b05-routeedit__canvas-wrap">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]),
|
||||
|
||||
@@ -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]),
|
||||
|
||||
@@ -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));
|
||||
})();
|
||||
|
||||
@@ -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]
|
||||
] # 저장 안 한 초안 = 새 걸음으로 되살림 · 없으면 안 부름
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ">저장 전으로</button>" in chrome and 'data-act="apply"' not in chrome
|
||||
assert "노선 반영</button>" not in chrome
|
||||
# 346-3 — [노선 반영] 없앰(노선은 페이지 [저장]이 맨 앞에서 보냄) · 352-2 — [저장 전으로] 없앰
|
||||
assert 'data-act="apply"' not in chrome and 'data-act="cancel"' not in chrome
|
||||
assert ">저장 전으로</button>" not in chrome and "노선 반영</button>" not in chrome
|
||||
assert ">취소</button>" not in chrome and ">확인</button>" not in chrome
|
||||
# 352-2 — 되돌리기 · 다시하기 = 글 없이 기호 + aria-label · title(단축키)
|
||||
assert 'aria-label="되돌리기" disabled>↶</button>' in chrome
|
||||
assert 'aria-label="다시하기" disabled>↷</button>' 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
|
||||
|
||||
Reference in New Issue
Block a user