제어 관리 저장 액션에 논리연산자 추가
This commit is contained in:
@@ -669,6 +669,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
|
||||
id: action.id as string,
|
||||
name: action.name as string,
|
||||
actionType: action.actionType as "insert" | "update" | "delete" | "upsert",
|
||||
logicalOperator: action.logicalOperator as "AND" | "OR" | undefined, // 논리 연산자 추가
|
||||
fieldMappings: ((action.fieldMappings as Record<string, unknown>[]) || []).map(
|
||||
(mapping: Record<string, unknown>) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
@@ -38,6 +38,8 @@ export const DataSaveSettings: React.FC<DataSaveSettingsProps> = ({
|
||||
id: `action_${settings.actions.length + 1}`,
|
||||
name: `액션 ${settings.actions.length + 1}`,
|
||||
actionType: "insert" as const,
|
||||
// 첫 번째 액션이 아니면 기본적으로 AND 연산자 추가
|
||||
...(settings.actions.length > 0 && { logicalOperator: "AND" as const }),
|
||||
fieldMappings: [],
|
||||
conditions: [],
|
||||
splitConfig: {
|
||||
@@ -60,6 +62,12 @@ export const DataSaveSettings: React.FC<DataSaveSettingsProps> = ({
|
||||
|
||||
const removeAction = (actionIndex: number) => {
|
||||
const newActions = settings.actions.filter((_, i) => i !== actionIndex);
|
||||
|
||||
// 첫 번째 액션을 삭제했다면, 새로운 첫 번째 액션의 logicalOperator 제거
|
||||
if (actionIndex === 0 && newActions.length > 0) {
|
||||
delete newActions[0].logicalOperator;
|
||||
}
|
||||
|
||||
onSettingsChange({ ...settings, actions: newActions });
|
||||
};
|
||||
|
||||
@@ -87,104 +95,132 @@ export const DataSaveSettings: React.FC<DataSaveSettingsProps> = ({
|
||||
) : (
|
||||
<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 key={action.id}>
|
||||
{/* 첫 번째 액션이 아닌 경우 논리 연산자 표시 */}
|
||||
{actionIndex > 0 && (
|
||||
<div className="mb-2 flex items-center justify-center">
|
||||
<div className="flex items-center gap-2 rounded-lg bg-gray-100 px-3 py-1">
|
||||
<span className="text-xs text-gray-600">이전 액션과의 관계:</span>
|
||||
<Select
|
||||
value={action.logicalOperator || "AND"}
|
||||
onValueChange={(value: "AND" | "OR") => updateAction(actionIndex, "logicalOperator", value)}
|
||||
>
|
||||
<SelectTrigger className="h-8 w-20 text-sm">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="AND">AND</SelectItem>
|
||||
<SelectItem value="OR">OR</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</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
|
||||
<div 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}
|
||||
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 />
|
||||
위에서 설정한 실행조건에 맞는 모든 데이터가 삭제됩니다.
|
||||
{/* 데이터 분할 설정 - 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>
|
||||
|
||||
Reference in New Issue
Block a user