feat(b08): 거리이정표 [요소 추가] · 선 없는 새 거래처 · 연결선 수기 입력 (250-4)
- 공사지 · 기준점 [+] 없앰 → [자동 정렬] 옆 [요소 추가] - 등록 = 상자만(linked false) · 연결 점으로 이음 · 안 이은 거래처 = 구간 km 안 셈(파이썬 · TS 짝) - 연결선 모달 [수기 입력] = 카카오 길찾기 연결 끊음(manual) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LLCk2y5xE8YGVgjbTntWsY
This commit is contained in:
@@ -64,8 +64,10 @@ def compute_milestone(data: dict[str, Any], mid_default_m: float | None) -> list
|
||||
for route in data.get("routes") or []:
|
||||
for index, row in enumerate(route.get("rows") or []):
|
||||
sums = {"s2": 0.0, "s1": 0.0, "pv": 0.0, "un": 0.0}
|
||||
via = bool(base.get("enabled")) and route.get("via_base", True) is not False
|
||||
add_legs(sums, route.get("legs"), "via" if via else "direct")
|
||||
linked = route.get("linked", True) is not False # 안 이은 거래처 = 구간 km 없음(155)
|
||||
via = linked and bool(base.get("enabled")) and route.get("via_base", True) is not False
|
||||
if linked:
|
||||
add_legs(sums, route.get("legs"), "via" if via else "direct")
|
||||
if via:
|
||||
add_legs(sums, base.get("legs"), "base")
|
||||
if row.get("dest") == "mid":
|
||||
|
||||
@@ -83,6 +83,10 @@ export interface MilestoneRoute {
|
||||
lat?: number | null;
|
||||
/** 다이어그램에 끌어 놓은 자리(153 · 왼 위 · 그림 좌표) — 없으면 방위 자동 자리 */
|
||||
pos?: [number, number] | null;
|
||||
/** 선 이음(155) — false = 아직 안 이음(요소 추가 뒤 · 연결 점으로 이음 · 구간 km 안 셈) · 없음 = 이음(옛 자료) */
|
||||
linked?: boolean;
|
||||
/** 수기 입력(155) — 카카오 길찾기 안 함 · km 손 입력만 */
|
||||
manual?: boolean;
|
||||
/** 업체 → 기준점(거침) · 시점 구간 */
|
||||
legs: Leg[];
|
||||
rows: MilestoneRow[];
|
||||
@@ -98,6 +102,7 @@ export interface MilestoneData {
|
||||
lon?: number | null;
|
||||
lat?: number | null;
|
||||
pos?: [number, number] | null;
|
||||
manual?: boolean;
|
||||
/** 기준점 → 시점 공통 구간 */
|
||||
legs: Leg[];
|
||||
};
|
||||
@@ -153,8 +158,9 @@ export function computeMilestone(
|
||||
for (const route of data.routes ?? []) {
|
||||
(route.rows ?? []).forEach((row, index) => {
|
||||
const sums = { s2: 0, s1: 0, pv: 0, un: 0 };
|
||||
const via = !!base?.enabled && route.via_base !== false;
|
||||
addLegs(sums, route.legs, via ? "via" : "direct");
|
||||
const linked = route.linked !== false; // 안 이은 거래처 = 구간 km 없음(155)
|
||||
const via = linked && !!base?.enabled && route.via_base !== false;
|
||||
if (linked) addLegs(sums, route.legs, via ? "via" : "direct");
|
||||
if (via) addLegs(sums, base.legs, "base");
|
||||
if (row.dest === "mid") addLegs(sums, [mid], "mid");
|
||||
const paved = sums.s2 + sums.s1 + sums.pv;
|
||||
|
||||
@@ -220,7 +220,7 @@ export function segmentEnds(data: MilestoneData, from: string, start: LonLat): K
|
||||
? { key: "base", text: `${baseName} → 시점`, from: pointOf(data.base), to: start ?? null }
|
||||
: null;
|
||||
const route = data.routes.find((r) => r.id === from);
|
||||
if (!route) return null;
|
||||
if (!route || route.linked === false) return null; // 155 안 이은 거래처 = 구간 없음
|
||||
const viaBase = data.base.enabled && route.via_base;
|
||||
return {
|
||||
key: "route",
|
||||
@@ -506,7 +506,9 @@ export function layoutMilestone(
|
||||
},
|
||||
[ux, uy],
|
||||
);
|
||||
line(g.id, g.anchor === "base" ? "base" : "start", g.legs);
|
||||
// 155 안 이은 거래처 = 선 없음(연결 점으로 이음)
|
||||
if (data.routes.find((r) => r.id === g.id)?.linked !== false)
|
||||
line(g.id, g.anchor === "base" ? "base" : "start", g.legs);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -94,12 +94,14 @@ class Place(BaseModel):
|
||||
lat: float | None = Field(default=None, ge=-90, le=90)
|
||||
# 153 다이어그램에 끌어 놓은 자리(왼 위 · 그림 좌표) — 없으면 방위 자동 자리
|
||||
pos: tuple[float, float] | None = None
|
||||
manual: bool = False # 155 수기 입력 — 카카오 길찾기 안 함
|
||||
legs: list[Leg] = Field(default_factory=list, max_length=20)
|
||||
|
||||
|
||||
class Route(Place):
|
||||
id: str = Field(pattern=ROUTE_ID)
|
||||
via_base: bool = True
|
||||
linked: bool = True # 155 False = 아직 선 안 이음(요소 추가 뒤)
|
||||
rows: list[Row] = Field(default_factory=list, max_length=50)
|
||||
|
||||
|
||||
|
||||
@@ -56,11 +56,13 @@
|
||||
}
|
||||
|
||||
/* 244-2 다이어그램 — 상자 · 선 · km 글(테마 변수) · 스크롤 없음(244-8 · 그림 = 틀 안 맞춤) */
|
||||
/* 153 [자동 정렬] — 다이어그램 왼쪽 위(끌어 놓은 자리가 있을 때만 · 오른쪽 위 = 진행단계 판 자리) */
|
||||
.b08-milestone__arrange {
|
||||
/* 153 · 155 [자동 정렬](끌어 놓은 자리 있을 때만) · [요소 추가] — 다이어그램 왼쪽 위(오른쪽 위 = 진행단계 판 자리) */
|
||||
.b08-milestone__tools {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.b08-milestone__diagram {
|
||||
@@ -89,8 +91,7 @@
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
.b08-milestone__box text,
|
||||
.b08-milestone__plus text {
|
||||
.b08-milestone__box text {
|
||||
fill: var(--color-text);
|
||||
}
|
||||
|
||||
@@ -127,16 +128,6 @@
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.b08-milestone__plus {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.b08-milestone__plus circle {
|
||||
fill: var(--color-surface);
|
||||
stroke: var(--color-accent);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
.b08-milestone__km {
|
||||
fill: var(--color-text);
|
||||
font-size: 12px;
|
||||
|
||||
@@ -161,25 +161,6 @@ export function createDiagram(
|
||||
base: () => openPlaceModal(projectId, { add: false, id: "base" }),
|
||||
};
|
||||
|
||||
const plus = (box: DiagramBox, viaBase: boolean): SVGGElement => {
|
||||
const g = svg("g", { class: "b08-milestone__plus", role: "button", tabindex: 0 });
|
||||
const cx = box.x + box.w - 2;
|
||||
const cy = box.y + 2;
|
||||
g.append(
|
||||
svg("circle", { cx, cy, r: 11 }),
|
||||
svg("text", { x: cx, y: cy, "text-anchor": "middle", "dominant-baseline": "central" }, "+"),
|
||||
svg("title", {}, "항목 추가"),
|
||||
);
|
||||
g.dataset.b08MilestonePlus = viaBase ? "base" : "site";
|
||||
const go = (e: Event): void => {
|
||||
e.stopPropagation();
|
||||
openPlaceModal(projectId, { add: true, viaBase }, addRoute);
|
||||
};
|
||||
g.addEventListener("click", go);
|
||||
g.addEventListener("keydown", (e) => e.key === "Enter" && go(e));
|
||||
return g;
|
||||
};
|
||||
|
||||
/** 153 상자 끌어 옮김 — 4px 넘게 움직이면 끌기(누름 = 모달은 그대로) · 놓으면 그 자리 저장(캐시 · [저장] 때 서버)
|
||||
* 기준점을 옮기면 거친 거래처도 따라감(자리 안 정한 것만 · 레이아웃이 기준점 둘레로 놓음) */
|
||||
const dragBox = (g: SVGGElement, box: DiagramBox, shift: SVGGElement): void => {
|
||||
@@ -269,9 +250,10 @@ export function createDiagram(
|
||||
const route = fresh.routes.find((r) => r.id === box.id);
|
||||
if (!t || !route) return;
|
||||
const via = t === "base";
|
||||
const now = fresh.base.enabled && route.via_base !== false;
|
||||
const now = route.linked === false ? null : fresh.base.enabled && route.via_base !== false;
|
||||
if (via === now) return; // 같은 연결 = 그대로
|
||||
route.via_base = via;
|
||||
route.linked = true; // 155 요소 추가 뒤 첫 이음
|
||||
route.legs = [{ road: null, km: null }]; // 옛 구간 km = 다른 길 — 새로 길찾기
|
||||
putMilestone(projectId, fresh);
|
||||
void findSegmentKm(projectId, route.id).then(toastKm);
|
||||
@@ -295,8 +277,16 @@ export function createDiagram(
|
||||
putMilestone(projectId, fresh);
|
||||
},
|
||||
});
|
||||
arrange.classList.add("b08-milestone__arrange");
|
||||
arrange.dataset.b08MilestoneArrange = "";
|
||||
// 155 [요소 추가] — 기준점 · 거래처 등록(공사지 · 기준점 [+] 없앰) · 등록 뒤 연결 점으로 선 이음
|
||||
const addElem = createButton({
|
||||
label: "요소 추가",
|
||||
size: "sm",
|
||||
variant: "ghost",
|
||||
onClick: () => openPlaceModal(projectId, { add: true }, addRoute),
|
||||
});
|
||||
addElem.dataset.b08MilestoneAdd = "open";
|
||||
const tools = el("div", { className: "b08-milestone__tools", children: [arrange, addElem] });
|
||||
|
||||
const refresh = (): void => {
|
||||
const data = liveMilestone(projectId);
|
||||
@@ -383,8 +373,6 @@ export function createDiagram(
|
||||
g.addEventListener("keydown", (e) => e.key === "Enter" && info());
|
||||
if (box.kind === "route" || box.kind === "base") dragBox(g, box, shift);
|
||||
if (box.kind === "route") g.append(connectDot(box, shift));
|
||||
if (box.kind === "site") g.append(plus(box, false));
|
||||
if (box.kind === "base") g.append(plus(box, true));
|
||||
shift.append(g);
|
||||
if (box.kind === "site") shift.append(lineLayer);
|
||||
}
|
||||
@@ -421,7 +409,7 @@ export function createDiagram(
|
||||
shift.append(text);
|
||||
}
|
||||
arrange.hidden = !data.base.pos && !data.routes.some((r) => r.pos);
|
||||
host.replaceChildren(root, arrange);
|
||||
host.replaceChildren(root, tools);
|
||||
attachSvgZoomPan({
|
||||
svg: root,
|
||||
layer,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
* 자동 그림(244-11) = 거래처 쪽 구간 [길찾기] · 옮김 때만(`findSegmentKm`)
|
||||
* ========================================================================== */
|
||||
|
||||
import { createCheckbox } from "@ui/ui_template_checkbox";
|
||||
import { createButton, createInputField, createSelectField, el } from "@ui/ui_template_elements";
|
||||
import { openModal } from "@ui/ui_template_modal";
|
||||
import {
|
||||
@@ -240,20 +241,39 @@ export function openLegInfo(projectId: string, from: string): void {
|
||||
});
|
||||
save.dataset.b08MilestoneLegSave = "";
|
||||
actions.append(find, save);
|
||||
body.append(
|
||||
legs.root,
|
||||
hint(
|
||||
from === "base"
|
||||
? "기준점 → 시점 = 도로가 안 이어질 수 있음 — 거리를 손으로 넣어도 됨(빈칸 = 길찾기 자동 값)"
|
||||
: "빈칸 = 길찾기 자동 값 · 넣은 값이 우선",
|
||||
),
|
||||
status,
|
||||
el("h4", { text: "경로 — 다음(카카오) 지도" }),
|
||||
map.root,
|
||||
// 155 [수기 입력] — 카카오 길찾기 연결 끊음(자동 값 지움 · 길찾기 · 지도 숨김 · km 손 입력) · 풀면 다시 길찾기
|
||||
const owner = (d = liveMilestone(projectId)) =>
|
||||
from === "base" ? d.base : d.routes.find((r) => r.id === from);
|
||||
const manual = createCheckbox("수기 입력 — 카카오 길찾기 안 함(거리 손 입력)");
|
||||
manual.input.checked = !!owner()?.manual;
|
||||
manual.input.dataset.b08MilestoneManual = "";
|
||||
const auto = hint(
|
||||
from === "base"
|
||||
? "기준점 → 시점 = 도로가 안 이어질 수 있음 — 거리를 손으로 넣어도 됨(빈칸 = 길찾기 자동 값)"
|
||||
: "빈칸 = 길찾기 자동 값 · 넣은 값이 우선",
|
||||
);
|
||||
const mapHead = el("h4", { text: "경로 — 다음(카카오) 지도" });
|
||||
const showMode = (): void => {
|
||||
const off = manual.input.checked;
|
||||
find.hidden = auto.hidden = mapHead.hidden = map.root.hidden = off;
|
||||
status.textContent = off ? "수기 입력 — 거리를 손으로 넣으세요" : status.textContent;
|
||||
};
|
||||
manual.input.addEventListener("change", () => {
|
||||
const fresh = liveMilestone(projectId);
|
||||
const target = owner(fresh);
|
||||
if (!target) return;
|
||||
target.legs = legs.value().map((l) => (manual.input.checked ? { ...l, auto_km: null } : l));
|
||||
target.manual = manual.input.checked;
|
||||
putMilestone(projectId, fresh);
|
||||
redrawLegs();
|
||||
showMode();
|
||||
if (!manual.input.checked) void run(); // 다시 카카오 연결 = 길찾기 한 번
|
||||
});
|
||||
body.append(manual.root, legs.root, auto, status, mapHead, map.root);
|
||||
showMode();
|
||||
drawMap();
|
||||
// 길 선이 아직 없으면 열 때 한 번(km 같으면 안 씀 · 자동 그림 없음)
|
||||
if (!segmentPath(from).length && seg.from && seg.to) void run(false);
|
||||
// 길 선이 아직 없으면 열 때 한 번(km 같으면 안 씀 · 자동 그림 없음 · 수기 입력이면 안 함)
|
||||
if (!manual.input.checked && !segmentPath(from).length && seg.from && seg.to) void run(false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
* 2열(분류(기준위치 · 거래처) · 항목(손 입력 + 분류 따라 제안 · 244-14) · 거래처 이름 · 목적지) + 소재지(주소 찾기 ·
|
||||
* 다음(카카오) 지도에서 고르기 · `…_UI_Milestone_Place`) · 추가 = [등록] · 상자 = [수정] · [삭제]
|
||||
* 상자 하나 = 항목 하나(149 · [+ 줄] 없음 · 같은 거래처라도 항목마다 따로 등록) · 경로 값은 연결선 모달
|
||||
* 연결(기준점 거침 · 시점으로 바로) = 처음 = [+] 누른 상자 쪽 · 그 뒤 = 다이어그램 연결 점 ● 끌기(154 · 체크 없앰)
|
||||
* 연결(기준점 거침 · 시점으로 바로) = 다이어그램 연결 점 ● 끌기(154 · 155 · 등록 = 상자만 · 선 없음)
|
||||
* 열기 = 다이어그램 [요소 추가](155 · 공사지 · 기준점 [+] 없앰)
|
||||
* 분류 기준위치 = 기준점(하나 · 항목 · 목적지 없음 · 있으면 고르기 막음) · 방위 = 소재지 좌표로 자동 자리
|
||||
* 구간 km · 도로 구분 · 길찾기 = 연결선 모달(`…_UI_Milestone_LegModal`) · [등록] · 소재지 옮김 뒤 그 구간 한 번
|
||||
* 시점(공사지) 상자 = 프로젝트 등록 주소 · VWorld 주소(좌표 → 주소 · 서버) · 아래 지도
|
||||
@@ -84,7 +85,7 @@ function rowField(r: MilestoneRow, kind: "route" | "base") {
|
||||
return { item, dest, note: r.note, setKind };
|
||||
}
|
||||
|
||||
export type PlaceTarget = { add: true; viaBase: boolean } | { add: false; id: string };
|
||||
export type PlaceTarget = { add: true } | { add: false; id: string };
|
||||
|
||||
/** 등록 모달 — 추가([+]) · 고침(거래처 · 기준점 상자) 한 벌 · id "base" = 기준점 */
|
||||
export function openPlaceModal(
|
||||
@@ -97,7 +98,7 @@ export function openPlaceModal(
|
||||
const route = !target.add && !editBase ? data.routes.find((r) => r.id === target.id) : undefined;
|
||||
if (!target.add && !editBase && !route) return;
|
||||
const title = target.add
|
||||
? `항목 추가 — ${target.viaBase ? "기준점 거침" : "공사지로 바로"}`
|
||||
? "요소 추가 — 기준점 · 거래처"
|
||||
: editBase
|
||||
? `기준점 — ${data.base.name || "기준점"}`
|
||||
: `항목 정보 — ${route!.name || "거래처"}`;
|
||||
@@ -178,15 +179,15 @@ export function openPlaceModal(
|
||||
if (moved(where)) segment = r.id;
|
||||
} else {
|
||||
if (!text) return name.setError("거래처 이름을 넣으세요.");
|
||||
const viaBase = target.add && target.viaBase;
|
||||
// 155 등록 = 상자만 · 선은 다이어그램 연결 점 ● 로 이음(이을 때 길찾기)
|
||||
const id = addRoute?.({
|
||||
name: text,
|
||||
via_base: viaBase,
|
||||
via_base: true,
|
||||
linked: false,
|
||||
dir: null,
|
||||
rows: rowValues(),
|
||||
...where,
|
||||
});
|
||||
if (id && where.lon != null) segment = id;
|
||||
}
|
||||
close();
|
||||
if (segment) void findSegmentKm(projectId, segment).then(toastKm);
|
||||
|
||||
@@ -239,6 +239,8 @@ export async function findSegmentKm(
|
||||
image = true,
|
||||
): Promise<string> {
|
||||
const data = liveMilestone(projectId);
|
||||
const owner = from === "base" ? data.base : data.routes.find((r) => r.id === from);
|
||||
if (owner?.manual) return ""; // 155 수기 입력 = 카카오 길찾기 안 함
|
||||
const seg = segmentEnds(data, from, siteInfo()?.start_lonlat ?? null);
|
||||
if (!seg) return "";
|
||||
if (!seg.from || !seg.to) {
|
||||
|
||||
@@ -299,7 +299,7 @@ def test_화면_등록_모달_연결선_모달():
|
||||
assert "길찾기" not in mid.replace("길찾기 없음", "") and "editMap" not in mid
|
||||
assert 'if (from === "start") return openMidLeg(projectId);' in leg
|
||||
assert "void reverseAddress(projectId, lon, lat)" in leg and "void run();" in leg
|
||||
assert "if (!segmentPath(from).length && seg.from && seg.to) void run(false);" in leg
|
||||
assert "if (!manual.input.checked && !segmentPath(from).length && seg.from && seg.to)" in leg
|
||||
for rel in (B08 + "UI_Milestone_Modal.ts", B08 + "UI_Milestone_Place.ts",
|
||||
B08 + "UI_Milestone_LegModal.ts", KMAP, STATE, LAYOUT, CALC,
|
||||
B08 + "UI_Milestone.ts", B08 + "UI_Milestone_Diagram.ts",
|
||||
|
||||
@@ -145,9 +145,9 @@ def test_화면_상자_누름_더하기_창():
|
||||
"openTab" not in ui
|
||||
and "route: (id) => openPlaceModal(projectId, { add: false, id })," in ui
|
||||
)
|
||||
assert 'if (box.kind === "site") g.append(plus(box, false));' in ui
|
||||
assert 'if (box.kind === "base") g.append(plus(box, true));' in ui
|
||||
assert "openPlaceModal(projectId, { add: true, viaBase }, addRoute)" in ui
|
||||
# 155 공사지 · 기준점 [+] 없앰 → 다이어그램 [요소 추가]
|
||||
assert "plus(box" not in ui and 'label: "요소 추가"' in ui
|
||||
assert "openPlaceModal(projectId, { add: true }, addRoute)" in ui
|
||||
modal = (ROOT / "B08_Quantity/B08_Quantity_UI_Milestone_Modal.ts").read_text(encoding="utf-8")
|
||||
assert "openModal({" in modal
|
||||
# 149 상자 하나 = 항목 하나 — [+ 줄] · 같은 이름 합침 없음
|
||||
|
||||
@@ -216,7 +216,7 @@ def test_화면_자리_캡처_키_서버만():
|
||||
assert "sdk.js" in kmap and "?appkey=${encodeURIComponent(key)}&autoload=false" in kmap
|
||||
assert "getDisplayMedia" not in kmap and "[지도 캡처]" not in kmap # 244-11 = 서버 자동
|
||||
leg = _read("B08_Quantity/B08_Quantity_UI_Milestone_LegModal.ts") # 244-13 = 연결선 모달 지도
|
||||
assert "map.root," in leg and "map.set(pins()" in leg
|
||||
assert "mapHead, map.root" in leg and "map.set(pins()" in leg
|
||||
route = _read("B08_Quantity/B08_Quantity_UI_Milestone_Route.ts")
|
||||
assert "routeMapView(projectId, routeId)" in route
|
||||
assert "mapView.draw();" in route
|
||||
|
||||
@@ -119,3 +119,30 @@ def test_154_연결_점_끌어_잇기():
|
||||
)
|
||||
css = _read("B08_Quantity/B08_Quantity_UI_Milestone.css")
|
||||
assert ".b08-milestone__connect {" in css and ".b08-milestone__box.is-drop-target rect {" in css
|
||||
|
||||
|
||||
def test_155_요소_추가_안_이은_거래처_수기_입력():
|
||||
leg = lambda road, km, auto=None: {"road": road, "km": km, "auto_km": auto} # noqa: E731
|
||||
route = {"id": "r", "name": "a", "address": "", "via_base": True, "dir": None, "linked": False,
|
||||
"legs": [leg(None, 5.0)], "rows": [{"item": "장비", "dest": "mid", "note": ""}]} # fmt: skip
|
||||
data = {"site": {"mid_station_m": 700, "mid_road": "비포장"},
|
||||
"base": {"enabled": True, "name": "b", "address": "", "dir": None, "legs": [leg(None, 0.6)]},
|
||||
"routes": [route]} # fmt: skip
|
||||
(a,) = compute_milestone(data, None) # 안 이음 = 구간 km 없음 · 중점 구간만
|
||||
assert (a["s2"], a["s1"], a["un"], a["total"]) == (0, 0, 0.7, 0.7)
|
||||
assert _ts(f"computeMilestone({json.dumps(data)}, null)") == [a]
|
||||
route["linked"] = True
|
||||
(b,) = compute_milestone(data, None)
|
||||
assert (b["s2"], b["s1"], b["total"]) == (5.0, 0.6, 6.3)
|
||||
ui = _read("B08_Quantity/B08_Quantity_UI_Milestone_Diagram.ts")
|
||||
assert "route.linked = true;" in ui and 'label: "요소 추가"' in ui and "plus(box" not in ui
|
||||
modal = _read("B08_Quantity/B08_Quantity_UI_Milestone_Modal.ts")
|
||||
assert "linked: false," in modal and "export type PlaceTarget = { add: true } |" in modal
|
||||
leg_ui = _read("B08_Quantity/B08_Quantity_UI_Milestone_LegModal.ts")
|
||||
assert (
|
||||
'createCheckbox("수기 입력' in leg_ui and "target.manual = manual.input.checked;" in leg_ui
|
||||
)
|
||||
state = _read("B08_Quantity/B08_Quantity_UI_Milestone_State.ts")
|
||||
assert "if (owner?.manual) return" in state # 수기 입력 = 카카오 길찾기 안 함
|
||||
layout = _read("B08_Quantity/B08_Quantity_Milestone_Layout.ts")
|
||||
assert "if (!route || route.linked === false) return null;" in layout
|
||||
|
||||
Reference in New Issue
Block a user