super-harness / src /components /workflow /selected-node-config-tab.tsx
Cyber Catalyst Team
Deploy to HF Spaces with LFS
4782147
Raw
History Blame Contribute Delete
5.27 kB
import { NodeKind, UINode } from "lib/ai/workflow/workflow.interface";
import { useReactFlow } from "@xyflow/react";
import { NodeIcon } from "./node-icon";
import { Input } from "ui/input";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "ui/dropdown-menu";
import { MoreHorizontalIcon, XIcon } from "lucide-react";
import { NodeContextMenuContent } from "./node-context-menu-content";
import { Textarea } from "ui/textarea";
import { Separator } from "ui/separator";
import { InputNodeDataConfig } from "./node-config/input-node-config";
import { OutputNodeDataConfig } from "./node-config/output-node-config";
import { LLMNodeDataConfig } from "./node-config/llm-node-config";
import { ConditionNodeDataConfig } from "./node-config/condition-node-config";
import { Label } from "ui/label";
import { NextNodeInfo } from "./next-node-info";
import { nextTick } from "lib/utils";
import { ToolNodeDataConfig } from "./node-config/tool-node-config";
import { HttpNodeConfig } from "./node-config/http-node-config";
import { TemplateNodeConfig } from "./node-config/template-node-config";
import { useTranslations } from "next-intl";
export function SelectedNodeConfigTab({ node }: { node: UINode }) {
const t = useTranslations();
const { updateNodeData, updateNode, setNodes } = useReactFlow();
return (
<div
key={node.id}
className="w-sm h-[85vh] space-y-4 bg-card border rounded-lg shadow-lg overflow-y-auto py-4"
>
{/* Header */}
<div className="px-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 w-full">
<NodeIcon type={node.data.kind} />
<Input
maxLength={20}
onChange={(e) =>
updateNodeData(node.id, { name: e.target.value })
}
value={node.data.name}
className="bg-transparent border-none px-0 text-lg font-semibold"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<div className="ml-auto rounded hover:bg-secondary cursor-pointer p-1">
<MoreHorizontalIcon className="size-3.5" />
</div>
</DropdownMenuTrigger>
<DropdownMenuContent>
<NodeContextMenuContent node={node.data} />
</DropdownMenuContent>
</DropdownMenu>
<div
className="p-1 rounded hover:bg-secondary cursor-pointer"
onClick={() => {
setNodes((nodes) => {
return nodes.map((n) =>
n.id === node.id ? { ...n, selected: false } : n,
);
});
}}
>
<XIcon className="size-3.5" />
</div>
</div>
</div>
{node.data.kind !== NodeKind.Note && (
<Textarea
className="text-xs bg-transparent rounded-none resize-none overflow-y-auto max-h-14 min-h-6 h-6 mt-2 p-0 border-none"
value={node.data.description}
onChange={(e) =>
updateNodeData(node.id, {
description: e.target.value,
})
}
placeholder={t("Workflow.nodeDescriptionPlaceholder")}
/>
)}
</div>
<Separator className="my-6" />
<div className="flex-1">
{node.data.kind === NodeKind.Input ? (
<InputNodeDataConfig data={node.data} />
) : node.data.kind === NodeKind.Output ? (
<OutputNodeDataConfig data={node.data} />
) : node.data.kind === NodeKind.LLM ? (
<LLMNodeDataConfig data={node.data} />
) : node.data.kind === NodeKind.Condition ? (
<ConditionNodeDataConfig data={node.data} />
) : node.data.kind === NodeKind.Tool ? (
<ToolNodeDataConfig data={node.data} />
) : node.data.kind === NodeKind.Http ? (
<HttpNodeConfig node={node} />
) : node.data.kind === NodeKind.Template ? (
<TemplateNodeConfig data={node.data} />
) : node.data.kind === NodeKind.Note ? (
<div className="h-full flex flex-col gap-2 px-4">
<Label
htmlFor="description"
className="text-muted-foreground text-xs"
>
{t("Common.description")}
</Label>
<Textarea
id="description"
className="resize-none min-h-80 max-h-80 overflow-y-auto"
value={node.data.description}
onChange={(e) =>
updateNodeData(node.id, {
description: e.target.value,
})
}
/>
</div>
) : null}
</div>
{![NodeKind.Output, NodeKind.Note].includes(node.data.kind) && (
<>
<Separator className="my-6" />
<div className="px-4 ">
<NextNodeInfo
node={node}
onSelectNode={(id) => {
updateNode(node.id, { selected: false });
nextTick().then(() => updateNode(id, { selected: true }));
}}
/>
</div>
</>
)}
</div>
);
}