feat(755-3): 예정노선 수정 켠 채 판 고침 — [저장] · [확정] 막고 알림 · 떠남 물음 · 탭 닫기 브라우저 물음
- design_save 저장 막음 자리(holdDesignSave · 화면에서 빠지면 풂) · 막음 = 저장 줄 · 가림막 앞 - ExpectedDraw = 켠 채 판 고침(사진첩 한 걸음 이상)이면 막음 글 · 공용 떠남 물음(guardProjectLeave) · 되돌려 고침 없으면 안 물음 - 시험 test_755 지킴 한 건 더함 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,22 @@ import { designSignature, markDesignClean } from "./design_leave";
|
||||
import { routeGradeTouch } from "./design_pipeline_page";
|
||||
import type { GradeTouch } from "../../B05_Profile/logic/B05_Profile_Pipeline_Grade";
|
||||
|
||||
/** [저장] · [확정] 막음(755-3) — 글을 돌려주면 알림하고 안 냄 · `root` 가 화면에서 빠지면 풂. */
|
||||
const saveHolds: Array<{ root: HTMLElement; hold: () => string | null }> = [];
|
||||
export function holdDesignSave(root: HTMLElement, hold: () => string | null): void {
|
||||
saveHolds.push({ root, hold });
|
||||
}
|
||||
function heldSave(): string | null {
|
||||
for (let index = saveHolds.length - 1; index >= 0; index -= 1) {
|
||||
if (!saveHolds[index].root.isConnected) saveHolds.splice(index, 1);
|
||||
}
|
||||
for (const { hold } of saveHolds) {
|
||||
const why = hold();
|
||||
if (why) return why;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export interface DesignSaveContext {
|
||||
projectId: string;
|
||||
routeId: () => number | null;
|
||||
@@ -249,6 +265,8 @@ export async function saveDesign(
|
||||
const confirm = options.confirm ?? false;
|
||||
const routeId = ctx.routeId();
|
||||
if (routeId === null) return false;
|
||||
const held = heldSave();
|
||||
if (held) return (showToast(held, "warning"), false);
|
||||
saving.add(ctx.projectId);
|
||||
let locked = confirm;
|
||||
if (locked) showLoadingOverlay();
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
* 끌 때 한 번 = 끊겨 있으면 알림하고 안 끔 · 바뀌었으면 확인창 → `POST /route/follow`(저장 0 · 폴리라인 두 단계) →
|
||||
* `onFollow(평면, 예정노선)` = 편집기 한 걸음 → 페이지 [저장] = 손 편집과 같은 길 + 초안 `expected`(`expected_route_edit.csv`).
|
||||
* [받은 노선으로] = 받은 꼭짓점으로 다시 추적 · 초안 `expected` = [](고친 예정노선 지움) — 한 걸음 · 페이지 [초기화] 는 그대로.
|
||||
* 켠 채 판을 고쳤으면(755-3) = [저장] · [확정] 막고 알림(`holdDesignSave`) · 떠남 = 공용 떠남 물음 · 탭 닫기 = 브라우저 물음.
|
||||
* 예정노선 세 벌 = 받은 노선(`expected_route.csv` · 안 덮음 · 고쳤으면 옅은 점선) · 저장본(`expected_edited`) · 이번 고침(`edit`).
|
||||
* 같은 예정노선 다른 세트(635-4) = 흐린 겹 보기만(`B05_Profile_UI_PlanContext`) · 그 끝 = 긋기 · 끌기 붙을 자리 · 벗어나면 안내 한 줄.
|
||||
* ========================================================================== */
|
||||
|
||||
import { keyIs } from "../A00_Common/key_registry";
|
||||
import { guardProjectLeave } from "../A00_Common/b_project_switch";
|
||||
import { holdDesignSave } from "../A00_Common/design/design_save";
|
||||
import { listenWhileAlive } from "@ui/ui_template_window_watch";
|
||||
import { createButton, showToast } from "@ui/ui_template_elements";
|
||||
import { askConfirm } from "@ui/ui_template_modal";
|
||||
@@ -42,6 +45,8 @@ import { flattenServerPlan, type FlattenedPlan } from "./logic/B05_Profile_UI_Ro
|
||||
type Vertex = [number, number];
|
||||
|
||||
const OFF_HINT = "「예정노선 수정」을 켜면 지도에서 예정노선을 고칩니다.";
|
||||
const HELD =
|
||||
"예정노선 수정 중 — 「예정노선 수정」을 끈 뒤 [저장]합니다(켠 동안 고친 판은 끌 때 평면선에 들어감).";
|
||||
|
||||
/** `POST /route/follow` 응답 — GET `/route/plan` 칸 이름(626-2). */
|
||||
type FollowResponse = Pick<RoutePlanResponse, "planned" | "nodes" | "curves" | "node_edits">;
|
||||
@@ -132,6 +137,14 @@ export function createExpectedDraw(params: ExpectedDrawParams): ExpectedDraw {
|
||||
return { lines: base.length > 1 ? [{ id: "main", vertices, branch: null }] : [], pieces: [] };
|
||||
};
|
||||
const measuring = (): boolean => open && params.measuring();
|
||||
/** 켠 채 판을 고침 — [저장] · 떠남이면 잃음(755-3). */
|
||||
const pending = (): boolean => open && undoStack.length > 0;
|
||||
holdDesignSave(canvas, () => (pending() ? HELD : null));
|
||||
guardProjectLeave(canvas, {
|
||||
dirty: pending,
|
||||
save: async () => (showToast(HELD, "warning"), false),
|
||||
message: HELD,
|
||||
});
|
||||
|
||||
// 속성 판 경위도 = 서버 변환(635-5)
|
||||
const coords = createPlanCoords(params.projectId, () => kit.props.render());
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
- 755-1 켠 동안 = 판만 고침 · 끊김 허용(가운데 묶음 지움) · 이 판 사진첩(Ctrl+Z · 도구줄 단추) ·
|
||||
끌 때 한 번 = 끊겼으면 알림하고 안 끔 · 바뀌었으면 `/route/follow` 한 걸음 · [잇기] = B05 사용.
|
||||
- 755-2 켠 동안 재기 = D03 재기 겹 · 받은 노선 = 분홍 점선 + 검은 테 · 켬 설명 걷음 · 위치 칸 걷음.
|
||||
- 755-3 켠 채 판 고침 = [저장] · [확정] 막고 알림 · 떠남 = 공용 떠남 물음(탭 닫기 = 브라우저 물음).
|
||||
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_755_expected_flow.py -q
|
||||
"""
|
||||
@@ -82,3 +83,16 @@ def test_받은_노선_색_설명_위치_걷음():
|
||||
assert re.search(r'key: "site",[^}]*d03: "use"', table, re.S) # D03 그대로
|
||||
theme = (ROOT / "ui_template" / "ui_template_theme.css").read_text("utf-8")
|
||||
assert "--draw-map-route-3:" in theme
|
||||
|
||||
|
||||
def test_켠_채_저장_떠남_알림():
|
||||
body = _body().replace("\r\n", "\n")
|
||||
assert "const pending = (): boolean => open && undoStack.length > 0;" in body
|
||||
assert "holdDesignSave(canvas, () => (pending() ? HELD : null));" in body
|
||||
assert "guardProjectLeave(canvas, {\n dirty: pending," in body
|
||||
save = (ROOT / "A00_Common" / "design" / "design_save.ts").read_text("utf-8")
|
||||
save = save.replace("\r\n", "\n")
|
||||
head = save[save.index("export async function saveDesign(") :]
|
||||
held = head.index("const held = heldSave();")
|
||||
assert held < head.index("saving.add(ctx.projectId);") # 막음 = 저장 줄 앞 · 가림막 없음
|
||||
assert held < head.index("showLoadingOverlay")
|
||||
|
||||
Reference in New Issue
Block a user