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:
@@ -1,118 +1,31 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* 스크립트 실행 액션 노드
|
||||
* Python, Shell, PowerShell 등 외부 스크립트를 실행하는 노드
|
||||
*/
|
||||
|
||||
import { memo } from "react";
|
||||
import { Handle, Position, NodeProps } from "reactflow";
|
||||
import { Terminal, FileCode, Play } from "lucide-react";
|
||||
import type { ScriptActionNodeData } from "@/types/node-editor";
|
||||
import { NodeProps } from "reactflow";
|
||||
import { Terminal } from "lucide-react";
|
||||
import { CompactNodeShell } from "./CompactNodeShell";
|
||||
|
||||
// 스크립트 타입별 아이콘 색상
|
||||
const SCRIPT_TYPE_COLORS: Record<string, { bg: string; text: string; label: string }> = {
|
||||
python: { bg: "bg-amber-100", text: "text-yellow-700", label: "Python" },
|
||||
shell: { bg: "bg-emerald-100", text: "text-emerald-700", label: "Shell" },
|
||||
powershell: { bg: "bg-primary/10", text: "text-primary", label: "PowerShell" },
|
||||
node: { bg: "bg-emerald-100", text: "text-emerald-700", label: "Node.js" },
|
||||
executable: { bg: "bg-muted", text: "text-foreground", label: "실행파일" },
|
||||
};
|
||||
|
||||
export const ScriptActionNode = memo(({ data, selected }: NodeProps<ScriptActionNodeData>) => {
|
||||
const scriptTypeInfo = SCRIPT_TYPE_COLORS[data.scriptType] || SCRIPT_TYPE_COLORS.executable;
|
||||
const hasScript = data.executionMode === "inline" ? !!data.inlineScript : !!data.scriptPath;
|
||||
export const ScriptActionNode = memo(({ data, selected }: NodeProps<any>) => {
|
||||
const scriptType = data.scriptType || "python";
|
||||
const summary = data.inlineScript
|
||||
? `${scriptType} 스크립트 (${data.inlineScript.split("\n").length}줄)`
|
||||
: "스크립트를 작성해 주세요";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`min-w-[250px] rounded-lg border-2 bg-white shadow-md transition-all ${
|
||||
selected ? "border-emerald-500 shadow-lg" : "border-border"
|
||||
}`}
|
||||
<CompactNodeShell
|
||||
color="#10B981"
|
||||
label={data.displayName || "스크립트 실행"}
|
||||
summary={summary}
|
||||
icon={<Terminal className="h-3.5 w-3.5" />}
|
||||
selected={selected}
|
||||
>
|
||||
{/* 입력 핸들 */}
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
className="!h-3 !w-3 !border-2 !border-white !bg-emerald-500"
|
||||
/>
|
||||
|
||||
{/* 헤더 */}
|
||||
<div className="flex items-center gap-2 rounded-t-lg bg-emerald-500 px-3 py-2 text-white">
|
||||
<Terminal className="h-4 w-4" />
|
||||
<div className="flex-1">
|
||||
<div className="text-sm font-semibold">{data.displayName || "스크립트 실행"}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 본문 */}
|
||||
<div className="space-y-2 p-3">
|
||||
{/* 스크립트 타입 */}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={`rounded px-2 py-0.5 text-xs font-medium ${scriptTypeInfo.bg} ${scriptTypeInfo.text}`}>
|
||||
{scriptTypeInfo.label}
|
||||
</span>
|
||||
<span className="rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground">
|
||||
{data.executionMode === "inline" ? "인라인" : "파일"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 스크립트 정보 */}
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
{data.executionMode === "inline" ? (
|
||||
<>
|
||||
<FileCode className="h-3 w-3 text-muted-foreground/70" />
|
||||
<span className="text-muted-foreground">
|
||||
{hasScript ? (
|
||||
<span className="text-emerald-600">
|
||||
{data.inlineScript!.split("\n").length}줄 스크립트
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-amber-500">스크립트 입력 필요</span>
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Play className="h-3 w-3 text-muted-foreground/70" />
|
||||
<span className="text-muted-foreground">
|
||||
{hasScript ? (
|
||||
<span className="truncate text-emerald-600">{data.scriptPath}</span>
|
||||
) : (
|
||||
<span className="text-amber-500">파일 경로 필요</span>
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 입력 방식 */}
|
||||
<div className="text-xs">
|
||||
<span className="text-muted-foreground">입력: </span>
|
||||
<span className="text-foreground">
|
||||
{data.inputMethod === "stdin" && "표준입력 (stdin)"}
|
||||
{data.inputMethod === "args" && "명령줄 인자"}
|
||||
{data.inputMethod === "env" && "환경변수"}
|
||||
{data.inputMethod === "file" && "파일"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 타임아웃 */}
|
||||
{data.options?.timeout && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
타임아웃: {Math.round(data.options.timeout / 1000)}초
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 출력 핸들 */}
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
className="!h-3 !w-3 !border-2 !border-white !bg-emerald-500"
|
||||
/>
|
||||
</div>
|
||||
{data.scriptType && (
|
||||
<span className="rounded bg-emerald-500/20 px-1 py-0.5 font-mono text-[9px] font-semibold text-emerald-400">
|
||||
{scriptType}
|
||||
</span>
|
||||
)}
|
||||
</CompactNodeShell>
|
||||
);
|
||||
});
|
||||
|
||||
ScriptActionNode.displayName = "ScriptActionNode";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user