import { Edge, useReactFlow } from "@xyflow/react"; import { ConditionNodeData, NodeKind, UINode, } from "lib/ai/workflow/workflow.interface"; import { ReactNode, useCallback, useMemo } from "react"; import { Label } from "ui/label"; import { NodeIcon } from "./node-icon"; import { Button } from "ui/button"; import { PlusIcon, Unlink } from "lucide-react"; import { NodeSelect } from "./node-select"; import { useUpdate } from "@/hooks/use-update"; import { createAppendNode } from "./create-append-node"; import { useTranslations } from "next-intl"; import { Tooltip, TooltipContent, TooltipTrigger } from "ui/tooltip"; interface NextNodeInfoProps { node: UINode; onSelectNode(nodeId: string): void; } export function NextNodeInfo({ node, onSelectNode }: NextNodeInfoProps) { const t = useTranslations(); const { addNodes, addEdges, updateNode, getEdges, getNodes, setEdges } = useReactFlow(); const nodes = getNodes() as UINode[]; const edges = getEdges(); const onDisconnected = useCallback( (edge: Edge) => { setEdges(edges.filter((e) => e.id !== edge.id)); }, [edges], ); const nextNodes = useMemo(() => { const connectedEdges = edges.filter((edge) => edge.source === node.id); const nextNodes = connectedEdges.map((edge) => { return { node: nodes.find((n) => n.id === edge.target)!, edge, }; }); return nextNodes; }, [edges, nodes]); const update = useUpdate(); const appendNode = useCallback( (kind: NodeKind, partialEdge?: Partial) => { const { node: newNode, edge: newEdge } = createAppendNode({ sourceNode: node, kind, edge: partialEdge, allNodes: nodes, allEdges: edges, }); addNodes([newNode]); if (newEdge) { addEdges([newEdge]); } update(() => { updateNode(node.id, { selected: false, }); }); }, [node.id, nodes, edges, addNodes], ); return (

{t("Workflow.nextNodeDescription")}

{node.data.kind === NodeKind.Condition ? ( ) : ( )}
); } interface NodeConnectorProps { onDisconnected: (edge: Edge) => void; appendNode: (kind: NodeKind, edge?: Partial) => void; onSelectNode: (id: string) => void; node: UINode; nextNodes: { node: UINode; edge: Edge; }[]; label?: ReactNode; } function ConditionNodeDataConnector({ node, onDisconnected, appendNode, onSelectNode, nextNodes, }: NodeConnectorProps) { const data = node.data as ConditionNodeData; const { ifNextNodes, elseNextNodes, elseIfNextNodes } = useMemo(() => { const ifNextNodes = nextNodes.filter( (n) => n.edge.sourceHandle === data.branches.if.id, ); const elseNextNodes = nextNodes.filter( (n) => n.edge.sourceHandle === data.branches.else.id, ); const elseIfNextNodes = (data.branches.elseIf ?? []).map((brach) => { return nextNodes.filter((n) => n.edge.sourceHandle === brach.id); }); return { ifNextNodes, elseNextNodes, elseIfNextNodes }; }, [nextNodes, node.data]); return (
IF CASE 1
} nextNodes={ifNextNodes} onDisconnected={onDisconnected} appendNode={(kind) => appendNode(kind, { sourceHandle: data.branches.if.id }) } onSelectNode={onSelectNode} /> {elseIfNextNodes.map((n, i) => { return ( ELSE IF CASE {i + 2} } nextNodes={n} onDisconnected={onDisconnected} appendNode={(kind) => appendNode(kind, { sourceHandle: data.branches.elseIf![i].id }) } onSelectNode={onSelectNode} /> ); })} ELSE CASE{" "} {elseIfNextNodes.length + 2} } nextNodes={elseNextNodes} onDisconnected={onDisconnected} appendNode={(kind) => appendNode(kind, { sourceHandle: data.branches.else.id }) } onSelectNode={onSelectNode} /> ); } function NextNodeConnector({ node, nextNodes, onDisconnected, appendNode, onSelectNode, label, }: NodeConnectorProps) { const t = useTranslations(); return (
{label} {nextNodes.map((n) => { return (
{n.node.data.name} {t("Workflow.unlink")}
); })}
); }