diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx index 9d8c6b39b303..0318f61a6bf4 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramBaseStepNode.tsx @@ -21,13 +21,12 @@ const StyledStepNodeType = styled.div` ${({ theme }) => theme.border.radius.sm} 0 0; color: ${({ theme }) => theme.color.gray50}; - font-size: ${({ theme }) => theme.font.size.xs}; + font-size: ${({ theme }) => theme.font.size.md}; font-weight: ${({ theme }) => theme.font.weight.semiBold}; + margin-left: ${({ theme }) => theme.spacing(2)}; padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)}; - position: absolute; - top: 0; - transform: translateY(-100%); + align-self: flex-start; .selectable.selected &, .selectable:focus &, @@ -62,9 +61,9 @@ const StyledStepNodeInnerContainer = styled.div<{ variant?: Variant }>` const StyledStepNodeLabel = styled.div<{ variant?: Variant }>` align-items: center; display: flex; - font-size: ${({ theme }) => theme.font.size.md}; + font-size: ${({ theme }) => theme.font.size.lg}; font-weight: ${({ theme }) => theme.font.weight.medium}; - column-gap: ${({ theme }) => theme.spacing(2)}; + column-gap: ${({ theme }) => theme.spacing(3)}; color: ${({ variant, theme }) => variant === 'placeholder' ? theme.font.color.extraLight @@ -80,9 +79,13 @@ export const StyledTargetHandle = styled(Handle)` `; const StyledRightFloatingElementContainer = styled.div` + display: flex; + align-items: center; position: absolute; + right: ${({ theme }) => theme.spacing(-3)}; + bottom: 0; + top: 0; transform: translateX(100%); - right: ${({ theme }) => theme.spacing(-2)}; `; export const WorkflowDiagramBaseStepNode = ({ @@ -104,9 +107,9 @@ export const WorkflowDiagramBaseStepNode = ({ ) : null} - - {capitalize(nodeType)} + {capitalize(nodeType)} + {Icon} diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasBase.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasBase.tsx index 79273d062aa6..55aab89ae27d 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasBase.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasBase.tsx @@ -1,3 +1,6 @@ +import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState'; +import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { WorkflowVersionStatusTag } from '@/workflow/components/WorkflowVersionStatusTag'; import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; @@ -15,14 +18,16 @@ import { Background, EdgeChange, FitViewOptions, + getNodesBounds, NodeChange, NodeProps, ReactFlow, + useReactFlow, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; -import React, { useMemo } from 'react'; -import { useSetRecoilState } from 'recoil'; -import { GRAY_SCALE, isDefined } from 'twenty-ui'; +import React, { useEffect, useMemo, useRef } from 'react'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { GRAY_SCALE, isDefined, THEME_COMMON } from 'twenty-ui'; const StyledResetReactflowStyles = styled.div` height: 100%; @@ -35,6 +40,9 @@ const StyledResetReactflowStyles = styled.div` .react-flow__node-output, .react-flow__node-group { padding: 0; + width: auto; + text-align: start; + white-space: nowrap; } --xy-node-border-radius: none; @@ -51,10 +59,10 @@ const StyledStatusTagContainer = styled.div` padding: ${({ theme }) => theme.spacing(2)}; `; -const defaultFitViewOptions: FitViewOptions = { - minZoom: 1.3, - maxZoom: 1.3, -}; +const defaultFitViewOptions = { + minZoom: 1, + maxZoom: 1, +} satisfies FitViewOptions; export const WorkflowDiagramCanvasBase = ({ diagram, @@ -77,11 +85,29 @@ export const WorkflowDiagramCanvasBase = ({ >; children?: React.ReactNode; }) => { + const reactflow = useReactFlow(); + const { nodes, edges } = useMemo( () => getOrganizedDiagram(diagram), [diagram], ); + const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); + const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState); + const isMobile = useIsMobile(); + + const rightDrawerState = !isRightDrawerOpen + ? 'closed' + : isRightDrawerMinimized + ? 'minimized' + : isMobile + ? 'fullScreen' + : 'normal'; + + const rightDrawerWidth = Number( + THEME_COMMON.rightDrawerWidth.replace('px', ''), + ); + const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); const handleNodesChange = ( @@ -118,27 +144,68 @@ export const WorkflowDiagramCanvasBase = ({ }); }; + const containerRef = useRef(null); + + useEffect(() => { + if (!isDefined(containerRef.current) || !reactflow.viewportInitialized) { + return; + } + + const currentViewport = reactflow.getViewport(); + + const flowBounds = getNodesBounds(reactflow.getNodes()); + + let visibleRightDrawerWidth = 0; + if (rightDrawerState === 'normal') { + visibleRightDrawerWidth = rightDrawerWidth; + } + + const viewportX = + (containerRef.current.offsetWidth + visibleRightDrawerWidth) / 2 - + flowBounds.width / 2; + + reactflow.setViewport( + { + ...currentViewport, + x: viewportX - visibleRightDrawerWidth, + }, + { duration: 300 }, + ); + }, [reactflow, rightDrawerState, rightDrawerWidth]); + return ( - + { - fitView(defaultFitViewOptions); + onInit={() => { + if (!isDefined(containerRef.current)) { + throw new Error('Expect the container ref to be defined'); + } + + const flowBounds = getNodesBounds(reactflow.getNodes()); + + reactflow.setViewport({ + x: containerRef.current.offsetWidth / 2 - flowBounds.width / 2, + y: 150, + zoom: defaultFitViewOptions.maxZoom, + }); }} + minZoom={defaultFitViewOptions.minZoom} + maxZoom={defaultFitViewOptions.maxZoom} nodeTypes={nodeTypes} - fitView nodes={nodes.map((node) => ({ ...node, draggable: false }))} edges={edges} onNodesChange={handleNodesChange} onEdgesChange={handleEdgesChange} + proOptions={{ hideAttribution: true }} > {children} - - - - + + + + ); }; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEditable.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEditable.tsx index ed953f511fa3..fe866fa72697 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasEditable.tsx @@ -5,6 +5,7 @@ import { WorkflowDiagramEmptyTrigger } from '@/workflow/components/WorkflowDiagr import { WorkflowDiagramStepNodeEditable } from '@/workflow/components/WorkflowDiagramStepNodeEditable'; import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; +import { ReactFlowProvider } from '@xyflow/react'; export const WorkflowDiagramCanvasEditable = ({ diagram, @@ -14,17 +15,19 @@ export const WorkflowDiagramCanvasEditable = ({ workflowWithCurrentVersion: WorkflowWithCurrentVersion; }) => { return ( - - - + + + + + ); }; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasReadonly.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasReadonly.tsx index d6c50fa9034e..5302046f22f9 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCanvasReadonly.tsx @@ -4,6 +4,7 @@ import { WorkflowDiagramEmptyTrigger } from '@/workflow/components/WorkflowDiagr import { WorkflowDiagramStepNodeReadonly } from '@/workflow/components/WorkflowDiagramStepNodeReadonly'; import { WorkflowVersion } from '@/workflow/types/Workflow'; import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram'; +import { ReactFlowProvider } from '@xyflow/react'; export const WorkflowDiagramCanvasReadonly = ({ diagram, @@ -13,16 +14,18 @@ export const WorkflowDiagramCanvasReadonly = ({ workflowVersion: WorkflowVersion; }) => { return ( - - - + + + + + ); }; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx index ec0614037889..98b93c689ada 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramCreateStepNode.tsx @@ -11,7 +11,7 @@ export const WorkflowDiagramCreateStepNode = () => { <> - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx index 9cef1fbb47bd..04c6a62be931 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx @@ -31,7 +31,7 @@ export const WorkflowDiagramStepNodeBase = ({ return ( @@ -41,7 +41,7 @@ export const WorkflowDiagramStepNodeBase = ({ return ( @@ -57,7 +57,7 @@ export const WorkflowDiagramStepNodeBase = ({ return ( @@ -66,7 +66,7 @@ export const WorkflowDiagramStepNodeBase = ({ case 'SEND_EMAIL': { return ( - + ); } diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeEditable.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeEditable.tsx index 579e3c923491..9df7f0bbc42f 100644 --- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeEditable.tsx @@ -32,6 +32,7 @@ export const WorkflowDiagramStepNodeEditable = ({ RightFloatingElement={ selected ? ( { return deleteOneStep(); diff --git a/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts b/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts index ffde2d1d88aa..1e76140993f4 100644 --- a/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts +++ b/packages/twenty-front/src/modules/workflow/utils/addCreateStepNodes.ts @@ -36,6 +36,7 @@ export const addCreateStepNodes = ({ nodes, edges }: WorkflowDiagram) => { markerEnd: { type: MarkerType.ArrowClosed, }, + deletable: false, }); } diff --git a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts index 971e996684f3..93fdaae51b0b 100644 --- a/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/utils/generateWorkflowDiagram.ts @@ -51,6 +51,7 @@ export const generateWorkflowDiagram = ({ markerEnd: { type: MarkerType.ArrowClosed, }, + deletable: false, }); return nodeId;