ERP-node/frontend/components/dataflow/connection/DataSaveSettings.tsx

197 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Plus, Save, Trash2 } from "lucide-react";
import { TableInfo, ColumnInfo } from "@/lib/api/dataflow";
import { DataSaveSettings as DataSaveSettingsType } from "@/types/connectionTypes";
import { ActionConditionsSection } from "./ActionConditionsSection";
import { ActionFieldMappings } from "./ActionFieldMappings";
import { ActionSplitConfig } from "./ActionSplitConfig";
interface DataSaveSettingsProps {
settings: DataSaveSettingsType;
onSettingsChange: (settings: DataSaveSettingsType) => void;
availableTables: TableInfo[];
fromTableColumns: ColumnInfo[];
toTableColumns: ColumnInfo[];
fromTableName?: string;
toTableName?: string;
tableColumnsCache: { [tableName: string]: ColumnInfo[] };
}
export const DataSaveSettings: React.FC<DataSaveSettingsProps> = ({
settings,
onSettingsChange,
availableTables,
fromTableColumns,
toTableColumns,
fromTableName,
toTableName,
tableColumnsCache,
}) => {
const addAction = () => {
const newAction = {
id: `action_${settings.actions.length + 1}`,
name: `액션 ${settings.actions.length + 1}`,
actionType: "insert" as const,
fieldMappings: [],
conditions: [],
splitConfig: {
sourceField: "",
delimiter: "",
targetField: "",
},
};
onSettingsChange({
...settings,
actions: [...settings.actions, newAction],
});
};
const updateAction = (actionIndex: number, field: string, value: any) => {
const newActions = [...settings.actions];
(newActions[actionIndex] as any)[field] = value;
onSettingsChange({ ...settings, actions: newActions });
};
const removeAction = (actionIndex: number) => {
const newActions = settings.actions.filter((_, i) => i !== actionIndex);
onSettingsChange({ ...settings, actions: newActions });
};
return (
<div className="rounded-lg border border-l-4 border-l-green-500 bg-green-50/30 p-4">
<div className="mb-3 flex items-center gap-2">
<Save className="h-4 w-4 text-green-500" />
<span className="text-sm font-medium"> </span>
</div>
<div className="space-y-4">
{/* 액션 목록 */}
<div>
<div className="mb-2 flex items-center justify-between">
<Label className="text-sm font-medium"> </Label>
<Button size="sm" variant="outline" onClick={addAction} className="h-7 text-xs">
<Plus className="mr-1 h-3 w-3" />
</Button>
</div>
{settings.actions.length === 0 ? (
<div className="rounded-lg border border-dashed p-3 text-center text-xs text-gray-500">
.
</div>
) : (
<div className="space-y-3">
{settings.actions.map((action, actionIndex) => (
<div key={action.id} className="rounded border bg-white p-3">
<div className="mb-3 flex items-center justify-between">
<Input
value={action.name}
onChange={(e) => updateAction(actionIndex, "name", e.target.value)}
className="h-7 flex-1 text-xs font-medium"
placeholder="액션 이름"
/>
<Button size="sm" variant="ghost" onClick={() => removeAction(actionIndex)} className="h-7 w-7 p-0">
<Trash2 className="h-3 w-3" />
</Button>
</div>
<div className="grid grid-cols-1 gap-3">
{/* 액션 타입 */}
<div>
<Label className="text-xs"> </Label>
<Select
value={action.actionType}
onValueChange={(value: "insert" | "update" | "delete" | "upsert") =>
updateAction(actionIndex, "actionType", value)
}
>
<SelectTrigger className="h-7 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="insert">INSERT</SelectItem>
<SelectItem value="update">UPDATE</SelectItem>
<SelectItem value="delete">DELETE</SelectItem>
<SelectItem value="upsert">UPSERT</SelectItem>
</SelectContent>
</Select>
</div>
</div>
{/* 액션별 개별 실행 조건 */}
<ActionConditionsSection
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
fromTableColumns={fromTableColumns}
toTableColumns={toTableColumns}
fromTableName={fromTableName}
toTableName={toTableName}
/>
{/* 데이터 분할 설정 - DELETE 액션은 제외 */}
{action.actionType !== "delete" && (
<ActionSplitConfig
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
fromTableColumns={fromTableColumns}
toTableColumns={toTableColumns}
/>
)}
{/* 필드 매핑 - DELETE 액션은 제외 */}
{action.actionType !== "delete" && (
<ActionFieldMappings
action={action}
actionIndex={actionIndex}
settings={settings}
onSettingsChange={onSettingsChange}
availableTables={availableTables}
tableColumnsCache={tableColumnsCache}
fromTableColumns={fromTableColumns}
toTableColumns={toTableColumns}
fromTableName={fromTableName}
toTableName={toTableName}
/>
)}
{/* DELETE 액션일 때 안내 메시지 */}
{action.actionType === "delete" && (
<div className="mt-3">
<div className="rounded border border-blue-200 bg-blue-50 p-3 text-xs text-blue-700">
<div className="flex items-start gap-2">
<span></span>
<div>
<div className="font-medium">DELETE </div>
<div className="mt-1">
DELETE <strong></strong> .
<br />
설정: 불필요 ( )
<br />
매핑: 불필요 ( )
<br />
.
</div>
</div>
</div>
</div>
</div>
)}
</div>
))}
</div>
)}
</div>
</div>
</div>
);
};