This commit is contained in:
StyleZhang
2024-03-01 14:28:40 +08:00
parent 74d26764f8
commit 0acb2db9b6
7 changed files with 103 additions and 21 deletions

View File

@ -8,13 +8,13 @@ const initialNodes = [
{
id: '1',
type: 'custom',
position: { x: 130, y: 130 },
position: { x: 0, y: 0 },
data: { type: 'start' },
},
{
id: '2',
type: 'custom',
position: { x: 434, y: 130 },
position: { x: 0, y: 0 },
data: {
type: 'if-else',
branches: [
@ -32,21 +32,28 @@ const initialNodes = [
{
id: '3',
type: 'custom',
position: { x: 738, y: 130 },
position: { x: 0, y: 0 },
data: { type: 'question-classifier', sortIndexInBranches: 0 },
},
{
id: '4',
type: 'custom',
position: { x: 738, y: 330 },
data: { type: 'variable-assigner', sortIndexInBranches: 1 },
position: { x: 0, y: 0 },
data: {
type: 'if-else',
sortIndexInBranches: 1,
branches: [
{
id: 'if-true',
name: 'IS TRUE',
},
{
id: 'if-false',
name: 'IS FALSE',
},
],
},
},
// {
// id: '5',
// type: 'custom',
// position: { x: 1100, y: 130 },
// data: { type: 'llm' },
// },
]
const initialEdges = [
@ -57,7 +64,6 @@ const initialEdges = [
sourceHandle: 'source',
target: '2',
targetHandle: 'target',
deletable: false,
},
{
id: '1',

View File

@ -16,10 +16,32 @@ import type {
SelectedNode,
} from './types'
import { NodeInitialData } from './constants'
import { getLayoutByDagre } from './utils'
export const useWorkflow = () => {
const store = useStoreApi()
const handleLayout = useCallback(async () => {
const {
getNodes,
edges,
setNodes,
} = store.getState()
const layout = getLayoutByDagre(getNodes(), edges)
const newNodes = produce(getNodes(), (draft) => {
draft.forEach((node) => {
const nodeWithPosition = layout.node(node.id)
node.position = {
x: nodeWithPosition.x,
y: nodeWithPosition.y,
}
})
})
setNodes(newNodes)
}, [store])
const handleEnterNode = useCallback<NodeMouseHandler>((_, node) => {
const {
getNodes,
@ -112,7 +134,8 @@ export const useWorkflow = () => {
return filtered
})
setEdges(newEdges)
}, [store])
handleLayout()
}, [store, handleLayout])
const handleEnterEdge = useCallback<EdgeMouseHandler>((_, edge) => {
const {
@ -152,7 +175,8 @@ export const useWorkflow = () => {
draft.splice(index, 1)
})
setEdges(newEdges)
}, [store])
handleLayout()
}, [store, handleLayout])
const handleUpdateNodeData = useCallback(({ id, data }: SelectedNode) => {
const {
@ -182,7 +206,7 @@ export const useWorkflow = () => {
data: NodeInitialData[nodeType],
position: {
x: currentNode.position.x + 304,
y: currentNode.position.y,
y: 0,
},
selected: true,
}
@ -289,5 +313,6 @@ export const useWorkflow = () => {
handleAddNextNode,
handleChangeCurrentNode,
handleDeleteNode,
handleLayout,
}
}

View File

@ -9,6 +9,7 @@ import ReactFlow, {
useNodesState,
} from 'reactflow'
import 'reactflow/dist/style.css'
import './style.css'
import type {
Edge,
Node,
@ -41,11 +42,6 @@ const Workflow: FC<WorkflowProps> = memo(({
const [edges, _, onEdgesChange] = useEdgesState(initialEdges)
const nodesInitialized = useNodesInitialized()
useEffect(() => {
if (nodesInitialized)
console.log('initialed')
}, [nodesInitialized])
const {
handleEnterNode,
handleLeaveNode,
@ -53,8 +49,14 @@ const Workflow: FC<WorkflowProps> = memo(({
handleEnterEdge,
handleLeaveEdge,
handleDeleteEdge,
handleLayout,
} = useWorkflow()
useEffect(() => {
if (nodesInitialized)
handleLayout()
}, [nodesInitialized, handleLayout])
useKeyPress('Backspace', handleDeleteEdge)
return (

View File

@ -0,0 +1,3 @@
.react-flow__node {
transition: transform 0.2s ease-in-out;
}

View File

@ -3,6 +3,7 @@ import {
getConnectedEdges,
getOutgoers,
} from 'reactflow'
import dagre from 'dagre'
import type {
Edge,
Node,
@ -118,3 +119,26 @@ export const getNodesPositionMap = (nodes: Node[], edges: Edge[]) => {
return positionMap
}
export const getLayoutByDagre = (nodes: Node[], edges: Edge[]) => {
const dagreGraph = new dagre.graphlib.Graph()
dagreGraph.setGraph({
rankdir: 'LR',
align: 'UL',
nodesep: 40,
ranksep: 64,
})
nodes.forEach((node) => {
dagreGraph.setNode(node.id, { width: node.width, height: node.height })
})
edges.forEach((edge) => {
dagreGraph.setEdge(edge.source, edge.target, {
weight: edge?.data?.weight || 1,
})
})
dagre.layout(dagreGraph)
return dagreGraph
}