From 536a975dc72c3db240738f5a56a1035f2026dfac Mon Sep 17 00:00:00 2001 From: hyeonsu Date: Wed, 17 Sep 2025 10:08:20 +0900 Subject: [PATCH] =?UTF-8?q?=EC=99=B8=EB=B6=80=20=ED=98=B8=EC=B6=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EA=B0=9C=EC=84=A0:=20API=20=EC=A2=85?= =?UTF-8?q?=EB=A5=98=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=AC=EB=9E=99?= =?UTF-8?q?,=20=EC=B9=B4=EC=B9=B4=EC=98=A4=ED=86=A1,=20=EB=94=94=EC=8A=A4?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=84=EC=9A=A9=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80.=20ConnectionSetupModal?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=84=A4=EC=A0=95=20=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dataflow/ConnectionSetupModal.tsx | 67 ++-- .../connection/ExternalCallSettings.tsx | 307 +++++++++++------- frontend/types/connectionTypes.ts | 18 +- 3 files changed, 251 insertions(+), 141 deletions(-) diff --git a/frontend/components/dataflow/ConnectionSetupModal.tsx b/frontend/components/dataflow/ConnectionSetupModal.tsx index 8cb2c831..d00b2068 100644 --- a/frontend/components/dataflow/ConnectionSetupModal.tsx +++ b/frontend/components/dataflow/ConnectionSetupModal.tsx @@ -87,13 +87,17 @@ export const ConnectionSetupModal: React.FC = ({ } else if (connectionType === "data-save") { // data-save 설정 로드 - 안전하게 처리 (다양한 구조 지원) let actionsData: Record[] = []; + const settingsRecord = settings as Record; - if (Array.isArray((settings as any).actions)) { + if (Array.isArray(settingsRecord.actions)) { // 직접 actions 배열이 있는 경우 - actionsData = (settings as any).actions; - } else if ((settings as any).plan && Array.isArray((settings as any).plan.actions)) { + actionsData = settingsRecord.actions as Record[]; + } else if (settingsRecord.plan && typeof settingsRecord.plan === "object" && settingsRecord.plan !== null) { // plan 객체 안에 actions가 있는 경우 - actionsData = (settings as any).plan.actions; + const planRecord = settingsRecord.plan as Record; + if (Array.isArray(planRecord.actions)) { + actionsData = planRecord.actions as Record[]; + } } else if (Array.isArray(settings)) { // settings 자체가 actions 배열인 경우 actionsData = settings as Record[]; @@ -130,26 +134,34 @@ export const ConnectionSetupModal: React.FC = ({ }); // control 설정도 로드 (전체 실행 조건) - if ( - (settings as any).control && - (settings as any).control.conditionTree && - Array.isArray((settings as any).control.conditionTree) - ) { - const conditionTree = (settings as any).control.conditionTree as ConditionNode[]; - setConditions( - conditionTree.map((condition) => ({ - ...condition, - operator: condition.operator || "=", // 기본값 보장 - })), - ); + if (settingsRecord.control && typeof settingsRecord.control === "object" && settingsRecord.control !== null) { + const controlRecord = settingsRecord.control as Record; + if (Array.isArray(controlRecord.conditionTree)) { + const conditionTree = controlRecord.conditionTree as ConditionNode[]; + setConditions( + conditionTree.map((condition) => ({ + ...condition, + operator: condition.operator || "=", // 기본값 보장 + })), + ); + } } } else if (connectionType === "external-call") { setExternalCallSettings({ - callType: (settings.callType as "rest-api" | "webhook") || "rest-api", + callType: (settings.callType as "rest-api" | "email" | "ftp" | "queue") || "rest-api", apiUrl: (settings.apiUrl as string) || "", httpMethod: (settings.httpMethod as "GET" | "POST" | "PUT" | "DELETE") || "POST", headers: (settings.headers as string) || "{}", bodyTemplate: (settings.bodyTemplate as string) || "{}", + // 새로운 필드들도 로드 + apiType: (settings.apiType as "slack" | "kakao-talk" | "discord" | "generic") || "generic", + slackWebhookUrl: (settings.slackWebhookUrl as string) || "", + slackChannel: (settings.slackChannel as string) || "", + slackMessage: (settings.slackMessage as string) || "", + kakaoAccessToken: (settings.kakaoAccessToken as string) || "", + kakaoMessage: (settings.kakaoMessage as string) || "", + discordWebhookUrl: (settings.discordWebhookUrl as string) || "", + discordMessage: (settings.discordMessage as string) || "", }); } }, @@ -515,13 +527,24 @@ export const ConnectionSetupModal: React.FC = ({ switch (externalCallSettings.callType) { case "rest-api": - return !externalCallSettings.apiUrl?.trim(); - case "kakao-talk": - return !externalCallSettings.kakaoAccessToken?.trim() || !externalCallSettings.bodyTemplate?.trim(); + // REST API의 경우 apiType에 따라 다른 검증 + switch (externalCallSettings.apiType) { + case "slack": + return !externalCallSettings.slackWebhookUrl?.trim() || !externalCallSettings.slackMessage?.trim(); + case "kakao-talk": + return !externalCallSettings.kakaoAccessToken?.trim() || !externalCallSettings.kakaoMessage?.trim(); + case "discord": + return !externalCallSettings.discordWebhookUrl?.trim() || !externalCallSettings.discordMessage?.trim(); + case "generic": + default: + return !externalCallSettings.apiUrl?.trim(); + } case "email": return !externalCallSettings.apiUrl?.trim(); // 이메일 서버 URL 필요 - case "webhook": - return !externalCallSettings.apiUrl?.trim(); + case "ftp": + return !externalCallSettings.apiUrl?.trim(); // FTP 서버 URL 필요 + case "queue": + return !externalCallSettings.apiUrl?.trim(); // 큐 서버 URL 필요 default: return true; } diff --git a/frontend/components/dataflow/connection/ExternalCallSettings.tsx b/frontend/components/dataflow/connection/ExternalCallSettings.tsx index f919ad6c..f320585d 100644 --- a/frontend/components/dataflow/connection/ExternalCallSettings.tsx +++ b/frontend/components/dataflow/connection/ExternalCallSettings.tsx @@ -27,7 +27,7 @@ export const ExternalCallSettings: React.FC = ({ sett onSettingsChange({ ...settings, apiUrl: e.target.value })} - placeholder="https://api.example.com/webhook" - className="text-sm" - /> - -
-
- - -
-
- -