mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-31 10:53:02 +00:00 
			
		
		
		
	 45deaee762
			
		
	
	
		45deaee762
		
			
		
	
	
	
	
		
			
			Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: Patryk Garstecki <patryk20120@yahoo.pl> Co-authored-by: Sebastian.W <thiner@gmail.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: takatost <takatost@users.noreply.github.com> Co-authored-by: rechardwang <wh_goodjob@163.com> Co-authored-by: Nite Knite <nkCoding@gmail.com> Co-authored-by: Chenhe Gu <guchenhe@gmail.com> Co-authored-by: Joshua <138381132+joshua20231026@users.noreply.github.com> Co-authored-by: Weaxs <459312872@qq.com> Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com> Co-authored-by: leejoo0 <81673835+leejoo0@users.noreply.github.com> Co-authored-by: JzoNg <jzongcode@gmail.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Vikey Chen <vikeytk@gmail.com> Co-authored-by: wanghl <Wang-HL@users.noreply.github.com> Co-authored-by: Haolin Wang-汪皓临 <haolin.wang@atlaslovestravel.com> Co-authored-by: Zixuan Cheng <61724187+Theysua@users.noreply.github.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: Bowen Liang <bowenliang@apache.org> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: fanghongtai <42790567+fanghongtai@users.noreply.github.com> Co-authored-by: wxfanghongtai <wxfanghongtai@gf.com.cn> Co-authored-by: Matri <qjp@bithuman.io> Co-authored-by: Benjamin <benjaminx@gmail.com>
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { useCallback } from 'react'
 | |
| import ELK from 'elkjs/lib/elk.bundled.js'
 | |
| import {
 | |
|   useReactFlow,
 | |
|   useStoreApi,
 | |
| } from 'reactflow'
 | |
| import { cloneDeep } from 'lodash-es'
 | |
| import type {
 | |
|   Edge,
 | |
|   Node,
 | |
| } from '../types'
 | |
| import { useWorkflowStore } from '../store'
 | |
| import { AUTO_LAYOUT_OFFSET } from '../constants'
 | |
| import { useNodesSyncDraft } from './use-nodes-sync-draft'
 | |
| 
 | |
| const layoutOptions = {
 | |
|   'elk.algorithm': 'layered',
 | |
|   'elk.direction': 'RIGHT',
 | |
|   'elk.layered.spacing.nodeNodeBetweenLayers': '60',
 | |
|   'elk.spacing.nodeNode': '40',
 | |
|   'elk.layered.nodePlacement.strategy': 'SIMPLE',
 | |
| }
 | |
| 
 | |
| const elk = new ELK()
 | |
| 
 | |
| export const getLayoutedNodes = async (nodes: Node[], edges: Edge[]) => {
 | |
|   const graph = {
 | |
|     id: 'root',
 | |
|     layoutOptions,
 | |
|     children: nodes.map((n) => {
 | |
|       return {
 | |
|         ...n,
 | |
|         width: n.width ?? 150,
 | |
|         height: n.height ?? 50,
 | |
|         targetPosition: 'left',
 | |
|         sourcePosition: 'right',
 | |
|       }
 | |
|     }),
 | |
|     edges: cloneDeep(edges),
 | |
|   }
 | |
| 
 | |
|   const layoutedGraph = await elk.layout(graph as any)
 | |
|   const layoutedNodes = nodes.map((node) => {
 | |
|     const layoutedNode = layoutedGraph.children?.find(
 | |
|       lgNode => lgNode.id === node.id,
 | |
|     )
 | |
| 
 | |
|     return {
 | |
|       ...node,
 | |
|       position: {
 | |
|         x: (layoutedNode?.x ?? 0) + AUTO_LAYOUT_OFFSET.x,
 | |
|         y: (layoutedNode?.y ?? 0) + AUTO_LAYOUT_OFFSET.y,
 | |
|       },
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   return {
 | |
|     layoutedNodes,
 | |
|   }
 | |
| }
 | |
| 
 | |
| export const useNodesLayout = () => {
 | |
|   const store = useStoreApi()
 | |
|   const reactflow = useReactFlow()
 | |
|   const workflowStore = useWorkflowStore()
 | |
|   const { handleSyncWorkflowDraft } = useNodesSyncDraft()
 | |
| 
 | |
|   const handleNodesLayout = useCallback(async () => {
 | |
|     workflowStore.setState({ nodeAnimation: true })
 | |
|     const {
 | |
|       getNodes,
 | |
|       edges,
 | |
|       setNodes,
 | |
|     } = store.getState()
 | |
|     const { setViewport } = reactflow
 | |
|     const nodes = getNodes()
 | |
|     const {
 | |
|       layoutedNodes,
 | |
|     } = await getLayoutedNodes(nodes, edges)
 | |
| 
 | |
|     setNodes(layoutedNodes)
 | |
|     const zoom = 0.7
 | |
|     setViewport({
 | |
|       x: 0,
 | |
|       y: 0,
 | |
|       zoom,
 | |
|     })
 | |
|     setTimeout(() => {
 | |
|       handleSyncWorkflowDraft()
 | |
|     })
 | |
|   }, [store, reactflow, handleSyncWorkflowDraft, workflowStore])
 | |
| 
 | |
|   return {
 | |
|     handleNodesLayout,
 | |
|   }
 | |
| }
 |