Enhance batch management functionality by adding node flow execution support and improving batch configuration creation. Introduce new API endpoint for retrieving node flows and update existing batch services to handle execution types. Update frontend components to support new scheduling options and node flow selection.

This commit is contained in:
DDD1542
2026-03-19 15:07:07 +09:00
parent 7f781b0177
commit 43cf91e748
41 changed files with 4020 additions and 3155 deletions

View File

@@ -1,69 +1,40 @@
"use client";
/**
* 테이블 소스 노드
*/
import { memo } from "react";
import { Handle, Position, NodeProps } from "reactflow";
import { NodeProps } from "reactflow";
import { Database } from "lucide-react";
import { CompactNodeShell } from "./CompactNodeShell";
import type { TableSourceNodeData } from "@/types/node-editor";
export const TableSourceNode = memo(({ data, selected }: NodeProps<TableSourceNodeData>) => {
// 디버깅: 필드 데이터 확인
if (data.fields && data.fields.length > 0) {
console.log("🔍 TableSource 필드 데이터:", data.fields);
}
const fieldCount = data.fields?.length || 0;
const summary = data.tableName
? `${data.tableName} (${fieldCount}개 필드)`
: "테이블을 선택해 주세요";
return (
<div
className={`min-w-[250px] rounded-lg border-2 bg-white shadow-md transition-all ${
selected ? "border-primary shadow-lg" : "border-border"
}`}
<CompactNodeShell
color="#3B82F6"
label={data.displayName || data.tableName || "테이블 소스"}
summary={summary}
icon={<Database className="h-3.5 w-3.5" />}
selected={selected}
hasInput={false}
>
{/* 헤더 */}
<div className="flex items-center gap-2 rounded-t-lg bg-primary px-3 py-2 text-white">
<Database className="h-4 w-4" />
<div className="flex-1">
<div className="text-sm font-semibold">{data.displayName || data.tableName || "테이블 소스"}</div>
{data.tableName && data.displayName !== data.tableName && (
<div className="text-xs opacity-80">{data.tableName}</div>
{fieldCount > 0 && (
<div className="space-y-0.5">
{data.fields!.slice(0, 4).map((f) => (
<div key={f.name} className="flex items-center gap-1.5">
<div className="h-1 w-1 flex-shrink-0 rounded-full bg-blue-400" />
<span>{f.label || f.displayName || f.name}</span>
</div>
))}
{fieldCount > 4 && (
<span className="text-zinc-600"> {fieldCount - 4}</span>
)}
</div>
</div>
{/* 본문 */}
<div className="p-3">
<div className="mb-2 text-xs font-medium text-muted-foreground">📍 </div>
{/* 필드 목록 */}
<div className="space-y-1">
<div className="text-xs font-medium text-foreground"> :</div>
<div className="max-h-[150px] overflow-y-auto">
{data.fields && data.fields.length > 0 ? (
data.fields.slice(0, 5).map((field) => (
<div key={field.name} className="flex items-center gap-2 text-xs text-muted-foreground">
<div className="h-1.5 w-1.5 rounded-full bg-primary/70" />
<span className="font-medium">{field.label || field.displayName || field.name}</span>
{(field.label || field.displayName) && field.label !== field.name && (
<span className="font-mono text-muted-foreground/70">({field.name})</span>
)}
<span className="text-muted-foreground/70">{field.type}</span>
</div>
))
) : (
<div className="text-xs text-muted-foreground/70"> </div>
)}
{data.fields && data.fields.length > 5 && (
<div className="text-xs text-muted-foreground/70">... {data.fields.length - 5}</div>
)}
</div>
</div>
</div>
{/* 출력 핸들 */}
<Handle type="source" position={Position.Right} className="!h-3 !w-3 !border-2 !border-primary !bg-white" />
</div>
)}
</CompactNodeShell>
);
});