| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   memo, | 
					
						
							|  |  |  |   useCallback, | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |   useMemo, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   useState, | 
					
						
							|  |  |  | } from 'react' | 
					
						
							|  |  |  | import { intersection } from 'lodash-es' | 
					
						
							|  |  |  | import type { EdgeProps } from 'reactflow' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   BaseEdge, | 
					
						
							|  |  |  |   EdgeLabelRenderer, | 
					
						
							|  |  |  |   Position, | 
					
						
							| 
									
										
										
										
											2024-04-15 15:49:40 +08:00
										 |  |  |   getBezierPath, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | } from 'reactflow' | 
					
						
							|  |  |  | import { | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |   useAvailableBlocks, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   useNodesInteractions, | 
					
						
							|  |  |  | } from './hooks' | 
					
						
							|  |  |  | import BlockSelector from './block-selector' | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  |   Edge, | 
					
						
							|  |  |  |   OnSelectBlock, | 
					
						
							|  |  |  | } from './types' | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  | import { NodeRunningStatus } from './types' | 
					
						
							|  |  |  | import { getEdgeColor } from './utils' | 
					
						
							| 
									
										
										
										
											2025-03-05 17:41:15 +08:00
										 |  |  | import { ITERATION_CHILDREN_Z_INDEX, LOOP_CHILDREN_Z_INDEX } from './constants' | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  | import CustomEdgeLinearGradientRender from './custom-edge-linear-gradient-render' | 
					
						
							| 
									
										
										
										
											2024-07-09 15:05:40 +08:00
										 |  |  | import cn from '@/utils/classnames' | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  | import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const CustomEdge = ({ | 
					
						
							|  |  |  |   id, | 
					
						
							|  |  |  |   data, | 
					
						
							|  |  |  |   source, | 
					
						
							|  |  |  |   sourceHandleId, | 
					
						
							|  |  |  |   target, | 
					
						
							|  |  |  |   targetHandleId, | 
					
						
							|  |  |  |   sourceX, | 
					
						
							|  |  |  |   sourceY, | 
					
						
							|  |  |  |   targetX, | 
					
						
							|  |  |  |   targetY, | 
					
						
							|  |  |  |   selected, | 
					
						
							|  |  |  | }: EdgeProps) => { | 
					
						
							|  |  |  |   const [ | 
					
						
							|  |  |  |     edgePath, | 
					
						
							|  |  |  |     labelX, | 
					
						
							|  |  |  |     labelY, | 
					
						
							| 
									
										
										
										
											2024-04-15 15:49:40 +08:00
										 |  |  |   ] = getBezierPath({ | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |     sourceX: sourceX - 8, | 
					
						
							|  |  |  |     sourceY, | 
					
						
							|  |  |  |     sourcePosition: Position.Right, | 
					
						
							|  |  |  |     targetX: targetX + 8, | 
					
						
							|  |  |  |     targetY, | 
					
						
							|  |  |  |     targetPosition: Position.Left, | 
					
						
							| 
									
										
										
										
											2024-04-15 15:49:40 +08:00
										 |  |  |     curvature: 0.16, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  |   const [open, setOpen] = useState(false) | 
					
						
							|  |  |  |   const { handleNodeAdd } = useNodesInteractions() | 
					
						
							| 
									
										
										
										
											2025-03-05 17:41:15 +08:00
										 |  |  |   const { availablePrevBlocks } = useAvailableBlocks((data as Edge['data'])!.targetType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop) | 
					
						
							|  |  |  |   const { availableNextBlocks } = useAvailableBlocks((data as Edge['data'])!.sourceType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop) | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |   const { | 
					
						
							|  |  |  |     _sourceRunningStatus, | 
					
						
							|  |  |  |     _targetRunningStatus, | 
					
						
							|  |  |  |   } = data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const linearGradientId = useMemo(() => { | 
					
						
							|  |  |  |     if ( | 
					
						
							|  |  |  |       ( | 
					
						
							|  |  |  |         _sourceRunningStatus === NodeRunningStatus.Succeeded | 
					
						
							|  |  |  |         || _sourceRunningStatus === NodeRunningStatus.Failed | 
					
						
							|  |  |  |         || _sourceRunningStatus === NodeRunningStatus.Exception | 
					
						
							|  |  |  |       ) && ( | 
					
						
							|  |  |  |         _targetRunningStatus === NodeRunningStatus.Succeeded | 
					
						
							|  |  |  |         || _targetRunningStatus === NodeRunningStatus.Failed | 
					
						
							|  |  |  |         || _targetRunningStatus === NodeRunningStatus.Exception | 
					
						
							|  |  |  |         || _targetRunningStatus === NodeRunningStatus.Running | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |       return id | 
					
						
							|  |  |  |   }, [_sourceRunningStatus, _targetRunningStatus, id]) | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   const handleOpenChange = useCallback((v: boolean) => { | 
					
						
							|  |  |  |     setOpen(v) | 
					
						
							|  |  |  |   }, []) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleInsert = useCallback<OnSelectBlock>((nodeType, toolDefaultValue) => { | 
					
						
							|  |  |  |     handleNodeAdd( | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         nodeType, | 
					
						
							|  |  |  |         toolDefaultValue, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         prevNodeId: source, | 
					
						
							|  |  |  |         prevNodeSourceHandle: sourceHandleId || 'source', | 
					
						
							|  |  |  |         nextNodeId: target, | 
					
						
							|  |  |  |         nextNodeTargetHandle: targetHandleId || 'target', | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |   }, [handleNodeAdd, source, sourceHandleId, target, targetHandleId]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |   const stroke = useMemo(() => { | 
					
						
							|  |  |  |     if (selected) | 
					
						
							|  |  |  |       return getEdgeColor(NodeRunningStatus.Running) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (linearGradientId) | 
					
						
							|  |  |  |       return `url(#${linearGradientId})` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data?._connectedNodeIsHovering) | 
					
						
							|  |  |  |       return getEdgeColor(NodeRunningStatus.Running, sourceHandleId === ErrorHandleTypeEnum.failBranch) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return getEdgeColor() | 
					
						
							|  |  |  |   }, [data._connectedNodeIsHovering, linearGradientId, selected, sourceHandleId]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   return ( | 
					
						
							|  |  |  |     <> | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |       { | 
					
						
							|  |  |  |         linearGradientId && ( | 
					
						
							|  |  |  |           <CustomEdgeLinearGradientRender | 
					
						
							|  |  |  |             id={linearGradientId} | 
					
						
							|  |  |  |             startColor={getEdgeColor(_sourceRunningStatus)} | 
					
						
							|  |  |  |             stopColor={getEdgeColor(_targetRunningStatus)} | 
					
						
							|  |  |  |             position={{ | 
					
						
							|  |  |  |               x1: sourceX, | 
					
						
							|  |  |  |               y1: sourceY, | 
					
						
							|  |  |  |               x2: targetX, | 
					
						
							|  |  |  |               y2: targetY, | 
					
						
							|  |  |  |             }} | 
					
						
							|  |  |  |           /> | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |       <BaseEdge | 
					
						
							|  |  |  |         id={id} | 
					
						
							|  |  |  |         path={edgePath} | 
					
						
							|  |  |  |         style={{ | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |           stroke, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |           strokeWidth: 2, | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |           opacity: data._waitingRun ? 0.7 : 1, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         }} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |       <EdgeLabelRenderer> | 
					
						
							|  |  |  |         <div | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |           className={cn( | 
					
						
							|  |  |  |             'nopan nodrag hover:scale-125', | 
					
						
							|  |  |  |             data?._hovering ? 'block' : 'hidden', | 
					
						
							|  |  |  |             open && '!block', | 
					
						
							|  |  |  |             data.isInIteration && `z-[${ITERATION_CHILDREN_Z_INDEX}]`, | 
					
						
							| 
									
										
										
										
											2025-03-05 17:41:15 +08:00
										 |  |  |             data.isInLoop && `z-[${LOOP_CHILDREN_Z_INDEX}]`, | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |           )} | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |           style={{ | 
					
						
							|  |  |  |             position: 'absolute', | 
					
						
							|  |  |  |             transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`, | 
					
						
							|  |  |  |             pointerEvents: 'all', | 
					
						
							| 
									
										
										
										
											2024-12-11 14:21:38 +08:00
										 |  |  |             opacity: data._waitingRun ? 0.7 : 1, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |           }} | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <BlockSelector | 
					
						
							|  |  |  |             open={open} | 
					
						
							|  |  |  |             onOpenChange={handleOpenChange} | 
					
						
							|  |  |  |             asChild | 
					
						
							|  |  |  |             onSelect={handleInsert} | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |             availableBlocksTypes={intersection(availablePrevBlocks, availableNextBlocks)} | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             triggerClassName={() => 'hover:scale-150 transition-all'} | 
					
						
							|  |  |  |           /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </EdgeLabelRenderer> | 
					
						
							|  |  |  |     </> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default memo(CustomEdge) |