chore(M02): 임시 시험 단추 호출부 · inspect 옵션 · 시험 정리(이어서)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0168FQuoV7vDh5nhnSowW5cp
This commit is contained in:
2026-09-28 00:13:19 +09:00
co-authored by Claude Sonnet 5
parent 860e251425
commit 66812026c1
5 changed files with 2 additions and 82 deletions
-12
View File
@@ -51,16 +51,6 @@ export interface SpreadsheetOptions {
onChange?: (book: Workbook) => void;
/** 고름이 바뀜 — 시트 id · 활성 칸 A1 · 범위 A1 */
onSelect?: (selection: { 시트: string; 칸: string; 범위: string }) => void;
/** ⚠ 임시 — 브레인 브라우저 검증용: 문맥을 `window.__aisloSheet` 에 걺(book · 고름 · 명령 읽기).
* M02 [스프레드시트 시험] 단추만 켬 · 산출근거 카드는 안 켬 · 1단계 검증 뒤 지움. */
inspect?: boolean;
}
declare global {
interface Window {
/** ⚠ 임시 — `inspect` 로 연 표의 문맥(브레인 검증용) */
__aisloSheet?: SpreadsheetContext;
}
}
export interface SpreadsheetHandle {
@@ -144,7 +134,6 @@ export function createSpreadsheet(
grid.render();
select(ctx.selection);
if (opts.inspect) window.__aisloSheet = ctx; // ⚠ 임시 — 브레인 검증용
function notify(message: string): void {
toast.textContent = message;
@@ -252,7 +241,6 @@ export function createSpreadsheet(
return ctx.engine.snapshot();
},
destroy() {
if (window.__aisloSheet === ctx) delete window.__aisloSheet;
clearTimeout(toastTimer);
detachKeys();
detachMouse();
@@ -118,11 +118,6 @@ export const createStructure = (column: string): Promise<TemplateDoc> =>
export const fetchStructureNumbers = (): Promise<Record<string, string>> =>
call("/structures/numbers");
/* --- ⚠ 임시 — [스프레드시트 시험] 단추(1단계 검증 뒤 지움) · 저장 자리 = 서버 tmp 견본 --- */
export const readSpreadsheetTrial = (): Promise<{ 문서: unknown }> => call("/spreadsheet-trial");
export const saveSpreadsheetTrial = (문서: unknown): Promise<{ 문서: unknown }> =>
call("/spreadsheet-trial", { method: "PUT", body: JSON.stringify({ 문서 }) });
/* --- 프로젝트 층 단추 다섯 --- */
const project = (id: string, tail: string): string => `/projects/${enc(id)}/templates/${tail}`;
const post = (path: string, body: object = {}): Promise<unknown> =>
@@ -5,15 +5,11 @@
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from common_util import common_util_spreadsheet as spreadsheet
from common_util.common_util_json import atomic_write_json
from M02_MasterTemplete import M02_MasterTemplete_Store as store
router = APIRouter(prefix="/api/m02", tags=["M02 MasterTemplete"])
@@ -61,34 +57,3 @@ def put_template(kind: str, name: str, body: SaveBody) -> dict:
def delete_template(kind: str, name: str, 판: str | None = None) -> dict:
_call(store.delete, kind, name, 판)
return {"ok": True}
# ── ⚠ 임시(스프레드시트 시험 단추 · 사용자 지시 · 1단계 검증 뒤 지움) ──────────
# 저장 자리 = `tmp/spreadsheet_trial.json`(git 밖) · 없으면 시트 셋 빈 통합문서.
TRIAL_PATH = Path(__file__).resolve().parent.parent / "tmp" / "spreadsheet_trial.json"
def _trial_doc() -> dict[str, Any]:
sheets = [{"id": f"s{i}", "이름": f"시트{i}", "칸": {}} for i in (1, 2, 3)]
return {"종류": "통합문서", "판": 1, "열": "시험", "서식": [{}], "시트": sheets, "활성": "s1"}
@router.get("/spreadsheet-trial")
def get_spreadsheet_trial() -> dict:
if not TRIAL_PATH.is_file():
return {"문서": _trial_doc()}
return {"문서": json.loads(TRIAL_PATH.read_text(encoding="utf-8"))}
class TrialBody(BaseModel):
문서: dict[str, Any]
@router.put("/spreadsheet-trial")
def put_spreadsheet_trial(body: TrialBody) -> dict:
try:
doc = spreadsheet.with_server_values(body.문서)
except spreadsheet.RecalcError as e:
raise HTTPException(status_code=503, detail=str(e)) from e
atomic_write_json(TRIAL_PATH, doc)
return {"문서": doc}
@@ -22,9 +22,6 @@ import {
type StructureColumn,
type StructurePanelHandle,
} from "./M02_MasterTemplete_Structure";
// ⚠ 임시 — [스프레드시트 시험] 단추(1단계 검증 뒤 지움)
import { mountSpreadsheetTrial } from "./M02_MasterTemplete_Spreadsheet_Trial";
export interface Selection {
layer: Layer;
projectId: string | null;
@@ -81,9 +78,6 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
const title = el("h2", { className: "m02-main__title", text: L("M02_PickTemplate") });
const reload = createButton({ label: L("M02_Reload"), variant: "ghost" });
const save = createButton({ label: L("M02_Save"), variant: "filled" });
// ⚠ 임시 — [스프레드시트 시험] 단추(사용자 지시 · 1단계 검증 뒤 지움)
const trial = createButton({ label: "스프레드시트 시험", variant: "ghost" });
trial.hidden = !isAdmin;
const slot = el("div", { className: "m02-main__slot" }); // 도면 양식의 작도 영역 칸이 들어옴
const notice = el("div", { className: "m02-main__notice", attrs: { hidden: "" } });
const host = el("div", { className: "m02-main__host" });
@@ -91,7 +85,7 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
const root = el("div", {
className: "m02-main",
children: [
el("div", { className: "m02-main__head", children: [title, slot, reload, save, trial] }),
el("div", { className: "m02-main__head", children: [title, slot, reload, save] }),
notice,
host,
extra,
@@ -276,18 +270,6 @@ export function createMain(isAdmin: boolean, onSaved?: () => void): MainHandle {
}
save.addEventListener("click", () => void doSave());
// ⚠ 임시 — [스프레드시트 시험] 빈 통합문서(시트 셋)를 메인 칸에 넓게 엶 · 저장은 서버 tmp 견본 자리
trial.addEventListener("click", async () => {
if (!(await confirmLeave())) return;
seq += 1;
dirty = false;
drop();
showNotice([]);
sel = null;
bar();
title.textContent = "스프레드시트 시험";
editor = mountSpreadsheetTrial(host, (d) => (dirty = d));
});
reload.addEventListener("click", async () => {
if (sel && (await confirmLeave())) void open(sel);
});
@@ -1,4 +1,4 @@
"""F — 산출근거 저장(basis 종류) · 옛 산출근거 옮김 · [저장] 때 서버 계산값 · 임시 시험 주소.
"""F — 산출근거 저장(basis 종류) · 옛 산출근거 옮김 · [저장] 때 서버 계산값.
서버 Node 풀이는 `test_spreadsheet_node.py` 가 따로 봄 — 여기는 `with_server_values` 를 바꿔 끼워
「브라우저 값은 버리고 서버 값만 적는다」 · 「못 풀면 저장을 막는다」 만 잼.
@@ -26,7 +26,6 @@ def client(tmp_path, monkeypatch):
(tmp_path / kind).mkdir()
shutil.copy(REAL / "table/구조물집계표.json", tmp_path / "table")
monkeypatch.setattr(store, "FOLDER", tmp_path)
monkeypatch.setattr(router_module, "TRIAL_PATH", tmp_path / "trial.json")
def fake(book):
clean = {k: v for k, v in book.items() if k != "계산값"}
@@ -127,12 +126,3 @@ def test_층_규칙과_프로젝트_복사(client, tmp_path, monkeypatch):
monkeypatch.setattr(layers, "SYSTEM_ROOT", tmp_path)
copied = layers.seed_project(tmp_path / "project")
assert "basis/rv" in copied["작업본"] and "basis/rv" in copied["초기"]
def test_임시_시험_주소(client):
first = client.get("/api/m02/spreadsheet-trial").json()["문서"]
assert [s["이름"] for s in first["시트"]] == ["시트1", "시트2", "시트3"]
first["시트"][0]["칸"] = {"A1": {"식": "1+41"}}
saved = client.put("/api/m02/spreadsheet-trial", json={"문서": first}).json()["문서"]
assert saved["계산값"] == SERVER
assert client.get("/api/m02/spreadsheet-trial").json()["문서"] == saved