From b6c683a1b8522b046d6e9b1282b5cf42ee27b120 Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Fri, 23 Feb 2024 17:19:35 +0800 Subject: [PATCH] next step --- web/app/(commonLayout)/workflow/page.tsx | 2 +- web/app/components/workflow/custom-edge.tsx | 3 +- web/app/components/workflow/hooks.ts | 44 +++++++++- web/app/components/workflow/index.tsx | 4 + .../nodes/_base/components/next-step.tsx | 87 +++++++++++++++++-- 5 files changed, 130 insertions(+), 10 deletions(-) diff --git a/web/app/(commonLayout)/workflow/page.tsx b/web/app/(commonLayout)/workflow/page.tsx index 06fd21b02d..b9f19457f7 100644 --- a/web/app/(commonLayout)/workflow/page.tsx +++ b/web/app/(commonLayout)/workflow/page.tsx @@ -15,7 +15,7 @@ const initialNodes = [ id: '2', type: 'custom', position: { x: 434, y: 130 }, - data: { type: 'code' }, + data: { type: 'if-else' }, }, { id: '3', diff --git a/web/app/components/workflow/custom-edge.tsx b/web/app/components/workflow/custom-edge.tsx index 9fb652e2ac..f656fb43c4 100644 --- a/web/app/components/workflow/custom-edge.tsx +++ b/web/app/components/workflow/custom-edge.tsx @@ -17,7 +17,6 @@ const CustomEdge = ({ targetY, selected, }: EdgeProps) => { - console.log() const [ edgePath, labelX, @@ -37,7 +36,7 @@ const CustomEdge = ({ id={id} path={edgePath} style={{ - stroke: selected ? '#2970FF' : '#D0D5DD', + stroke: (selected || data?.connectedNodeIsHovering) ? '#2970FF' : '#D0D5DD', strokeWidth: 2, }} /> diff --git a/web/app/components/workflow/hooks.ts b/web/app/components/workflow/hooks.ts index 5aa0e06a93..5449ba2a8d 100644 --- a/web/app/components/workflow/hooks.ts +++ b/web/app/components/workflow/hooks.ts @@ -1,7 +1,13 @@ import { useCallback } from 'react' import produce from 'immer' -import type { EdgeMouseHandler } from 'reactflow' -import { useStoreApi } from 'reactflow' +import type { + EdgeMouseHandler, + NodeMouseHandler, +} from 'reactflow' +import { + getConnectedEdges, + useStoreApi, +} from 'reactflow' import type { SelectedNode } from './types' import { useStore } from './store' @@ -9,6 +15,38 @@ export const useWorkflow = () => { const store = useStoreApi() const setSelectedNode = useStore(state => state.setSelectedNode) + const handleEnterNode = useCallback((_, node) => { + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const connectedEdges = getConnectedEdges([node], edges) + + connectedEdges.forEach((edge) => { + const currentEdge = draft.find(e => e.id === edge.id) + if (currentEdge) + currentEdge.data = { ...currentEdge.data, connectedNodeIsHovering: true } + }) + }) + setEdges(newEdges) + }, [store]) + const handleLeaveNode = useCallback((_, node) => { + const { + edges, + setEdges, + } = store.getState() + const newEdges = produce(edges, (draft) => { + const connectedEdges = getConnectedEdges([node], edges) + + connectedEdges.forEach((edge) => { + const currentEdge = draft.find(e => e.id === edge.id) + if (currentEdge) + currentEdge.data = { ...currentEdge.data, connectedNodeIsHovering: false } + }) + }) + setEdges(newEdges) + }, [store]) const handleEnterEdge = useCallback((_, edge) => { const { edges, @@ -61,6 +99,8 @@ export const useWorkflow = () => { }, [setSelectedNode, store]) return { + handleEnterNode, + handleLeaveNode, handleEnterEdge, handleLeaveEdge, handleSelectNode, diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 4abe22a56b..fe5a6199a9 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -37,6 +37,8 @@ const Workflow: FC = memo(({ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges) const { + handleEnterNode, + handleLeaveNode, handleEnterEdge, handleLeaveEdge, handleSelectNode, @@ -61,6 +63,8 @@ const Workflow: FC = memo(({ edgeTypes={edgeTypes} nodes={nodes} edges={edges} + onNodeMouseEnter={handleEnterNode} + onNodeMouseLeave={handleLeaveNode} onEdgesChange={onEdgesChange} onEdgeMouseEnter={handleEnterEdge} onEdgeMouseLeave={handleLeaveEdge} diff --git a/web/app/components/workflow/nodes/_base/components/next-step.tsx b/web/app/components/workflow/nodes/_base/components/next-step.tsx index 8b59f0e979..4d8626863f 100644 --- a/web/app/components/workflow/nodes/_base/components/next-step.tsx +++ b/web/app/components/workflow/nodes/_base/components/next-step.tsx @@ -2,23 +2,27 @@ import { memo, useCallback, } from 'react' +import { + getOutgoers, + useStoreApi, +} from 'reactflow' import BlockIcon from '../../../block-icon' import type { Node } from '../../../types' -import { BlockEnum } from '../../../types' import { useStore } from '../../../store' import BlockSelector from '../../../block-selector' import { Plus } from '@/app/components/base/icons/src/vender/line/general' import Button from '@/app/components/base/button' const NextStep = () => { + const store = useStoreApi() const selectedNode = useStore(state => state.selectedNode) - const outgoers: Node[] = [] + const outgoers: Node[] = getOutgoers(selectedNode as Node, store.getState().getNodes(), store.getState().edges) const renderAddNextNodeTrigger = useCallback((open: boolean) => { return (
{
-
+ + { + (!outgoers.length || outgoers.length === 1) && ( + + + + + + ) + } + { + outgoers.length > 1 && ( + + { + Array(outgoers.length + 1).fill(0).map((_, index) => ( + + { + index === 0 && ( + + ) + } + { + index > 0 && ( + + ) + } + + + )) + } + + + ) + } +
{ !!outgoers.length && outgoers.map(outgoer => ( @@ -76,7 +153,7 @@ const NextStep = () => { )) } { - (!outgoers.length || selectedNode!.data.type === BlockEnum.IfElse) && ( + (!outgoers.length || outgoers.length > 1) && ( {}} placement='top'