제어관리 외부 커넥션 설정기능

This commit is contained in:
kjs
2025-09-24 18:23:57 +09:00
parent 0d9ee4c40f
commit b41e645c74
25 changed files with 6775 additions and 209 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import React from "react";
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
@@ -9,6 +9,11 @@ import { Plus, Trash2 } from "lucide-react";
import { TableInfo, ColumnInfo } from "@/lib/api/dataflow";
import { DataSaveSettings } from "@/types/connectionTypes";
import { InsertFieldMappingPanel } from "./InsertFieldMappingPanel";
import { ConnectionSelectionPanel } from "./ConnectionSelectionPanel";
import { TableSelectionPanel } from "./TableSelectionPanel";
import { UpdateFieldMappingPanel } from "./UpdateFieldMappingPanel";
import { DeleteConditionPanel } from "./DeleteConditionPanel";
import { getActiveConnections, ConnectionInfo } from "@/lib/api/multiConnection";
interface ActionFieldMappingsProps {
action: DataSaveSettings["actions"][0];
@@ -21,6 +26,8 @@ interface ActionFieldMappingsProps {
toTableColumns?: ColumnInfo[];
fromTableName?: string;
toTableName?: string;
// 🆕 다중 커넥션 지원을 위한 새로운 props
enableMultiConnection?: boolean;
}
export const ActionFieldMappings: React.FC<ActionFieldMappingsProps> = ({
@@ -34,8 +41,20 @@ export const ActionFieldMappings: React.FC<ActionFieldMappingsProps> = ({
toTableColumns = [],
fromTableName,
toTableName,
enableMultiConnection = false,
}) => {
// INSERT 액션일 때는 새로운 패널 사용
// 🆕 다중 커넥션 상태 관리
const [fromConnectionId, setFromConnectionId] = useState<number | undefined>(action.fromConnection?.connectionId);
const [toConnectionId, setToConnectionId] = useState<number | undefined>(action.toConnection?.connectionId);
const [selectedFromTable, setSelectedFromTable] = useState<string | undefined>(action.fromTable || fromTableName);
const [selectedToTable, setSelectedToTable] = useState<string | undefined>(action.targetTable || toTableName);
// 다중 커넥션이 활성화된 경우 새로운 UI 렌더링
if (enableMultiConnection) {
return renderMultiConnectionUI();
}
// 기존 INSERT 액션 처리 (단일 커넥션)
if (action.actionType === "insert" && fromTableColumns.length > 0 && toTableColumns.length > 0) {
return (
<InsertFieldMappingPanel
@@ -50,6 +69,135 @@ export const ActionFieldMappings: React.FC<ActionFieldMappingsProps> = ({
/>
);
}
// 🆕 다중 커넥션 UI 렌더링 함수
function renderMultiConnectionUI() {
const hasConnectionsSelected = fromConnectionId !== undefined && toConnectionId !== undefined;
const hasTablesSelected = selectedFromTable && selectedToTable;
// 커넥션 변경 핸들러
const handleFromConnectionChange = (connectionId: number) => {
setFromConnectionId(connectionId);
setSelectedFromTable(undefined); // 테이블 선택 초기화
updateActionConnection("fromConnection", connectionId);
};
const handleToConnectionChange = (connectionId: number) => {
setToConnectionId(connectionId);
setSelectedToTable(undefined); // 테이블 선택 초기화
updateActionConnection("toConnection", connectionId);
};
// 테이블 변경 핸들러
const handleFromTableChange = (tableName: string) => {
setSelectedFromTable(tableName);
updateActionTable("fromTable", tableName);
};
const handleToTableChange = (tableName: string) => {
setSelectedToTable(tableName);
updateActionTable("targetTable", tableName);
};
// 액션 커넥션 정보 업데이트
const updateActionConnection = (type: "fromConnection" | "toConnection", connectionId: number) => {
const newActions = [...settings.actions];
if (!newActions[actionIndex][type]) {
newActions[actionIndex][type] = {};
}
newActions[actionIndex][type]!.connectionId = connectionId;
onSettingsChange({ ...settings, actions: newActions });
};
// 액션 테이블 정보 업데이트
const updateActionTable = (type: "fromTable" | "targetTable", tableName: string) => {
const newActions = [...settings.actions];
newActions[actionIndex][type] = tableName;
onSettingsChange({ ...settings, actions: newActions });
};
return (
<div className="space-y-6">
{/* 1단계: 커넥션 선택 */}
<ConnectionSelectionPanel
fromConnectionId={fromConnectionId}
toConnectionId={toConnectionId}
onFromConnectionChange={handleFromConnectionChange}
onToConnectionChange={handleToConnectionChange}
actionType={action.actionType}
allowSameConnection={true}
/>
{/* 2단계: 테이블 선택 */}
{hasConnectionsSelected && (
<TableSelectionPanel
fromConnectionId={fromConnectionId}
toConnectionId={toConnectionId}
selectedFromTable={selectedFromTable}
selectedToTable={selectedToTable}
onFromTableChange={handleFromTableChange}
onToTableChange={handleToTableChange}
actionType={action.actionType}
allowSameTable={true}
showSameTableWarning={true}
/>
)}
{/* 3단계: 액션 타입별 매핑/조건 설정 */}
{hasTablesSelected && renderActionSpecificPanel()}
</div>
);
}
// 액션 타입별 패널 렌더링
function renderActionSpecificPanel() {
switch (action.actionType) {
case "insert":
return (
<InsertFieldMappingPanel
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
fromConnectionId={fromConnectionId}
toConnectionId={toConnectionId}
fromTableName={selectedFromTable}
toTableName={selectedToTable}
/>
);
case "update":
return (
<UpdateFieldMappingPanel
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
fromConnectionId={fromConnectionId}
toConnectionId={toConnectionId}
fromTableName={selectedFromTable}
toTableName={selectedToTable}
/>
);
case "delete":
return (
<DeleteConditionPanel
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
fromConnectionId={fromConnectionId}
toConnectionId={toConnectionId}
fromTableName={selectedFromTable}
toTableName={selectedToTable}
/>
);
default:
return null;
}
}
const addFieldMapping = () => {
const newActions = [...settings.actions];
newActions[actionIndex].fieldMappings.push({
@@ -154,7 +302,9 @@ export const ActionFieldMappings: React.FC<ActionFieldMappingsProps> = ({
tableColumnsCache[mapping.sourceTable]?.map((column) => (
<SelectItem key={column.columnName} value={column.columnName}>
<div className="truncate" title={column.columnName}>
{column.displayName || column.columnLabel || column.columnName}
{column.displayName && column.displayName !== column.columnName
? column.displayName
: column.columnName}
</div>
</SelectItem>
))}
@@ -200,7 +350,9 @@ export const ActionFieldMappings: React.FC<ActionFieldMappingsProps> = ({
tableColumnsCache[mapping.targetTable]?.map((column) => (
<SelectItem key={column.columnName} value={column.columnName}>
<div className="truncate" title={column.columnName}>
{column.displayName || column.columnLabel || column.columnName}
{column.displayName && column.displayName !== column.columnName
? column.displayName
: column.columnName}
</div>
</SelectItem>
))}