|
import { useSetModalState } from '@/hooks/commonHooks'; |
|
import { |
|
useFetchFlow, |
|
useFetchFlowTemplates, |
|
useRunFlow, |
|
useSetFlow, |
|
} from '@/hooks/flow-hooks'; |
|
import { useFetchLlmList } from '@/hooks/llmHooks'; |
|
import { IGraph } from '@/interfaces/database/flow'; |
|
import { useIsFetching } from '@tanstack/react-query'; |
|
import React, { |
|
KeyboardEventHandler, |
|
useCallback, |
|
useEffect, |
|
useState, |
|
} from 'react'; |
|
import { Node, Position, ReactFlowInstance } from 'reactflow'; |
|
import { v4 as uuidv4 } from 'uuid'; |
|
|
|
import { useParams } from 'umi'; |
|
import useStore, { RFState } from './store'; |
|
import { buildDslComponentsByGraph } from './utils'; |
|
|
|
const selector = (state: RFState) => ({ |
|
nodes: state.nodes, |
|
edges: state.edges, |
|
onNodesChange: state.onNodesChange, |
|
onEdgesChange: state.onEdgesChange, |
|
onConnect: state.onConnect, |
|
setNodes: state.setNodes, |
|
onSelectionChange: state.onSelectionChange, |
|
}); |
|
|
|
export const useSelectCanvasData = () => { |
|
|
|
|
|
return useStore(selector); |
|
}; |
|
|
|
export const useHandleDrag = () => { |
|
const handleDragStart = useCallback( |
|
(operatorId: string) => (ev: React.DragEvent<HTMLDivElement>) => { |
|
ev.dataTransfer.setData('application/reactflow', operatorId); |
|
ev.dataTransfer.effectAllowed = 'move'; |
|
}, |
|
[], |
|
); |
|
|
|
return { handleDragStart }; |
|
}; |
|
|
|
export const useHandleDrop = () => { |
|
const addNode = useStore((state) => state.addNode); |
|
const [reactFlowInstance, setReactFlowInstance] = |
|
useState<ReactFlowInstance<any, any>>(); |
|
|
|
const onDragOver = useCallback((event: React.DragEvent<HTMLDivElement>) => { |
|
event.preventDefault(); |
|
event.dataTransfer.dropEffect = 'move'; |
|
}, []); |
|
|
|
const onDrop = useCallback( |
|
(event: React.DragEvent<HTMLDivElement>) => { |
|
event.preventDefault(); |
|
|
|
const type = event.dataTransfer.getData('application/reactflow'); |
|
|
|
|
|
if (typeof type === 'undefined' || !type) { |
|
return; |
|
} |
|
|
|
|
|
|
|
|
|
const position = reactFlowInstance?.screenToFlowPosition({ |
|
x: event.clientX, |
|
y: event.clientY, |
|
}); |
|
const newNode = { |
|
id: uuidv4(), |
|
type: 'textUpdater', |
|
position: position || { |
|
x: 0, |
|
y: 0, |
|
}, |
|
data: { |
|
label: `${type}`, |
|
}, |
|
sourcePosition: Position.Right, |
|
targetPosition: Position.Left, |
|
}; |
|
|
|
addNode(newNode); |
|
}, |
|
[reactFlowInstance, addNode], |
|
); |
|
|
|
return { onDrop, onDragOver, setReactFlowInstance }; |
|
}; |
|
|
|
export const useShowDrawer = () => { |
|
const [clickedNode, setClickedNode] = useState<Node>(); |
|
const { |
|
visible: drawerVisible, |
|
hideModal: hideDrawer, |
|
showModal: showDrawer, |
|
} = useSetModalState(); |
|
|
|
const handleShow = useCallback( |
|
(node: Node) => { |
|
setClickedNode(node); |
|
showDrawer(); |
|
}, |
|
[showDrawer], |
|
); |
|
|
|
return { |
|
drawerVisible, |
|
hideDrawer, |
|
showDrawer: handleShow, |
|
clickedNode, |
|
}; |
|
}; |
|
|
|
export const useHandleKeyUp = () => { |
|
const deleteEdge = useStore((state) => state.deleteEdge); |
|
const handleKeyUp: KeyboardEventHandler = useCallback( |
|
(e) => { |
|
if (e.code === 'Delete') { |
|
deleteEdge(); |
|
} |
|
}, |
|
[deleteEdge], |
|
); |
|
|
|
return { handleKeyUp }; |
|
}; |
|
|
|
export const useSaveGraph = () => { |
|
const { data } = useFetchFlow(); |
|
const { setFlow } = useSetFlow(); |
|
const { id } = useParams(); |
|
const { nodes, edges } = useStore((state) => state); |
|
const saveGraph = useCallback(() => { |
|
const dslComponents = buildDslComponentsByGraph(nodes, edges); |
|
setFlow({ |
|
id, |
|
title: data.title, |
|
dsl: { ...data.dsl, graph: { nodes, edges }, components: dslComponents }, |
|
}); |
|
}, [nodes, edges, setFlow, id, data]); |
|
|
|
return { saveGraph }; |
|
}; |
|
|
|
export const useHandleFormValuesChange = (id?: string) => { |
|
const updateNodeForm = useStore((state) => state.updateNodeForm); |
|
const handleValuesChange = useCallback( |
|
(changedValues: any, values: any) => { |
|
console.info(changedValues, values); |
|
if (id) { |
|
updateNodeForm(id, values); |
|
} |
|
}, |
|
[updateNodeForm, id], |
|
); |
|
|
|
return { handleValuesChange }; |
|
}; |
|
|
|
const useSetGraphInfo = () => { |
|
const { setEdges, setNodes } = useStore((state) => state); |
|
const setGraphInfo = useCallback( |
|
({ nodes = [], edges = [] }: IGraph) => { |
|
if (nodes.length && edges.length) { |
|
setNodes(nodes); |
|
setEdges(edges); |
|
} |
|
}, |
|
[setEdges, setNodes], |
|
); |
|
return setGraphInfo; |
|
}; |
|
|
|
export const useFetchDataOnMount = () => { |
|
const { loading, data } = useFetchFlow(); |
|
const setGraphInfo = useSetGraphInfo(); |
|
|
|
useEffect(() => { |
|
setGraphInfo(data?.dsl?.graph ?? {}); |
|
}, [setGraphInfo, data?.dsl?.graph]); |
|
|
|
useFetchFlowTemplates(); |
|
useFetchLlmList(); |
|
|
|
return { loading, flowDetail: data }; |
|
}; |
|
|
|
export const useFlowIsFetching = () => { |
|
return useIsFetching({ queryKey: ['flowDetail'] }) > 0; |
|
}; |
|
|
|
export const useRunGraph = () => { |
|
const { data } = useFetchFlow(); |
|
const { runFlow } = useRunFlow(); |
|
const { id } = useParams(); |
|
const { nodes, edges } = useStore((state) => state); |
|
const runGraph = useCallback(() => { |
|
const dslComponents = buildDslComponentsByGraph(nodes, edges); |
|
runFlow({ |
|
id: id!!, |
|
dsl: { ...data.dsl, components: dslComponents }, |
|
}); |
|
}, [nodes, edges, runFlow, id, data]); |
|
|
|
return { runGraph }; |
|
}; |
|
|