From 84095ace3b4e59b69f142a509cadd2555024fbac Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Thu, 11 Dec 2025 13:05:12 +0900 Subject: [PATCH] =?UTF-8?q?feat(button-actions):=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?=ED=9B=84=20=EB=85=B8=EB=93=9C=20=ED=94=8C=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20RepeatScreenModal=20props=20=EC=88=98=EC=8B=A0=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dataflowConfig.flowConfig 설정 시 저장 완료 후 노드 플로우 자동 실행 - executeNodeFlow API 동적 import로 번들 최적화 - RepeatScreenModal에서 _groupedData props 수신 지원 추가 - tiptap 라이브러리 버전 업그레이드 (2.11.5 → 2.27.1) --- .../RepeatScreenModalComponent.tsx | 27 +++++----- frontend/lib/utils/buttonActions.ts | 49 +++++++++++++++++++ frontend/package-lock.json | 41 +++++++++------- frontend/package.json | 9 ++-- 4 files changed, 92 insertions(+), 34 deletions(-) diff --git a/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx b/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx index 662dacea..980bbfe9 100644 --- a/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx +++ b/frontend/lib/registry/components/repeat-screen-modal/RepeatScreenModalComponent.tsx @@ -55,7 +55,8 @@ export function RepeatScreenModalComponent({ ...props }: RepeatScreenModalComponentProps) { // props에서도 groupedData를 추출 (DynamicWebTypeRenderer에서 전달될 수 있음) - const groupedData = propsGroupedData || (props as any).groupedData; + // DynamicComponentRenderer에서는 _groupedData로 전달됨 + const groupedData = propsGroupedData || (props as any).groupedData || (props as any)._groupedData; const componentConfig = { ...config, ...component?.config, @@ -691,7 +692,7 @@ export function RepeatScreenModalComponent({ for (const tableRow of tableRowsWithExternalSource) { const key = `${card._cardId}-${tableRow.id}`; - // 🆕 v3.7: 삭제된 행은 집계에서 제외 + // 🆕 v3.7: 삭제된 행은 집계에서 제외 const rows = (extData[key] || []).filter((row) => !row._isDeleted); externalRowsByTableId[tableRow.id] = rows; allExternalRows.push(...rows); @@ -1183,19 +1184,19 @@ export function RepeatScreenModalComponent({ console.log(`[RepeatScreenModal] DELETE 성공: ${targetTable}, id=${targetRow._originalData.id}`); // 성공 시 UI에서 완전히 제거 - setExternalTableData((prev) => { - const newData = { - ...prev, + setExternalTableData((prev) => { + const newData = { + ...prev, [key]: prev[key].filter((row) => row._rowId !== rowId), - }; - + }; + // 행 삭제 시 집계 재계산 - setTimeout(() => { - recalculateAggregationsWithExternalData(newData); - }, 0); - - return newData; - }); + setTimeout(() => { + recalculateAggregationsWithExternalData(newData); + }, 0); + + return newData; + }); } catch (error: any) { console.error(`[RepeatScreenModal] DELETE 실패:`, error.response?.data || error.message); // 에러 시에도 다이얼로그 닫기 diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index 02168e8f..1ced2836 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -2651,6 +2651,55 @@ export class ButtonActionExecutor { controlDataSource, }; + // 노드 플로우 방식 실행 (flowConfig가 있는 경우) + const hasFlowConfig = config.dataflowConfig?.flowConfig && config.dataflowConfig.flowConfig.flowId; + if (hasFlowConfig) { + console.log("🎯 저장 후 노드 플로우 실행:", config.dataflowConfig.flowConfig); + + const { flowId } = config.dataflowConfig.flowConfig; + + try { + // 노드 플로우 실행 API 호출 + const { executeNodeFlow } = await import("@/lib/api/nodeFlows"); + + // 데이터 소스 준비 + let sourceData: any = context.formData || {}; + + // repeat-screen-modal 데이터가 있으면 병합 + const repeatScreenModalKeys = Object.keys(context.formData || {}).filter((key) => + key.startsWith("_repeatScreenModal_"), + ); + if (repeatScreenModalKeys.length > 0) { + console.log("📦 repeat-screen-modal 데이터 발견:", repeatScreenModalKeys); + } + + console.log("📦 노드 플로우에 전달할 데이터:", { + flowId, + dataSourceType: controlDataSource, + sourceData, + }); + + const result = await executeNodeFlow(flowId, { + dataSourceType: controlDataSource, + sourceData, + context: extendedContext, + }); + + if (result.success) { + console.log("✅ 저장 후 노드 플로우 실행 완료:", result); + toast.success("제어 로직 실행이 완료되었습니다."); + } else { + console.error("❌ 저장 후 노드 플로우 실행 실패:", result); + toast.error("저장은 완료되었으나 제어 실행 중 오류가 발생했습니다."); + } + } catch (error: any) { + console.error("❌ 저장 후 노드 플로우 실행 오류:", error); + toast.error(`제어 실행 오류: ${error.message || "알 수 없는 오류"}`); + } + + return; // 노드 플로우 실행 후 종료 + } + // 관계 기반 제어 실행 if (config.dataflowConfig?.controlMode === "relationship" && config.dataflowConfig?.relationshipConfig) { console.log("🔗 저장 후 관계 기반 제어 실행:", config.dataflowConfig.relationshipConfig); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 845a09f7..6c2ec5f0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -34,10 +34,11 @@ "@react-three/fiber": "^9.4.0", "@tanstack/react-query": "^5.86.0", "@tanstack/react-table": "^8.21.3", - "@tiptap/extension-placeholder": "^2.11.5", + "@tiptap/core": "^3.13.0", + "@tiptap/extension-placeholder": "^2.27.1", "@tiptap/pm": "^2.11.5", - "@tiptap/react": "^2.11.5", - "@tiptap/starter-kit": "^2.11.5", + "@tiptap/react": "^2.27.1", + "@tiptap/starter-kit": "^2.27.1", "@turf/buffer": "^7.2.0", "@turf/helpers": "^7.2.0", "@turf/intersect": "^7.2.0", @@ -3301,16 +3302,16 @@ } }, "node_modules/@tiptap/core": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.1.tgz", - "integrity": "sha512-nkerkl8syHj44ZzAB7oA2GPmmZINKBKCa79FuNvmGJrJ4qyZwlkDzszud23YteFZEytbc87kVd/fP76ROS6sLg==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.13.0.tgz", + "integrity": "sha512-iUelgiTMgPVMpY5ZqASUpk8mC8HuR9FWKaDzK27w9oWip9tuB54Z8mePTxNcQaSPb6ErzEaC8x8egrRt7OsdGQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/pm": "^2.7.0" + "@tiptap/pm": "^3.13.0" } }, "node_modules/@tiptap/extension-blockquote": { @@ -3699,6 +3700,19 @@ "url": "https://github.com/sponsors/ueberdosis" } }, + "node_modules/@tiptap/starter-kit/node_modules/@tiptap/core": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.27.1.tgz", + "integrity": "sha512-nkerkl8syHj44ZzAB7oA2GPmmZINKBKCa79FuNvmGJrJ4qyZwlkDzszud23YteFZEytbc87kVd/fP76ROS6sLg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^2.7.0" + } + }, "node_modules/@turf/along": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/along/-/along-7.2.0.tgz", @@ -6070,7 +6084,7 @@ "version": "20.19.24", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -6108,7 +6122,7 @@ "version": "19.2.2", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", - "devOptional": true, + "dev": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.2.0" @@ -12524,13 +12538,6 @@ "react-dom": ">=16" } }, - "node_modules/react-is": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", - "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", - "license": "MIT", - "peer": true - }, "node_modules/react-leaflet": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz", @@ -14190,7 +14197,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/unrs-resolver": { diff --git a/frontend/package.json b/frontend/package.json index d5ac5f5a..2549a177 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,10 +16,6 @@ "test:dataflow": "jest lib/services/__tests__/buttonDataflowPerformance.test.ts" }, "dependencies": { - "@tiptap/extension-placeholder": "^2.11.5", - "@tiptap/pm": "^2.11.5", - "@tiptap/react": "^2.11.5", - "@tiptap/starter-kit": "^2.11.5", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", @@ -46,6 +42,11 @@ "@react-three/fiber": "^9.4.0", "@tanstack/react-query": "^5.86.0", "@tanstack/react-table": "^8.21.3", + "@tiptap/core": "^3.13.0", + "@tiptap/extension-placeholder": "^2.27.1", + "@tiptap/pm": "^2.11.5", + "@tiptap/react": "^2.27.1", + "@tiptap/starter-kit": "^2.27.1", "@turf/buffer": "^7.2.0", "@turf/helpers": "^7.2.0", "@turf/intersect": "^7.2.0",