diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseEdge.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseEdge.tsx index 1d74c6064d..cfe4a51107 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseEdge.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseEdge.tsx @@ -1,7 +1,7 @@ import { useTheme } from '@emotion/react'; import { BaseEdge, type EdgeProps } from '@xyflow/react'; import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; -import { useEdgeSelected } from '@/workflow/workflow-diagram/hooks/useEdgeSelected'; +import { useEdgeState } from '@/workflow/workflow-diagram/hooks/useEdgeState'; type WorkflowDiagramBaseEdgeProps = Pick< EdgeProps, @@ -19,11 +19,17 @@ export const WorkflowDiagramBaseEdge = ({ }: WorkflowDiagramBaseEdgeProps) => { const theme = useTheme(); - const { isEdgeSelected } = useEdgeSelected(); + const { isEdgeSelected, isEdgeHovered } = useEdgeState(); const selected = isEdgeSelected({ source, target }); - const stroke = selected ? theme.color.blue : theme.border.color.strong; + const isHovered = isEdgeHovered({ source, target }); + + const stroke = selected + ? theme.color.blue + : isHovered + ? theme.font.color.light + : theme.border.color.strong; return ( , edge: WorkflowDiagramEdge) => { - setEdgeHovered(edge.id); + ( + _: React.MouseEvent, + hoveredEdge: WorkflowDiagramEdge, + ) => { + setEdgeHovered({ + source: hoveredEdge.source, + target: hoveredEdge.target, + }); }, [setEdgeHovered], ); const onEdgeMouseLeave = useCallback(() => { - setNoEdgeHovered(); - }, [setNoEdgeHovered]); + clearEdgeHover(); + }, [clearEdgeHover]); return ( diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx index 5f2847e7d7..25759528e6 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx @@ -1,4 +1,4 @@ -import { useEdgeSelected } from '@/workflow/workflow-diagram/hooks/useEdgeSelected'; +import { useEdgeState } from '@/workflow/workflow-diagram/hooks/useEdgeState'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { type OnSelectionChangeParams, @@ -9,7 +9,7 @@ import { isDefined } from 'twenty-shared/utils'; import { FeatureFlagKey } from '~/generated/graphql'; export const WorkflowDiagramCanvasEditableEffect = () => { - const { setEdgeSelected, clearEdgeSelection } = useEdgeSelected(); + const { setEdgeSelected, clearEdgeSelected } = useEdgeState(); const isWorkflowBranchEnabled = useIsFeatureEnabled( FeatureFlagKey.IS_WORKFLOW_BRANCH_ENABLED, @@ -24,7 +24,8 @@ export const WorkflowDiagramCanvasEditableEffect = () => { const selectedEdge = edges?.[0]; if (!isDefined(selectedEdge)) { - clearEdgeSelection(); + clearEdgeSelected(); + return; } @@ -33,7 +34,7 @@ export const WorkflowDiagramCanvasEditableEffect = () => { target: selectedEdge.target, }); }, - [isWorkflowBranchEnabled, setEdgeSelected, clearEdgeSelection], + [isWorkflowBranchEnabled, setEdgeSelected, clearEdgeSelected], ); useOnSelectionChange({ diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx index 2bd3344add..c9a3c0f1bf 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx @@ -1,4 +1,4 @@ -import { EDGE_BRANCH_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeBranchArrowMarkerId'; +import { EdgeBranchArrowMarker } from '@/workflow/workflow-diagram/constants/EdgeBranchArrowMarker'; import { useTheme } from '@emotion/react'; export const WorkflowDiagramCustomMarkers = () => { @@ -8,7 +8,7 @@ export const WorkflowDiagramCustomMarkers = () => { { fill={theme.background.primary} /> + + + + + + + + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdgeEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdgeEditable.tsx index cd1fa29ae0..94effc288c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdgeEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramDefaultEdgeEditable.tsx @@ -8,7 +8,6 @@ import { WorkflowDiagramEdgeButtonGroup } from '@/workflow/workflow-diagram/comp import { WorkflowDiagramEdgeV2Container } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2Container'; import { WorkflowDiagramEdgeV2VisibilityContainer } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2VisibilityContainer'; import { WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramEdgeOptionsClickOutsideId'; -import { useEdgeHovered } from '@/workflow/workflow-diagram/hooks/useEdgeHovered'; import { useOpenWorkflowEditFilterInCommandMenu } from '@/workflow/workflow-diagram/hooks/useOpenWorkflowEditFilterInCommandMenu'; import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation'; import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; @@ -25,11 +24,11 @@ import { useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; import { IconFilter, IconPlus, IconTrash } from 'twenty-ui/display'; import { FeatureFlagKey } from '~/generated/graphql'; +import { useEdgeState } from '@/workflow/workflow-diagram/hooks/useEdgeState'; type WorkflowDiagramDefaultEdgeEditableProps = EdgeProps; export const WorkflowDiagramDefaultEdgeEditable = ({ - id, source, target, sourceX, @@ -45,7 +44,7 @@ export const WorkflowDiagramDefaultEdgeEditable = ({ const { isInRightDrawer } = useContext(ActionMenuContext); - const { isEdgeHovered } = useEdgeHovered(); + const { isEdgeHovered } = useEdgeState(); const [edgePath, labelX, labelY] = getBezierPath({ sourceX, @@ -129,7 +128,9 @@ export const WorkflowDiagramDefaultEdgeEditable = ({ labelY={labelY} > { - const [workflowHoveredEdgeId, setWorkflowHoveredEdgeId] = - useRecoilComponentState(workflowHoveredEdgeIdComponentState); - - const isEdgeHovered = (edgeId: string) => { - return workflowHoveredEdgeId === edgeId; - }; - - const setEdgeHovered = (edgeId: string) => { - setWorkflowHoveredEdgeId(edgeId); - }; - - const setNoEdgeHovered = () => { - setWorkflowHoveredEdgeId(undefined); - }; - - return { - isEdgeHovered, - setEdgeHovered, - setNoEdgeHovered, - }; -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeSelected.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeSelected.ts deleted file mode 100644 index 4d45a2afe4..0000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeSelected.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { workflowSelectedEdgeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedEdgeComponentState'; -import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; -import { type WorkflowDiagramHandlesSelected } from '@/workflow/workflow-diagram/types/WorkflowDiagramHandlesSelected'; -import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge'; - -export const useEdgeSelected = () => { - const [workflowSelectedEdge, setWorkflowSelectedEdge] = - useRecoilComponentState(workflowSelectedEdgeComponentState); - - const isEdgeSelected = ({ source, target }: WorkflowDiagramEdge) => { - return ( - workflowSelectedEdge?.source === source && - workflowSelectedEdge?.target === target - ); - }; - - const getNodeHandlesSelectedState = ( - id: string, - ): WorkflowDiagramHandlesSelected => { - return { - targetHandle: workflowSelectedEdge?.target === id, - sourceHandle: workflowSelectedEdge?.source === id, - }; - }; - - const setEdgeSelected = ({ source, target }: WorkflowDiagramEdge) => { - if ( - workflowSelectedEdge?.source === source && - workflowSelectedEdge?.target === target - ) { - return; - } - - setWorkflowSelectedEdge({ source, target }); - }; - - const clearEdgeSelection = () => { - setWorkflowSelectedEdge(undefined); - }; - - return { - isEdgeSelected, - setEdgeSelected, - clearEdgeSelection, - getNodeHandlesSelectedState, - }; -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeState.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeState.ts new file mode 100644 index 0000000000..8eb326ea5c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useEdgeState.ts @@ -0,0 +1,132 @@ +import { workflowSelectedEdgeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedEdgeComponentState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; +import { type WorkflowDiagramNodeHandles } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeHandles'; +import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge'; +import { workflowHoveredEdgeComponentState } from '@/workflow/workflow-diagram/states/workflowHoveredEdgeComponentState'; +import { useReactFlow } from '@xyflow/react'; +import { EdgeBranchArrowMarker } from '@/workflow/workflow-diagram/constants/EdgeBranchArrowMarker'; + +export const useEdgeState = () => { + const reactflow = useReactFlow(); + + const [workflowSelectedEdge, setWorkflowSelectedEdge] = + useRecoilComponentState(workflowSelectedEdgeComponentState); + + const [workflowHoveredEdge, setWorkflowHoveredEdge] = useRecoilComponentState( + workflowHoveredEdgeComponentState, + ); + + const isEdgeSelected = ({ source, target }: WorkflowDiagramEdge) => { + return ( + workflowSelectedEdge?.source === source && + workflowSelectedEdge?.target === target + ); + }; + + const isEdgeHovered = ({ source, target }: WorkflowDiagramEdge) => { + return ( + workflowHoveredEdge?.source === source && + workflowHoveredEdge?.target === target + ); + }; + + const getNodeHandlesSelectedState = ( + id: string, + ): WorkflowDiagramNodeHandles => { + return { + targetHandle: workflowSelectedEdge?.target === id, + sourceHandle: workflowSelectedEdge?.source === id, + }; + }; + + const getNodeHandlesHoveredState = ( + id: string, + ): WorkflowDiagramNodeHandles => { + return { + targetHandle: workflowHoveredEdge?.target === id, + sourceHandle: workflowHoveredEdge?.source === id, + }; + }; + + const setEdgeSelected = ({ source, target }: WorkflowDiagramEdge) => { + if ( + workflowSelectedEdge?.source === source && + workflowSelectedEdge?.target === target + ) { + return; + } + + setWorkflowSelectedEdge({ source, target }); + + reactflow.setEdges((edges) => + edges.map((edge) => ({ + ...edge, + markerEnd: + edge.source === source && edge.target === target + ? EdgeBranchArrowMarker.Selected + : EdgeBranchArrowMarker.Default, + })), + ); + }; + + const setEdgeHovered = ({ source, target }: WorkflowDiagramEdge) => { + if ( + workflowHoveredEdge?.source === source && + workflowHoveredEdge?.target === target + ) { + return; + } + + setWorkflowHoveredEdge({ source, target }); + + reactflow.setEdges((edges) => + edges.map((edge) => + edge.source === source && + edge.target === target && + edge.markerEnd !== EdgeBranchArrowMarker.Selected + ? { + ...edge, + markerEnd: EdgeBranchArrowMarker.Hover, + } + : edge, + ), + ); + }; + + const clearEdgeSelected = () => { + setWorkflowSelectedEdge(undefined); + + reactflow.setEdges((edges) => + edges.map((edge) => ({ + ...edge, + markerEnd: EdgeBranchArrowMarker.Default, + })), + ); + }; + + const clearEdgeHover = () => { + setWorkflowHoveredEdge(undefined); + + reactflow.setEdges((edges) => + edges.map((edge) => + edge.markerEnd === EdgeBranchArrowMarker.Hover + ? { + ...edge, + markerEnd: EdgeBranchArrowMarker.Default, + } + : edge, + ), + ); + }; + + return { + isEdgeSelected, + setEdgeSelected, + clearEdgeSelected, + getNodeHandlesSelectedState, + isEdgeHovered, + setEdgeHovered, + clearEdgeHover, + getNodeHandlesHoveredState, + }; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeIdComponentState.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeComponentState.ts similarity index 59% rename from packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeIdComponentState.ts rename to packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeComponentState.ts index c7c7e80f52..e9473b6444 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeIdComponentState.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/states/workflowHoveredEdgeComponentState.ts @@ -1,10 +1,11 @@ import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext'; +import type { WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge'; -export const workflowHoveredEdgeIdComponentState = createComponentState< - string | undefined +export const workflowHoveredEdgeComponentState = createComponentState< + WorkflowDiagramEdge | undefined >({ - key: 'workflowHoveredEdgeIdComponentState', + key: 'workflowHoveredEdgeComponentState', defaultValue: undefined, componentInstanceContext: WorkflowVisualizerComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramHandlesSelected.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramNodeHandles.ts similarity index 53% rename from packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramHandlesSelected.ts rename to packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramNodeHandles.ts index 17362dd078..173727a08e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramHandlesSelected.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramNodeHandles.ts @@ -1,4 +1,4 @@ -export type WorkflowDiagramHandlesSelected = { +export type WorkflowDiagramNodeHandles = { targetHandle: boolean; sourceHandle: boolean; }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/generateWorkflowRunDiagram.test.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/generateWorkflowRunDiagram.test.ts index 66353e1798..84d841b121 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/generateWorkflowRunDiagram.test.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/generateWorkflowRunDiagram.test.ts @@ -119,7 +119,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-0", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "trigger", @@ -133,7 +133,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-1", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step1", @@ -147,7 +147,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-2", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step2", @@ -349,7 +349,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-3", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "trigger", @@ -363,7 +363,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-4", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step1", @@ -377,7 +377,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-5", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step2", @@ -579,7 +579,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-6", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "trigger", @@ -593,7 +593,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-7", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step1", @@ -607,7 +607,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-8", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step2", @@ -828,7 +828,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-9", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "trigger", @@ -842,7 +842,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-10", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step1", @@ -856,7 +856,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-11", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step2", @@ -870,7 +870,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-12", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "step3", @@ -1057,7 +1057,7 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-13", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": false, "source": "trigger", diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/getWorkflowVersionDiagram.test.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/getWorkflowVersionDiagram.test.ts index b6d05d2e9a..d31685087c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/getWorkflowVersionDiagram.test.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/__tests__/getWorkflowVersionDiagram.test.ts @@ -157,7 +157,7 @@ describe('getWorkflowVersionDiagram', () => { }, "deletable": true, "id": "8f3b2121-f194-4ba4-9fbf-0", - "markerEnd": "workflow-edge-branch-arrow", + "markerEnd": "edge-branch-arrow-default", "markerStart": undefined, "selectable": true, "source": "trigger", diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramFilterEdgeEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramFilterEdgeEditable.tsx index 0e2dd72f68..b73b2d3d1c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramFilterEdgeEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramFilterEdgeEditable.tsx @@ -14,7 +14,6 @@ import { WorkflowDiagramEdgeButtonGroup } from '@/workflow/workflow-diagram/comp import { WorkflowDiagramEdgeV2Container } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2Container'; import { WorkflowDiagramEdgeV2VisibilityContainer } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2VisibilityContainer'; import { WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramEdgeOptionsClickOutsideId'; -import { useEdgeHovered } from '@/workflow/workflow-diagram/hooks/useEdgeHovered'; import { useOpenWorkflowEditFilterInCommandMenu } from '@/workflow/workflow-diagram/hooks/useOpenWorkflowEditFilterInCommandMenu'; import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation'; import { workflowDiagramPanOnDragComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramPanOnDragComponentState'; @@ -48,6 +47,7 @@ import { import { IconButtonGroup } from 'twenty-ui/input'; import { MenuItem } from 'twenty-ui/navigation'; import { FeatureFlagKey } from '~/generated/graphql'; +import { useEdgeState } from '@/workflow/workflow-diagram/hooks/useEdgeState'; type WorkflowDiagramFilterEdgeEditableProps = EdgeProps; @@ -80,7 +80,6 @@ const StyledConfiguredFilterContainer = styled.div` `; export const WorkflowDiagramFilterEdgeEditable = ({ - id, source, target, sourceY, @@ -118,7 +117,7 @@ export const WorkflowDiagramFilterEdgeEditable = ({ const { openDropdown } = useOpenDropdown(); const { closeDropdown } = useCloseDropdown(); - const { isEdgeHovered } = useEdgeHovered(); + const { isEdgeHovered } = useEdgeState(); const setWorkflowDiagramPanOnDrag = useSetRecoilComponentState( workflowDiagramPanOnDragComponentState, @@ -197,7 +196,9 @@ export const WorkflowDiagramFilterEdgeEditable = ({ > - {isEdgeHovered(id) || isDropdownOpen || nodeCreationStarted ? ( + {isEdgeHovered({ source, target }) || + isDropdownOpen || + nodeCreationStarted ? ( - prop !== 'disableHoverEffect' && prop !== 'selected', + prop !== 'disableHoverEffect' && prop !== 'selected' && prop !== 'hovered', })<{ disableHoverEffect: boolean; selected: boolean; + hovered?: boolean; }>` &.react-flow__handle { height: ${NODE_HANDLE_HEIGHT_PX}px; width: ${NODE_HANDLE_WIDTH_PX}px; - border-color: ${({ theme, selected }) => - selected ? theme.color.blue : theme.border.color.strong}; + border-color: ${({ theme, selected, hovered }) => + selected + ? theme.color.blue + : hovered + ? theme.font.color.light + : theme.border.color.strong}; background: ${({ theme, selected }) => selected ? theme.adaptiveColors.blue1 : theme.background.primary}; transition: @@ -79,6 +85,7 @@ export const WorkflowDiagramHandleEditable = ({ type, position, selected, + hovered = false, }: WorkflowDiagramHandleEditableProps) => { const isWorkflowBranchEnabled = useIsFeatureEnabled( FeatureFlagKey.IS_WORKFLOW_BRANCH_ENABLED, @@ -90,6 +97,7 @@ export const WorkflowDiagramHandleEditable = ({ position={position} disableHoverEffect={!isWorkflowBranchEnabled} selected={selected} + hovered={hovered} /> ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx index fa55fdea94..05b5b819eb 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx @@ -1,6 +1,6 @@ import { WorkflowDiagramCreateStepElement } from '@/workflow/workflow-diagram/components/WorkflowDiagramCreateStepElement'; import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId'; -import { useEdgeSelected } from '@/workflow/workflow-diagram/hooks/useEdgeSelected'; +import { useEdgeState } from '@/workflow/workflow-diagram/hooks/useEdgeState'; import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation'; import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { type WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant'; @@ -100,10 +100,13 @@ export const WorkflowDiagramStepNodeEditableContent = ({ const { isNodeCreationStarted } = useStartNodeCreation(); - const { getNodeHandlesSelectedState } = useEdgeSelected(); + const { getNodeHandlesSelectedState, getNodeHandlesHoveredState } = + useEdgeState(); const handlesSelectedState = getNodeHandlesSelectedState(id); + const handlesHoveredState = getNodeHandlesHoveredState(id); + return ( <> {data.nodeType !== 'trigger' && ( @@ -111,6 +114,7 @@ export const WorkflowDiagramStepNodeEditableContent = ({ type="target" position={Position.Top} selected={handlesSelectedState.targetHandle} + hovered={handlesHoveredState.targetHandle} /> )} @@ -161,6 +165,7 @@ export const WorkflowDiagramStepNodeEditableContent = ({ type="source" position={Position.Bottom} selected={handlesSelectedState.sourceHandle || selected} + hovered={handlesHoveredState.sourceHandle} /> );