fix(M01): 흐름도 패널 글 · 왼쪽 고침 → 오른쪽 따라감 · 시험판 길 지움

- 패널 위 글 「이 로직의 계산 방법을 흐름도로 보여 줌」(「옛 식」 · 「정본」 말 지움)
- 왼쪽 편집기로 고친 뒤 잠시 쉬면 고친 줄을 서버 변환(POST /api/m01/logic/flow {file, key, row})으로 다시 받아 오른쪽에 넣음 · 마지막 물음만 받음 · 길이 아직 없으면 아무 일 없음
- 다른 로직 받기에서 흐름도 시험판(DF-) cfGet 길 지움

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
This commit is contained in:
2026-10-02 07:43:09 +09:00
co-authored by Claude Opus 5.5
parent d202a3a6d8
commit 45b614ca55
2 changed files with 51 additions and 10 deletions
+25 -5
View File
@@ -43,6 +43,7 @@ import {
emptyFlow,
examplesOf,
fetchFlow,
fetchFlowFor,
sameShape,
withExamples,
mountLogicFlow,
@@ -78,9 +79,11 @@ interface Opened extends Draft {
values: Record<string, string>;
/** 흐름 로직의 왼쪽 「지금 내용」 자리 — 흐름도 왼쪽 보기가 그림 */
flowHost: HTMLElement;
/** 오른쪽 흐름도의 기준(예시값만 다른지 견줄 때) */
flowBase?: CfLogic;
}
/** 줄의 흐름(있으면 흐름도가 정본) */
/** 줄의 흐름(있으면 흐름도로 셈) */
const flowOf = (row: LogicRow | null): CfLogic | null => (row?.흐름 as CfLogic | undefined) ?? null;
const OWN_FILE = "로직_자체.json";
@@ -165,6 +168,7 @@ export async function mountM01LogicLab(
if (opened.origKey !== null && now === opened.original) delete drafts[opened.id];
else drafts[opened.id] = pick(opened, clone(opened.row));
persist();
if (!flowOf(opened.row)) scheduleFlow(opened); // 왼쪽 편집기로 고침 — 오른쪽 흐름도도 따라감
const inputs = JSON.stringify(opened.row.입력 ?? []);
if (inputs !== calcInputs) drawCalc();
if (isOwnLogic(opened.row)) {
@@ -241,6 +245,22 @@ export async function mountM01LogicLab(
flowNow?.redrawLeft();
};
/** 왼쪽 고침 뒤 잠시 쉬면 고친 줄을 서버가 흐름도로 바꿔 줌 → 오른쪽에 넣음 · 마지막 물음만 받음 */
let flowTimer: number | undefined;
let flowSeq = 0;
const scheduleFlow = (o: Opened): void => {
window.clearTimeout(flowTimer);
flowTimer = window.setTimeout(() => {
const seq = ++flowSeq;
if (!o.row) return;
void fetchFlowFor(o.row, o.origKey ?? "", o.file).then((got) => {
if (!got || seq !== flowSeq || opened !== o || !flowNow || flowOf(o.row)) return;
o.flowBase = withExamples(got.flow, o.values);
flowNow.set(clone(o.flowBase));
});
}, 700);
};
/** 오른쪽 흐름도 — 줄의 흐름 · 없으면 서버 변환(흐름 받기) · 그것도 없으면 빈 흐름 */
const startFlow = async (o: Opened): Promise<void> => {
const row = o.row;
@@ -249,7 +269,7 @@ export async function mountM01LogicLab(
const own = flowOf(row);
const got = own || o.origKey === null ? null : await fetchFlow(o.origKey, o.file);
// 시험 입력 한 벌 — 열 때 왼쪽 시험 계산 입력을 흐름 변수 예시값으로
let base = withExamples(
o.flowBase = withExamples(
own ?? got?.flow ?? (await emptyFlow(row.이름, row.결과단위)),
o.values,
);
@@ -257,7 +277,7 @@ export async function mountM01LogicLab(
try {
const made = await mountLogicFlow({
split,
flow: clone(base),
flow: clone(o.flowBase),
title: row.이름 || row.키,
readOnly: !admin,
notes: got?.notes ?? [],
@@ -266,9 +286,9 @@ export async function mountM01LogicLab(
onChange: (lg) => {
if (!o.row || opened !== o) return;
const was = flowOf(o.row);
if (sameShape(lg, was ?? base)) {
if (sameShape(lg, was ?? o.flowBase ?? lg)) {
// 예시값만 바뀜 — 고친 것 아님 · 왼쪽 시험 계산 입력에 같은 이름으로 넣고 다시 셈
base = lg;
o.flowBase = lg;
syncLeft(o, examplesOf(lg));
return;
}