From f2052b12d30c577d2c92c16c345e191530507609 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 21 Sep 2026 09:40:33 +0900 Subject: [PATCH] =?UTF-8?q?feat(M01):=20=ED=9D=90=EB=A6=84=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=BC=EC=97=90=EC=84=9C=20=E3=80=8C=EB=B3=B8=EB=96=A0=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0=E3=80=8D=20=EB=A1=9C=20=EC=9E=90?= =?UTF-8?q?=EC=B2=B4=20=EB=A1=9C=EC=A7=81=20=EB=A7=8C=EB=93=A4=EC=96=B4=20?= =?UTF-8?q?=EA=B3=A0=EC=B9=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 정본 로직 상자 위 [본떠 만들기] 가 `POST /logic/copy`(계약 5장)를 불러 자체 로직(`GX…`)을 만들고 그 줄을 바로 엶 — 거기서 [고치기] 가 열림. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PAdA5ThqmtVSsbzjusk1cJ --- M01_MasterData/M01_MasterData_UI_Logic_Api.ts | 6 ++++++ M01_MasterData/M01_MasterData_UI_Logic_Flow.ts | 5 ++++- M01_MasterData/M01_MasterData_UI_Logic_Page.ts | 18 ++++++++++++++++++ M01_MasterData/M01_MasterData_UI_Logic_Text.ts | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Api.ts b/M01_MasterData/M01_MasterData_UI_Logic_Api.ts index fb180409..8d4d8356 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Api.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_Api.ts @@ -186,3 +186,9 @@ export const runCalc = (body: { export const saveFiles = ( files: SaveFile[], ): Promise<{ files: { file: string; version: string }[] }> => request("/save", { files }); + +/** 본떠 만들기 — 정본·자체 둘 다 본뜸 · 새 키(`GX…`)는 서버가 줌(계약 5장) */ +export const copyLogic = ( + key: string, +): Promise<{ file: string; version: string; key: string; logic: LogicRow }> => + request("/logic/copy", { key }); diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Flow.ts b/M01_MasterData/M01_MasterData_UI_Logic_Flow.ts index 80df10cc..8f31326e 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Flow.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_Flow.ts @@ -32,7 +32,10 @@ import "./M01_MasterData_UI_Logic_Flow_Style.css"; const title = (kind: FlowKind): string => tx(`Col_${kind}` as TextKey); -/** 자체 로직인지 — 자체 파일이거나 키가 `GX…` · 아직 저장 안 한 새 줄(키 "")도 고칠 수 있음 */ +/** + * 자체 로직인지 — 자체 파일(`로직_자체.json`)이거나 키가 `GX…`(계약 5장). + * 아직 저장 안 한 새 줄(키 "")도 고칠 수 있음 · 정본은 「본떠 만들기」 뒤에야 고침. + */ export const isOwnLogic = (file: string, row: LogicRow): boolean => file.startsWith("로직_자체") || (row.키 ?? "").startsWith("GX") || (row.키 ?? "") === ""; diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Page.ts b/M01_MasterData/M01_MasterData_UI_Logic_Page.ts index b3ca491d..01b7d9b9 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Page.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_Page.ts @@ -18,6 +18,7 @@ import { } from "@ui/ui_template_elements"; import { ApiError, + copyLogic, fetchLogic, fetchLogicFiles, fetchLogics, @@ -195,6 +196,7 @@ export async function mountM01Logic( row: shown, editable: isOwnLogic(current.file, shown), onChange: touch, + onCopy: () => void onCopy(current), }); return; } @@ -320,6 +322,22 @@ export async function mountM01Logic( show(next); }; + /** 「본떠 만들기」 — 정본을 자체 파일로 복제하고(계약 5장) 그 새 로직을 바로 엶 */ + const onCopy = async (from: Opened): Promise => { + if (!from.origKey) return; + showLoadingOverlay(); + try { + const made = await copyLogic(from.origKey); + await reload(); + showToast(tx("Edit_Copied", { v: made.key }), "success"); + await open(logicId("자체", made.key), "자체", made.key); + } catch (error) { + failed(error); + } finally { + hideLoadingOverlay(); + } + }; + const onDelete = async (): Promise => { if (!opened?.row) return; if ( diff --git a/M01_MasterData/M01_MasterData_UI_Logic_Text.ts b/M01_MasterData/M01_MasterData_UI_Logic_Text.ts index 615687bd..a727482f 100644 --- a/M01_MasterData/M01_MasterData_UI_Logic_Text.ts +++ b/M01_MasterData/M01_MasterData_UI_Logic_Text.ts @@ -134,6 +134,7 @@ const TEXT = { "Master logics are read-only here — use “Copy as mine” first", ], Edit_Copy: ["본떠 만들기", "Copy as mine"], + Edit_Copied: ["내 로직 「{v}」 을 만들었음 — 여기서 고치면 됨", "Made your logic “{v}”"], Edit_CopySoon: [ "복제 길(API)이 아직 없음 — 서버가 준비되면 여기서 바로 됨", "The copy API is not ready yet",