외부호출 기능(rest API)
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Globe } from "lucide-react";
|
||||
|
||||
// 타입 import
|
||||
import { RightPanelProps } from "../types/redesigned";
|
||||
@@ -14,6 +16,7 @@ import FieldMappingStep from "./FieldMappingStep";
|
||||
import ControlConditionStep from "./ControlConditionStep";
|
||||
import ActionConfigStep from "./ActionConfigStep";
|
||||
import MultiActionConfigStep from "./MultiActionConfigStep";
|
||||
import ExternalCallPanel from "../../../external-call/ExternalCallPanel";
|
||||
|
||||
/**
|
||||
* 🎯 우측 패널 (70% 너비)
|
||||
@@ -22,6 +25,12 @@ import MultiActionConfigStep from "./MultiActionConfigStep";
|
||||
* - 시각적 매핑 영역
|
||||
*/
|
||||
const RightPanel: React.FC<RightPanelProps> = ({ state, actions }) => {
|
||||
console.log("🔄 [RightPanel] 컴포넌트 렌더링 - connectionType:", state.connectionType);
|
||||
|
||||
// connectionType 변경 감지
|
||||
useEffect(() => {
|
||||
console.log("🔄 [RightPanel] connectionType 변경됨:", state.connectionType);
|
||||
}, [state.connectionType]);
|
||||
// 완료된 단계 계산
|
||||
const completedSteps: number[] = [];
|
||||
|
||||
@@ -52,104 +61,225 @@ const RightPanel: React.FC<RightPanelProps> = ({ state, actions }) => {
|
||||
}
|
||||
|
||||
const renderCurrentStep = () => {
|
||||
switch (state.currentStep) {
|
||||
case 1:
|
||||
try {
|
||||
// 외부호출인 경우 단계 무시하고 바로 외부호출 설정 화면 표시
|
||||
console.log("🔍 [RightPanel] renderCurrentStep - connectionType:", state.connectionType);
|
||||
if (state.connectionType === "external_call") {
|
||||
console.log("✅ [RightPanel] 외부호출 화면 렌더링");
|
||||
return (
|
||||
<ConnectionStep
|
||||
connectionType={state.connectionType}
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
relationshipName={state.relationshipName}
|
||||
description={state.description}
|
||||
diagramId={state.diagramId} // 🔧 수정 모드 감지용
|
||||
onSelectConnection={actions.selectConnection}
|
||||
onSetRelationshipName={actions.setRelationshipName}
|
||||
onSetDescription={actions.setDescription}
|
||||
onNext={() => actions.goToStep(2)}
|
||||
/>
|
||||
);
|
||||
<div className="flex h-full flex-col">
|
||||
{/* 헤더 */}
|
||||
<div className="flex-shrink-0 px-4 py-2">
|
||||
<div className="flex items-center gap-3 border-b pb-2">
|
||||
<Globe className="h-5 w-5 text-blue-600" />
|
||||
<h2 className="text-lg font-semibold">외부 호출 설정</h2>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-sm">
|
||||
REST API 호출을 통해 외부 시스템에 데이터를 전송하거나 알림을 보낼 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
case 2:
|
||||
return (
|
||||
<TableStep
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
fromTable={state.fromTable}
|
||||
toTable={state.toTable}
|
||||
onSelectTable={actions.selectTable}
|
||||
onNext={() => actions.goToStep(3)} // 3단계(제어 조건)로
|
||||
onBack={() => actions.goToStep(1)}
|
||||
/>
|
||||
);
|
||||
{/* 관계명 및 설명 입력 */}
|
||||
<div className="flex-shrink-0 px-4 pb-2">
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="text-sm font-medium">관계명 *</label>
|
||||
<input
|
||||
type="text"
|
||||
value={state.relationshipName || ""}
|
||||
onChange={(e) => actions.setRelationshipName(e.target.value)}
|
||||
placeholder="외부호출 관계의 이름을 입력하세요"
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-sm font-medium">설명</label>
|
||||
<textarea
|
||||
value={state.description || ""}
|
||||
onChange={(e) => actions.setDescription(e.target.value)}
|
||||
placeholder="외부호출의 용도나 설명을 입력하세요"
|
||||
rows={2}
|
||||
className="mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
case 3:
|
||||
// 3단계: 제어 조건
|
||||
return (
|
||||
<ControlConditionStep
|
||||
state={state}
|
||||
actions={actions}
|
||||
onBack={() => actions.goToStep(2)}
|
||||
onNext={() => {
|
||||
// 4단계로 넘어가기 전에 컬럼 로드
|
||||
actions.loadColumns();
|
||||
actions.goToStep(4);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
{/* 외부호출 패널 - 공간 최적화 */}
|
||||
<div className="flex-1 overflow-hidden px-4">
|
||||
<div className="h-full max-h-[calc(100vh-400px)] overflow-y-auto">
|
||||
<ExternalCallPanel
|
||||
relationshipId={`external-call-${Date.now()}`}
|
||||
readonly={false}
|
||||
initialSettings={
|
||||
state.externalCallConfig || {
|
||||
callType: "rest-api",
|
||||
restApiSettings: {
|
||||
apiUrl: "",
|
||||
httpMethod: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
bodyTemplate: "",
|
||||
authentication: { type: "none" },
|
||||
timeout: 30000,
|
||||
retryCount: 3,
|
||||
},
|
||||
}
|
||||
}
|
||||
onSettingsChange={actions.updateExternalCallConfig}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
case 4:
|
||||
// 4단계: 통합된 멀티 액션 설정 (제어 조건 + 액션 설정 + 컬럼 매핑)
|
||||
return (
|
||||
<MultiActionConfigStep
|
||||
fromTable={state.fromTable}
|
||||
toTable={state.toTable}
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
fromColumns={state.fromColumns} // 🔧 중앙에서 관리되는 컬럼 정보
|
||||
toColumns={state.toColumns} // 🔧 중앙에서 관리되는 컬럼 정보
|
||||
controlConditions={state.controlConditions}
|
||||
onUpdateControlCondition={actions.updateControlCondition}
|
||||
onDeleteControlCondition={actions.deleteControlCondition}
|
||||
onAddControlCondition={actions.addControlCondition}
|
||||
actionGroups={state.actionGroups}
|
||||
groupsLogicalOperator={state.groupsLogicalOperator}
|
||||
onUpdateActionGroup={actions.updateActionGroup}
|
||||
onDeleteActionGroup={actions.deleteActionGroup}
|
||||
onAddActionGroup={actions.addActionGroup}
|
||||
onAddActionToGroup={actions.addActionToGroup}
|
||||
onUpdateActionInGroup={actions.updateActionInGroup}
|
||||
onDeleteActionFromGroup={actions.deleteActionFromGroup}
|
||||
onSetGroupsLogicalOperator={actions.setGroupsLogicalOperator}
|
||||
fieldMappings={state.fieldMappings}
|
||||
onCreateMapping={actions.createMapping}
|
||||
onDeleteMapping={actions.deleteMapping}
|
||||
onLoadColumns={actions.loadColumns}
|
||||
onNext={() => {
|
||||
// 완료 처리 - 저장 및 상위 컴포넌트 알림
|
||||
actions.saveMappings();
|
||||
}}
|
||||
onBack={() => actions.goToStep(3)}
|
||||
/>
|
||||
{/* 하단 버튼 - 바로 붙여서 고정 */}
|
||||
<div className="flex-shrink-0 border-t bg-white px-4 py-2">
|
||||
<div className="flex gap-3">
|
||||
<Button
|
||||
onClick={actions.saveMappings}
|
||||
className="w-full bg-blue-600 hover:bg-blue-700"
|
||||
disabled={state.isLoading}
|
||||
>
|
||||
{state.isLoading ? "저장 중..." : "저장"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
// 데이터 저장인 경우에만 단계별 진행
|
||||
switch (state.currentStep) {
|
||||
case 1:
|
||||
return (
|
||||
<ConnectionStep
|
||||
connectionType={state.connectionType}
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
relationshipName={state.relationshipName}
|
||||
description={state.description}
|
||||
diagramId={state.diagramId} // 🔧 수정 모드 감지용
|
||||
onSelectConnection={actions.selectConnection}
|
||||
onSetRelationshipName={actions.setRelationshipName}
|
||||
onSetDescription={actions.setDescription}
|
||||
onNext={() => actions.goToStep(2)}
|
||||
/>
|
||||
);
|
||||
|
||||
case 2:
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<TableStep
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
fromTable={state.fromTable}
|
||||
toTable={state.toTable}
|
||||
onSelectTable={actions.selectTable}
|
||||
onNext={() => actions.goToStep(3)} // 3단계(제어 조건)로
|
||||
onBack={() => actions.goToStep(1)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
case 3:
|
||||
// 데이터 저장인 경우 제어 조건 단계
|
||||
return (
|
||||
<ControlConditionStep
|
||||
state={state}
|
||||
actions={actions}
|
||||
onBack={() => actions.goToStep(2)}
|
||||
onNext={() => {
|
||||
// 4단계로 넘어가기 전에 컬럼 로드
|
||||
actions.loadColumns();
|
||||
actions.goToStep(4);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
case 4:
|
||||
// 외부호출인 경우 4단계 없음
|
||||
if (state.connectionType === "external_call") {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 4단계: 통합된 멀티 액션 설정 (제어 조건 + 액션 설정 + 컬럼 매핑)
|
||||
return (
|
||||
<MultiActionConfigStep
|
||||
fromTable={state.fromTable}
|
||||
toTable={state.toTable}
|
||||
fromConnection={state.fromConnection}
|
||||
toConnection={state.toConnection}
|
||||
fromColumns={state.fromColumns} // 🔧 중앙에서 관리되는 컬럼 정보
|
||||
toColumns={state.toColumns} // 🔧 중앙에서 관리되는 컬럼 정보
|
||||
controlConditions={state.controlConditions}
|
||||
onUpdateControlCondition={actions.updateControlCondition}
|
||||
onDeleteControlCondition={actions.deleteControlCondition}
|
||||
onAddControlCondition={actions.addControlCondition}
|
||||
actionGroups={state.actionGroups}
|
||||
groupsLogicalOperator={state.groupsLogicalOperator}
|
||||
onUpdateActionGroup={actions.updateActionGroup}
|
||||
onDeleteActionGroup={actions.deleteActionGroup}
|
||||
onAddActionGroup={actions.addActionGroup}
|
||||
onAddActionToGroup={actions.addActionToGroup}
|
||||
onUpdateActionInGroup={actions.updateActionInGroup}
|
||||
onDeleteActionFromGroup={actions.deleteActionFromGroup}
|
||||
onSetGroupsLogicalOperator={actions.setGroupsLogicalOperator}
|
||||
fieldMappings={state.fieldMappings}
|
||||
onCreateMapping={actions.createMapping}
|
||||
onDeleteMapping={actions.deleteMapping}
|
||||
onLoadColumns={actions.loadColumns}
|
||||
onNext={() => {
|
||||
// 완료 처리 - 저장 및 상위 컴포넌트 알림
|
||||
actions.saveMappings();
|
||||
}}
|
||||
onBack={() => actions.goToStep(3)}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ [RightPanel] renderCurrentStep 에러:", error);
|
||||
return <div>renderCurrentStep 에러: {String(error)}</div>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
{/* 단계 진행 표시 */}
|
||||
<div className="bg-card/50 border-b p-3">
|
||||
<StepProgress currentStep={state.currentStep} completedSteps={completedSteps} onStepClick={actions.goToStep} />
|
||||
</div>
|
||||
try {
|
||||
console.log("🎯 [RightPanel] return 시작 - connectionType:", state.connectionType);
|
||||
|
||||
{/* 현재 단계 컨텐츠 */}
|
||||
<div className="min-h-0 flex-1 p-3">
|
||||
<Card className="flex h-full flex-col overflow-hidden">{renderCurrentStep()}</Card>
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
{/* 단계 진행 표시 - 외부호출이 아닐 때만 */}
|
||||
{state.connectionType !== "external_call" && (
|
||||
<div className="bg-card/50 border-b p-3">
|
||||
<StepProgress
|
||||
currentStep={state.currentStep}
|
||||
completedSteps={completedSteps}
|
||||
onStepClick={actions.goToStep}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 현재 단계 컨텐츠 */}
|
||||
<div className="min-h-0 flex-1 p-3">
|
||||
{(() => {
|
||||
console.log("🎯 [RightPanel] 조건부 렌더링 체크 - connectionType:", state.connectionType);
|
||||
console.log("🎯 [RightPanel] external_call인가?", state.connectionType === "external_call");
|
||||
|
||||
if (state.connectionType === "external_call") {
|
||||
console.log("🎯 [RightPanel] 외부호출 렌더링 시작");
|
||||
return renderCurrentStep();
|
||||
} else {
|
||||
console.log("🎯 [RightPanel] 데이터 저장 렌더링 시작");
|
||||
return <Card className="flex h-full flex-col overflow-hidden">{renderCurrentStep()}</Card>;
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("❌ [RightPanel] 렌더링 에러:", error);
|
||||
return <div>렌더링 에러 발생: {String(error)}</div>;
|
||||
}
|
||||
};
|
||||
|
||||
export default RightPanel;
|
||||
|
||||
Reference in New Issue
Block a user