diff options
| author | blackhao <13851610112@163.com> | 2025-12-06 01:30:57 -0600 |
|---|---|---|
| committer | blackhao <13851610112@163.com> | 2025-12-06 01:30:57 -0600 |
| commit | 93dbe11014cf967690727c25e89d9d1075008c24 (patch) | |
| tree | e168becbfff0e699f49021c1b3de6918e7f0a124 /frontend/src/App.tsx | |
| parent | bcb44d5a7c4b17afd7ba64be5b497d74afc69fb6 (diff) | |
Diffstat (limited to 'frontend/src/App.tsx')
| -rw-r--r-- | frontend/src/App.tsx | 115 |
1 files changed, 96 insertions, 19 deletions
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8c52751..9ec1340 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -13,6 +13,7 @@ import 'reactflow/dist/style.css'; import useFlowStore from './store/flowStore'; import LLMNode from './components/nodes/LLMNode'; import Sidebar from './components/Sidebar'; +import LeftSidebar from './components/LeftSidebar'; import { ContextMenu } from './components/ContextMenu'; import { Plus } from 'lucide-react'; @@ -31,12 +32,19 @@ function Flow() { deleteEdge, deleteNode, deleteBranch, - setSelectedNode + setSelectedNode, + toggleNodeDisabled, + archiveNode, + createNodeFromArchive, + toggleTraceDisabled } = useFlowStore(); const reactFlowWrapper = useRef<HTMLDivElement>(null); const { project } = useReactFlow(); const [menu, setMenu] = useState<{ x: number; y: number; type: 'pane' | 'node' | 'edge'; id?: string } | null>(null); + + const [isLeftOpen, setIsLeftOpen] = useState(true); + const [isRightOpen, setIsRightOpen] = useState(true); const onPaneClick = () => { setSelectedNode(null); @@ -73,6 +81,7 @@ function Flow() { systemPrompt: '', userPrompt: '', mergeStrategy: 'smart', + reasoningEffort: 'medium', // Default for reasoning models messages: [], traces: [], outgoingTraces: [], @@ -86,12 +95,44 @@ function Flow() { }; const onNodeClick = (_: any, node: Node) => { + // Don't select disabled nodes + const nodeData = node.data as any; + if (nodeData?.disabled) return; setSelectedNode(node.id); }; + const onDragOver = (event: React.DragEvent) => { + event.preventDefault(); + event.dataTransfer.dropEffect = 'copy'; + }; + + const onDrop = (event: React.DragEvent) => { + event.preventDefault(); + + const archiveId = event.dataTransfer.getData('archiveId'); + if (!archiveId) return; + + const bounds = reactFlowWrapper.current?.getBoundingClientRect(); + if (!bounds) return; + + const position = project({ + x: event.clientX - bounds.left, + y: event.clientY - bounds.top + }); + + createNodeFromArchive(archiveId, position); + }; + return ( <div style={{ width: '100vw', height: '100vh', display: 'flex' }}> - <div style={{ flex: 1, height: '100%' }} ref={reactFlowWrapper}> + <LeftSidebar isOpen={isLeftOpen} onToggle={() => setIsLeftOpen(!isLeftOpen)} /> + + <div + style={{ flex: 1, height: '100%', position: 'relative' }} + ref={reactFlowWrapper} + onDragOver={onDragOver} + onDrop={onDrop} + > <ReactFlow nodes={nodes} edges={edges} @@ -139,28 +180,64 @@ function Flow() { } } } - ] : menu.type === 'node' ? [ - { - label: 'Delete Node (Cascade)', - danger: true, - onClick: () => menu.id && deleteBranch(menu.id) - } - ] : [ - { - label: 'Disconnect', - onClick: () => menu.id && deleteEdge(menu.id) - }, - { - label: 'Delete Branch', - danger: true, - onClick: () => menu.id && deleteBranch(undefined, menu.id) + ] : menu.type === 'node' ? (() => { + const targetNode = nodes.find(n => n.id === menu.id); + const isDisabled = targetNode?.data?.disabled; + + // If disabled, only show Enable option + if (isDisabled) { + return [ + { + label: 'Enable Node', + onClick: () => menu.id && toggleNodeDisabled(menu.id) + } + ]; } - ] + + // Normal node menu + return [ + { + label: 'Disable Node', + onClick: () => menu.id && toggleNodeDisabled(menu.id) + }, + { + label: 'Add to Archive', + onClick: () => menu.id && archiveNode(menu.id) + }, + { + label: 'Delete Node (Cascade)', + danger: true, + onClick: () => menu.id && deleteBranch(menu.id) + } + ]; + })() : (() => { + // Check if any node connected to this edge is disabled + const targetEdge = edges.find(e => e.id === menu.id); + const sourceNode = nodes.find(n => n.id === targetEdge?.source); + const targetNode = nodes.find(n => n.id === targetEdge?.target); + const isTraceDisabled = sourceNode?.data?.disabled || targetNode?.data?.disabled; + + return [ + { + label: isTraceDisabled ? 'Enable Trace' : 'Disable Trace', + onClick: () => menu.id && toggleTraceDisabled(menu.id) + }, + { + label: 'Disconnect', + onClick: () => menu.id && deleteEdge(menu.id) + }, + { + label: 'Delete Branch', + danger: true, + onClick: () => menu.id && deleteBranch(undefined, menu.id) + } + ]; + })() } /> )} </div> - <Sidebar /> + <Sidebar isOpen={isRightOpen} onToggle={() => setIsRightOpen(!isRightOpen)} /> </div> ); } |
