feat(B07): 평면도 관리 모달 오른쪽 CAD 캔버스만 · 확정 풀기 뺌(140-1)
- CAD 싣기 곁값 bare — 제목줄 · 리본 · 패널 · 상태막대 안 그림 · 높이 변수 0 - 모달 [확정 풀기] 지움 · 확정 배지 · [CAD 에서 열기] 그대로 · M02 미리보기 그대로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TNMXVCZXMpHpVvqmFkeChL
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
* [평면도 관리] 모달(PLAN 130-1) — 좌측 패널이 좁아 종류 · 대피소 자리 · 장 보기를 한 창에 모음.
|
||||
*
|
||||
* 왼쪽 = 종류 목록(× 지우기) · 종류 추가 · 업데이트 폼 · 대피소 · 사토장 자리 · 평면도 장 목록
|
||||
* 오른쪽 = 고른 장 미리보기(보기 전용 CAD · 장 바꾸기) · [확정 풀기] · [CAD 에서 열기]
|
||||
* 고치기는 지금 서버 길 그대로(종류 파일 · 확정 풀기) — 고칠 때마다 모달 안을 다시 받고,
|
||||
* 오른쪽 = 고른 장 미리보기(보기 전용 CAD · 캔버스만 `bare`) · 확정 배지 · [CAD 에서 열기]
|
||||
* 고치기는 지금 서버 길 그대로(종류 파일) — 고칠 때마다 모달 안을 다시 받고,
|
||||
* 닫을 때 `onClosed(changed)` 로 좌측 목록 · 도면을 다시 읽음.
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
fetchDesignDrawing,
|
||||
fetchDesignDrawingList,
|
||||
fetchPlanKinds,
|
||||
invalidateDesignDrawing,
|
||||
type CadDrawing,
|
||||
type DesignDrawingItem,
|
||||
type PlanKindsState,
|
||||
@@ -115,7 +114,7 @@ export function openPlanManager(controls: PlanManageControls): void {
|
||||
.querySelectorAll<HTMLElement>(".b07-plan-manage__sheets .b07-drawing-button")
|
||||
.forEach((item) => (item.dataset.active = String(item.dataset.drawingId === picked)));
|
||||
|
||||
/** 장 하나를 미리보기에 — 보기 전용 · 확정이면 [확정 풀기](지금 [수정]과 같은 서버 길). */
|
||||
/** 장 하나를 미리보기에 — 보기 전용 · 확정 풀기는 메인 [수정](140-1). */
|
||||
const show = async (drawing: DesignDrawingItem, label: string): Promise<void> => {
|
||||
picked = drawing.id;
|
||||
markActive();
|
||||
@@ -127,12 +126,6 @@ export function openPlanManager(controls: PlanManageControls): void {
|
||||
const badge = el("span", "b07-plan-manage__badge", response.confirmed ? "확정" : "확정 전");
|
||||
badge.dataset.confirmed = String(response.confirmed);
|
||||
head.append(badge);
|
||||
if (response.confirmed)
|
||||
head.append(
|
||||
button("b07-plan-tools__button", "확정 풀기", () => {
|
||||
void run(() => invalidateDesignDrawing(projectId, drawing.id), edits);
|
||||
}),
|
||||
);
|
||||
head.append(button("b07-plan-tools__button", "CAD 에서 열기", () => finish(drawing.id)));
|
||||
preview.load(
|
||||
response.drawing,
|
||||
@@ -146,6 +139,7 @@ export function openPlanManager(controls: PlanManageControls): void {
|
||||
hostTitle: "평면도 미리보기",
|
||||
ribbonCollapsed: true,
|
||||
panelsCollapsed: true,
|
||||
bare: true,
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
@@ -58,6 +58,10 @@ button {
|
||||
.cad-host-save {
|
||||
--cad-title-height: 0px;
|
||||
}
|
||||
.cad-bare {
|
||||
--cad-title-height: 0px;
|
||||
--cad-status-height: 0px;
|
||||
}
|
||||
.controls {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Ribbon } from '../ribbon/Ribbon';
|
||||
import { StatusBar } from './StatusBar';
|
||||
import { useCadRefresh } from './use-cad-refresh';
|
||||
import { isInspectorCollapsed, isRibbonCollapsed, setInspectorCollapsed } from './ui-state';
|
||||
import { getActiveToolActor } from '../state';
|
||||
import { getActiveToolActor, isBare } from '../state';
|
||||
import type { Tool } from '../tools';
|
||||
import { ViewControls } from './ViewControls';
|
||||
import { DropHint } from './DropHint';
|
||||
@@ -26,21 +26,27 @@ export const Toolbar: FC = () => {
|
||||
const ribbonCollapsed = isRibbonCollapsed();
|
||||
// 좌측 패널 접힘 — 호스트(M02 미리보기)가 접힌 채로 실을 수 있게 ui-state 에 둔다
|
||||
const panelCollapsed = isInspectorCollapsed();
|
||||
// 캔버스만(B07 평면도 관리 모달) — 겉칸을 안 그리고 높이 · 폭 변수를 0 으로
|
||||
const bare = isBare();
|
||||
|
||||
useEffect(() => {
|
||||
// 편 상태의 폭은 App.css의 `--cad-panel-width` 기본값을 쓴다. 여기 숫자를 박아
|
||||
// 두면 스타일에서 넓혀도 이 인라인 값이 덮는다(2026-09-01 실측: 300px 무시됨).
|
||||
if (panelCollapsed) document.documentElement.style.setProperty('--cad-panel-width', '0px');
|
||||
if (panelCollapsed || bare) document.documentElement.style.setProperty('--cad-panel-width', '0px');
|
||||
else document.documentElement.style.removeProperty('--cad-panel-width');
|
||||
document.documentElement.style.setProperty(
|
||||
'--cad-command-height',
|
||||
commandLineVisible ? '86px' : '0px'
|
||||
commandLineVisible && !bare ? '86px' : '0px'
|
||||
);
|
||||
// 리본 접힘 — 탭 줄(26px)만 남기고 패널 줄 자리를 걷는다(`Ribbon.tsx` 가 안 그림).
|
||||
if (ribbonCollapsed) document.documentElement.style.setProperty('--cad-ribbon-height', '26px');
|
||||
if (bare) document.documentElement.style.setProperty('--cad-ribbon-height', '0px');
|
||||
else if (ribbonCollapsed)
|
||||
document.documentElement.style.setProperty('--cad-ribbon-height', '26px');
|
||||
else document.documentElement.style.removeProperty('--cad-ribbon-height');
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
}, [panelCollapsed, commandLineVisible, ribbonCollapsed]);
|
||||
}, [panelCollapsed, commandLineVisible, ribbonCollapsed, bare]);
|
||||
|
||||
if (bare) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
setLayers,
|
||||
setOriginMarker,
|
||||
setViewOnly,
|
||||
setBare,
|
||||
} from '../state.ts';
|
||||
import { setInspectorCollapsed, setRibbonCollapsed } from '../components/ui-state.ts';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -68,6 +69,8 @@ interface DrawingLoadMessage {
|
||||
panelsCollapsed?: boolean;
|
||||
/** 미리보기 — 왼쪽 끌기 = 화면 옮기기 · 두 번 누름 = 전체 맞춤 · 선택 · 명령 안내 없음. */
|
||||
viewOnly?: boolean;
|
||||
/** 캔버스만 — 제목줄 · 리본 · 패널 · 상태막대를 안 그림(B07 평면도 관리 모달). */
|
||||
bare?: boolean;
|
||||
originMarker?: boolean;
|
||||
}
|
||||
|
||||
@@ -227,6 +230,7 @@ export function registerAisloDrawingBridge() {
|
||||
setRibbonCollapsed(event.data.ribbonCollapsed === true);
|
||||
if (event.data.panelsCollapsed) setInspectorCollapsed(true);
|
||||
setViewOnly(event.data.viewOnly === true);
|
||||
setBare(event.data.bare === true);
|
||||
setOriginMarker(event.data.originMarker === true);
|
||||
if (event.data.frameEdit) applyFramePreview();
|
||||
// 앞 도면에서 켜 둔 그리기 도구를 내린다. 안 내리면 **확정한 도면 위에도**
|
||||
|
||||
@@ -7,9 +7,11 @@ import {
|
||||
getEntities,
|
||||
getHighlightedEntityIds,
|
||||
isDrawingDirty,
|
||||
isBare,
|
||||
isDrawingReadOnly,
|
||||
resetUndoBaseline,
|
||||
setActiveLayerId,
|
||||
setBare,
|
||||
setDesignMeta,
|
||||
setEntities,
|
||||
setHighlightedEntityIds,
|
||||
@@ -120,3 +122,23 @@ describe('isDrawingReadOnly', () => {
|
||||
expect(isDrawingReadOnly()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setBare', () => {
|
||||
it('캔버스만 — 켜면 뿌리에 cad-bare(제목줄 · 상태막대 0), 끄면 걷힌다', () => {
|
||||
stubWindow();
|
||||
const classes = new Set<string>();
|
||||
(globalThis as { document?: unknown }).document = {
|
||||
documentElement: {
|
||||
classList: {
|
||||
toggle: (name: string, on: boolean) => (on ? classes.add(name) : classes.delete(name)),
|
||||
},
|
||||
},
|
||||
};
|
||||
setBare(true);
|
||||
expect(isBare()).toBe(true);
|
||||
expect(classes.has('cad-bare')).toBe(true);
|
||||
setBare(false);
|
||||
expect(isBare()).toBe(false);
|
||||
expect(classes.has('cad-bare')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -197,6 +197,8 @@ let viewOnly = false;
|
||||
let originMarker = false;
|
||||
let hostTitle = 'B07 상세 설계';
|
||||
let hostSave = false;
|
||||
/** 캔버스만(B07 평면도 관리 모달) — 제목줄 · 리본 · 패널 · 상태막대를 안 그린다. */
|
||||
let bare = false;
|
||||
|
||||
/**
|
||||
* 실은 뒤로 실제 편집이 있었는가. 도면을 바꾸기 전에 부모가 물어보는 근거다 —
|
||||
@@ -512,6 +514,13 @@ export const setHostSave = (enabled: boolean) => {
|
||||
// 제목 줄이 없어지면 그 높이만큼 위로 당긴다(App.css `.cad-host-save`).
|
||||
document.documentElement.classList.toggle('cad-host-save', enabled);
|
||||
};
|
||||
export const isBare = (): boolean => bare;
|
||||
export const setBare = (enabled: boolean) => {
|
||||
bare = enabled;
|
||||
// 제목 줄 · 상태막대 높이를 걷는다(App.css `.cad-bare`) — 리본 · 패널은 Toolbar 가 0 으로.
|
||||
document.documentElement.classList.toggle('cad-bare', enabled);
|
||||
notifyWindow(HtmlEvent.UPDATE_STATE);
|
||||
};
|
||||
export const getHostTitle = (): string => hostTitle;
|
||||
export const setHostTitle = (title: string) => {
|
||||
hostTitle = title;
|
||||
|
||||
@@ -320,7 +320,7 @@ const { buildDrawingSidePanel } = loadTs(path.join(B07, "B07_DesignDetail_UI_Pan
|
||||
confirms: confirms.length,
|
||||
};
|
||||
|
||||
// 미리보기 장 바꾸기 — 「지형 2장」 → 「노선배치도」(확정 → [확정 풀기])
|
||||
// 미리보기 장 바꾸기 — 「지형 2장」 → 「노선배치도」(확정 배지만 · [확정 풀기] 없음 140-1)
|
||||
const pickSheet = async (id) => {
|
||||
modal.body
|
||||
.querySelectorAll(".b07-plan-manage__sheets .b07-drawing-button")
|
||||
@@ -340,14 +340,6 @@ const { buildDrawingSidePanel } = loadTs(path.join(B07, "B07_DesignDetail_UI_Pan
|
||||
};
|
||||
await pickSheet("plan_k_route");
|
||||
out.routeHead = head().textContent;
|
||||
byText(head(), "BUTTON", "확정 풀기")[0].click();
|
||||
await settle();
|
||||
await settle();
|
||||
out.release = {
|
||||
call: calls.find((c) => c[0] === "invalidate"),
|
||||
head: head().textContent,
|
||||
preview: cad.loads.at(-1).drawing.entities[0].id,
|
||||
};
|
||||
|
||||
// 닫기 — 고친 게 있으니 changed = true · 미리보기 듣기 멈춤
|
||||
modal.opts.beforeClose();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- 좌측 「평면도」 = 장 단추 + [평면도 관리] 하나 · 종류 폼 · 대피소 칸 · × 없음.
|
||||
- 단추 → 공용 모달(큰 창) · 안에 종류 목록 · 종류 폼 · 대피소 · 사토장 자리 · 장 목록 · 첫 장 미리보기(보기 전용).
|
||||
- 종류 추가 · 업데이트(축척 포함) · 지우기 = 지금 서버 길 · 고칠 때마다 모달 안을 다시 받음.
|
||||
- 미리보기 장 바꾸기 · 확정이면 [확정 풀기](invalidate) · 닫으면 changed=True · [CAD 에서 열기] = 그 장 id.
|
||||
- 미리보기 장 바꾸기 · 캔버스만(bare) · 확정 배지만(확정 풀기 없음 140-1) · 닫으면 changed=True · [CAD 에서 열기] = 그 장 id.
|
||||
|
||||
Node 헬퍼 `helper_130_b07_plan_manage.cjs` 가 화면 그릇 흉내로 돌림. 화면은 사용자 확인.
|
||||
"""
|
||||
@@ -54,6 +54,7 @@ def test_첫_장_미리보기는_보기_전용(out):
|
||||
assert out["open"]["preview"] == "plan_k_terrain"
|
||||
extra = out["open"]["extra"]
|
||||
assert extra["readOnly"] is True and extra["viewOnly"] is True
|
||||
assert extra["bare"] is True # 140-1 캔버스만(제목줄 · 리본 · 상태막대 없음)
|
||||
assert extra["recoveryScope"] == "b07-plan-preview" # 본 CAD 자동백업 칸과 안 겹침
|
||||
|
||||
|
||||
@@ -82,12 +83,10 @@ def test_미리보기_장_바꾸기(out):
|
||||
assert "확정 전" in s2["head"] and "확정 풀기" not in s2["head"]
|
||||
|
||||
|
||||
def test_확정이면_확정_풀기(out):
|
||||
assert "확정 풀기" in out["routeHead"]
|
||||
rel = out["release"]
|
||||
assert rel["call"] == ["invalidate", "plan_k_route"]
|
||||
assert "확정 풀기" not in rel["head"]
|
||||
assert rel["preview"] == "plan_k_route" # 보던 장 그대로
|
||||
def test_확정이면_배지만(out):
|
||||
# 140-1 확정 풀기는 메인 [수정] — 모달엔 배지 · [CAD 에서 열기]만
|
||||
assert "확정" in out["routeHead"] and "CAD 에서 열기" in out["routeHead"]
|
||||
assert "확정 풀기" not in out["routeHead"]
|
||||
|
||||
|
||||
def test_닫으면_좌측_다시_읽기_신호(out):
|
||||
|
||||
@@ -77,6 +77,8 @@ export interface CadLoadExtra {
|
||||
panelsCollapsed?: boolean;
|
||||
/** 미리보기 — 왼쪽 끌기 = 화면 옮기기 · 두 번 누름 = 전체 맞춤 · 선택 · 명령 안내 없음. */
|
||||
viewOnly?: boolean;
|
||||
/** 캔버스만 — 제목줄 · 리본 · 패널 · 상태막대를 안 그린다(B07 평면도 관리 모달). */
|
||||
bare?: boolean;
|
||||
/** 좌표 0,0 에 기준점 십자를 그린다(그리기 겹판 · 저장 안 됨) — 안 보내면 없음. */
|
||||
originMarker?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user