diff --git a/resources/tester/test_sheet_drawing_select.py b/resources/tester/test_sheet_drawing_select.py index 4d43320e..88822d95 100644 --- a/resources/tester/test_sheet_drawing_select.py +++ b/resources/tester/test_sheet_drawing_select.py @@ -19,12 +19,13 @@ OPS = ROOT / "ui_template" / "sheet" / "ui_template_sheet_ops.ts" pytestmark = pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음") SCRIPT = """ -const { navRows, selectionOf } = await import(process.argv[1]); +const { navRows, selectionOf, isBlankPick } = await import(process.argv[1]); const doc = JSON.parse(process.argv[2]); console.log(JSON.stringify({ master: navRows(doc, "master"), project: navRows(doc, "project"), pick: [selectionOf(doc, "s:drawing", "c2"), selectionOf(doc, "d:r1", "c1"), selectionOf(doc, "s:unit", "zz")], + blank: ["s:price", "s:drawing", "s:basis", "s:desc", "d:r1"].map((k) => [isBlankPick(k, { id: "t", 머리: [], 꼴: "글" }), isBlankPick(k, { id: "n", 머리: [], 꼴: "수" })]), })); """ @@ -62,3 +63,9 @@ def test_selection_shape(): {"row": "d:r1", "col": 0, "colId": "c1"}, {"row": "s:unit", "col": -1, "colId": None}, ] + + +def test_text_column_pick_rows_blank(): + assert _run()["blank"] == [ + [True, False], [True, False], [True, False], [False, False], [False, False], + ] # fmt: skip diff --git a/ui_template/sheet/ui_template_sheet.ts b/ui_template/sheet/ui_template_sheet.ts index df3fa706..9b692e7d 100644 --- a/ui_template/sheet/ui_template_sheet.ts +++ b/ui_template/sheet/ui_template_sheet.ts @@ -22,6 +22,7 @@ import { canDeleteRow, deleteColumn, deleteRow, + isBlankPick, KEY_BASIS, KEY_DRAWING, KEY_PRICE, @@ -235,6 +236,7 @@ export function createSheet(host: HTMLElement, input: SheetDoc, opts: SheetOptio const sel = state.sel; const col = sel && colOf(sel.c); if (!sel || !col) return; + if (isBlankPick(sel.r, col)) return; // 글 열은 빈칸 · 잠김 if (opts.onPick && state.mode === "master" && PICK_ROWS.includes(sel.r)) { if (initial === undefined) void pick(sel.r, col.id); // 글자를 쳐서는 안 엶 return; diff --git a/ui_template/sheet/ui_template_sheet_ops.ts b/ui_template/sheet/ui_template_sheet_ops.ts index 02996e43..488b39bb 100644 --- a/ui_template/sheet/ui_template_sheet_ops.ts +++ b/ui_template/sheet/ui_template_sheet_ops.ts @@ -28,6 +28,10 @@ export type MasterRowKey = (typeof MASTER_ROWS)[number]; /** 조회 후 선택 줄 — `onPick` 을 주면 이 줄 칸은 치지 않고 고름. */ export const PICK_ROWS: readonly string[] = [KEY_PRICE, KEY_DRAWING, KEY_BASIS]; +/** 글 열(NO · 측점 · 비고 같은 꼴=글)의 일위대가 · 도면 · 산출근거 칸 — 빈칸 · 잠김. */ +export const isBlankPick = (key: string, col: SheetColumn): boolean => + PICK_ROWS.includes(key) && col.꼴 === "글"; + /** 키보드로 옮겨 다니는 줄 차례(쪽을 가로지름). */ export function navRows(doc: SheetDoc, mode: SheetMode): string[] { const special = mode === "master" ? [KEY_UNIT, ...MASTER_ROWS] : [KEY_UNIT]; diff --git a/ui_template/sheet/ui_template_sheet_render.ts b/ui_template/sheet/ui_template_sheet_render.ts index dc488dc3..1b34465c 100644 --- a/ui_template/sheet/ui_template_sheet_render.ts +++ b/ui_template/sheet/ui_template_sheet_render.ts @@ -14,6 +14,7 @@ import { columnNames, formulaLabel, headMinWidths, textWidth } from "./ui_templa import { cellEditable, isBoundColumn, + isBlankPick, isCalcColumn, KEY_BASIS, KEY_DRAWING, @@ -64,7 +65,7 @@ function headFont(): string { /** 칸을 고칠 수 있나 — 줄 열쇠 기준(머리 칸은 따로) · 도면 · 산출근거 줄은 손으로 못 침. */ export function keyEditable(state: RenderState, key: string, col: SheetColumn): boolean { - if (key === KEY_DRAWING || key === KEY_BASIS) return false; + if (key === KEY_DRAWING || key === KEY_BASIS || isBlankPick(key, col)) return false; if (key.startsWith("s:")) return state.mode === "master"; if (key.startsWith("t:")) return false; const row = state.doc.줄.find((r) => `d:${r.id}` === key); @@ -178,8 +179,10 @@ export function renderSheet(state: RenderState): HTMLElement { )[key]; const tr = el("tr", { className: "ui-sheet__meta", children: [gutter("th", st(label))] }); cols.forEach((col, j) => { - const text = - key === "s:formula" + const blank = isBlankPick(key, col); + const text = blank + ? "" + : key === "s:formula" ? formulaLabel(col.식 ?? "", names, col.id) : key === "s:desc" ? "" @@ -188,7 +191,7 @@ export function renderSheet(state: RenderState): HTMLElement { : (col.일위대가 ?? ""); const td = bodyCell(key, col, j, text); td.classList.remove("is-num"); - if (state.pick && PICK_ROWS.includes(key)) td.classList.add("is-pick"); + if (state.pick && PICK_ROWS.includes(key) && !blank) td.classList.add("is-pick"); if (key === "s:formula" && col.식) { // 같은 종류 열은 짧은 이름 · 풍선은 긴 이름 + 고칠 때 쓰는 id 식 td.textContent = "";