From 36fcb29e86b4de1c66088318948d98b5957ead2c Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Thu, 14 Aug 2025 10:05:42 +0200 Subject: [PATCH] Implement proper arrows between nodes for workflows and workflow versions (#13909) > [!IMPORTANT] > We still have to implement the new arrows for **workflow runs**. I kept the old arrows because they currently indicate the success state of an execution. In the new version, arrows will all look the same, regardless of the execution state of the previous node, so we'll be able to use the same arrows everywhere. ## Workflows You can see that arrows start from the right spot and end just above the target node. **We will soon remove the round top handle, and the arrow will gently touch the top of the node.** https://github.com/user-attachments/assets/febd5f49-393f-4d97-addc-bede5cf6944a ## Workflow versions https://github.com/user-attachments/assets/e519850f-abd9-4d75-8337-c4c44a2dbfed Closes https://github.com/twentyhq/core-team-issues/issues/1369 --- .../WorkflowDiagramCustomMarkers.tsx | 23 ++++---- .../WorkflowDiagramStepNodeReadonly.tsx | 2 +- .../components/WorkflowRunDiagramBaseEdge.tsx | 8 ++- .../constants/EdgeBranchArrowMarkerId.ts | 1 + .../constants/EdgeGrayCircleMarkedId.ts | 1 - ...kflowVisualizerEdgeDefaultConfiguration.ts | 7 +-- .../generateWorkflowRunDiagram.test.ts | 56 +++++++++---------- .../getWorkflowVersionDiagram.test.ts | 4 +- 8 files changed, 50 insertions(+), 52 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeBranchArrowMarkerId.ts delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeGrayCircleMarkedId.ts 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 b2e2dd5adf..fd85b03806 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,10 +1,8 @@ -import { EDGE_GRAY_CIRCLE_MARKED_ID } from '@/workflow/workflow-diagram/constants/EdgeGrayCircleMarkedId'; +import { EDGE_BRANCH_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeBranchArrowMarkerId'; import { EDGE_GREEN_CIRCLE_MARKED_ID } from '@/workflow/workflow-diagram/constants/EdgeGreenCircleMarkedId'; import { EDGE_GREEN_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeGreenRoundedArrowMarkerId'; import { EDGE_GREEN_ROUNDED_ARROW_MARKER_WIDTH_PX } from '@/workflow/workflow-diagram/constants/EdgeGreenRoundedArrowMarkerWidthPx'; import { EDGE_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId'; -import { NODE_HANDLE_HEIGHT_PX } from '@/workflow/workflow-diagram/constants/NodeHandleHeightPx'; -import { NODE_HANDLE_WIDTH_PX } from '@/workflow/workflow-diagram/constants/NodeHandleWidthPx'; import { useTheme } from '@emotion/react'; export const WorkflowDiagramCustomMarkers = () => { @@ -40,17 +38,16 @@ export const WorkflowDiagramCustomMarkers = () => { - diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx index 7264da8762..5f40e8f994 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx @@ -51,7 +51,7 @@ export const WorkflowDiagramStepNodeReadonly = ({ variant={getNodeVariantFromStepRunStatus(data.runStatus)} nodeType={data.nodeType} Icon={} - displayHandle={false} + displayHandle onClick={() => { if ( !isDefined(workflowVisualizerWorkflowId) || diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramBaseEdge.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramBaseEdge.tsx index 665b1e6b4e..fa6deab9be 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramBaseEdge.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramBaseEdge.tsx @@ -1,9 +1,9 @@ -import { EDGE_GRAY_CIRCLE_MARKED_ID } from '@/workflow/workflow-diagram/constants/EdgeGrayCircleMarkedId'; import { EDGE_GREEN_CIRCLE_MARKED_ID } from '@/workflow/workflow-diagram/constants/EdgeGreenCircleMarkedId'; import { EDGE_GREEN_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeGreenRoundedArrowMarkerId'; import { EDGE_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId'; import { type Theme, useTheme } from '@emotion/react'; import { BaseEdge } from '@xyflow/react'; +import { isDefined } from 'twenty-shared/utils'; import { StepStatus } from 'twenty-shared/workflow'; const toMarkerId = (id: string) => `url(#${id})`; @@ -13,7 +13,7 @@ const getMarkerStart = (edgeExecutionStatus: StepStatus | undefined) => { return EDGE_GREEN_CIRCLE_MARKED_ID; } - return EDGE_GRAY_CIRCLE_MARKED_ID; + return undefined; }; const getMarkerEnd = (edgeExecutionStatus: StepStatus | undefined) => { @@ -49,9 +49,11 @@ export const WorkflowRunDiagramBaseEdge = ({ }: WorkflowRunDiagramBaseEdgeProps) => { const theme = useTheme(); + const markerStart = getMarkerStart(edgeExecutionStatus); + return ( { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-0", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "trigger", "target": "step1", @@ -133,8 +133,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-1", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step1", "target": "step2", @@ -147,8 +147,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-2", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step2", "target": "step3", @@ -349,8 +349,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-3", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "trigger", "target": "step1", @@ -363,8 +363,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-4", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step1", "target": "step2", @@ -377,8 +377,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-5", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step2", "target": "step3", @@ -579,8 +579,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-6", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "trigger", "target": "step1", @@ -593,8 +593,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-7", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step1", "target": "step2", @@ -607,8 +607,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-8", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step2", "target": "step3", @@ -828,8 +828,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-9", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "trigger", "target": "step1", @@ -842,8 +842,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-10", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step1", "target": "step2", @@ -856,8 +856,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-11", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step2", "target": "step3", @@ -870,8 +870,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-12", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "step3", "target": "step4", @@ -1057,8 +1057,8 @@ describe('generateWorkflowRunDiagram', () => { }, "deletable": false, "id": "8f3b2121-f194-4ba4-9fbf-13", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": false, "source": "trigger", "target": "step1", 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 d4f7e6183c..6e1e43c61e 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 @@ -161,8 +161,8 @@ describe('getWorkflowVersionDiagram', () => { }, "deletable": true, "id": "8f3b2121-f194-4ba4-9fbf-0", - "markerEnd": "workflow-edge-arrow-rounded", - "markerStart": "workflow-edge-gray-circle", + "markerEnd": "workflow-edge-branch-arrow", + "markerStart": undefined, "selectable": true, "source": "trigger", "target": "step-1",