Skip to content

Commit

Permalink
refactor: put most of the code in the workflows module instead of the…
Browse files Browse the repository at this point in the history
… pages directory
  • Loading branch information
Devessier committed Aug 22, 2024
1 parent 4f39561 commit 9975e47
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 167 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { CreateStepNode } from '@/workflow/components/nodes/CreateStepNode';
import { StepNode } from '@/workflow/components/nodes/StepNode';
import { showPageWorkflowDiagramState } from '@/workflow/states/showPageWorkflowDiagramState';
import {
WorkflowDiagram,
WorkflowDiagramEdge,
WorkflowDiagramNode,
} from '@/workflow/types/WorkflowDiagram';
import { getOrganizedDiagram } from '@/workflow/utils/getOrganizedDiagram';
import {
applyEdgeChanges,
applyNodeChanges,
Background,
EdgeChange,
NodeChange,
ReactFlow,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useMemo } from 'react';
import { useSetRecoilState } from 'recoil';
import { GRAY_SCALE, isDefined } from 'twenty-ui';

export const WorkflowShowPageDiagram = ({
diagram,
}: {
diagram: WorkflowDiagram;
}) => {
const { nodes, edges } = useMemo(
() => getOrganizedDiagram(diagram),
[diagram],
);

const setShowPageWorkflowDiagram = useSetRecoilState(
showPageWorkflowDiagramState,
);

const handleNodesChange = (
nodeChanges: Array<NodeChange<WorkflowDiagramNode>>,
) => {
setShowPageWorkflowDiagram((diagram) => {
if (isDefined(diagram) === false) {
throw new Error(
'It must be impossible for the nodes to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.',
);
}

return {
...diagram,
nodes: applyNodeChanges(nodeChanges, diagram.nodes),
};
});
};

const handleEdgesChange = (
edgeChanges: Array<EdgeChange<WorkflowDiagramEdge>>,
) => {
setShowPageWorkflowDiagram((diagram) => {
if (isDefined(diagram) === false) {
throw new Error(
'It must be impossible for the edges to be updated if the diagram is not defined yet. Be sure the diagram is rendered only when defined.',
);
}

return {
...diagram,
edges: applyEdgeChanges(edgeChanges, diagram.edges),
};
});
};

return (
<ReactFlow
nodeTypes={{
default: StepNode,
'create-step': CreateStepNode,
}}
fitView
nodes={nodes.map((node) => ({ ...node, draggable: false }))}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={handleEdgesChange}
>
<Background color={GRAY_SCALE.gray25} size={2} />
</ReactFlow>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,13 @@ import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { showPageWorkflowDiagramState } from '@/workflow/states/showPageWorkflowDiagramState';
import { showPageWorkflowErrorState } from '@/workflow/states/showPageWorkflowErrorState';
import { showPageWorkflowLoadingState } from '@/workflow/states/showPageWorkflowLoadingState';
import {
Workflow,
WorkflowAction,
WorkflowTrigger,
} from '@/workflow/types/Workflow';
import {
WorkflowDiagram,
WorkflowDiagramEdge,
WorkflowDiagramNode,
} from '@/workflow/types/WorkflowDiagram';
import { Workflow } from '@/workflow/types/Workflow';
import { WorkflowDiagram } from '@/workflow/types/WorkflowDiagram';
import { addCreateStepNodes } from '@/workflow/utils/addCreateStepNodes';
import { MarkerType } from '@xyflow/react';
import { generateWorklowDiagram } from '@/workflow/utils/generateWorkflowDiagram';
import { useEffect } from 'react';
import { useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-ui';
import { v4 } from 'uuid';

type WorkflowShowPageEffectProps = {
workflowId: string;
Expand All @@ -29,71 +20,6 @@ const EMPTY_FLOW_DATA: WorkflowDiagram = {
edges: [],
};

const generateWorklowDiagram = (trigger: WorkflowTrigger): WorkflowDiagram => {
const nodes: Array<WorkflowDiagramNode> = [];
const edges: Array<WorkflowDiagramEdge> = [];

// Helper function to generate nodes and edges recursively
const processNode = (
action: WorkflowAction,
parentNodeId: string,
xPos: number,
yPos: number,
) => {
const nodeId = v4();
nodes.push({
id: nodeId,
data: {
nodeType: 'action',
label: action.name,
},
position: {
x: xPos,
y: yPos,
},
});

// Create an edge from the parent node to this node
edges.push({
id: v4(),
source: parentNodeId,
target: nodeId,
markerEnd: {
type: MarkerType.ArrowClosed,
},
});

// Recursively generate flow for the next action if it exists
if (isDefined(action.nextAction)) {
processNode(action.nextAction, nodeId, xPos + 150, yPos + 100);
}
};

// Start with the trigger node
const triggerNodeId = v4();
nodes.push({
id: triggerNodeId,
data: {
nodeType: 'trigger',
label: trigger.settings.triggerName,
},
position: {
x: 0,
y: 0,
},
});

// If there's a next action, start the recursive generation
if (isDefined(trigger.nextAction)) {
processNode(trigger.nextAction, triggerNodeId, 150, 100);
}

return {
nodes,
edges,
};
};

const getFlowLastVersion = (
workflow: Workflow | undefined,
): WorkflowDiagram => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IconButton } from '@/ui/input/button/components/IconButton';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
import { StyledTargetHandle } from '@/workflow/components/nodes/common/StyledTargetHandle';
import { Position } from '@xyflow/react';
import { IconPlus } from 'twenty-ui';
import { StyledTargetHandle } from '~/pages/workflows/nodes/base';

export const CreateStepNode = () => {
const { openRightDrawer } = useRightDrawer();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { StyledTargetHandle } from '@/workflow/components/nodes/common/StyledTargetHandle';
import { WorkflowDiagramStepNodeData } from '@/workflow/types/WorkflowDiagram';
import styled from '@emotion/styled';
import { Handle, Position } from '@xyflow/react';
import { StyledTargetHandle } from '~/pages/workflows/nodes/base';

const StyledStepNodeContainer = styled.div`
display: flex;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled from '@emotion/styled';

import { Handle } from '@xyflow/react';

export const StyledTargetHandle = styled(Handle)`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { WorkflowAction, WorkflowTrigger } from '@/workflow/types/Workflow';
import {
WorkflowDiagram,
WorkflowDiagramEdge,
WorkflowDiagramNode,
} from '@/workflow/types/WorkflowDiagram';
import { MarkerType } from '@xyflow/react';
import { isDefined } from 'twenty-ui';
import { v4 } from 'uuid';

export const generateWorklowDiagram = (
trigger: WorkflowTrigger,
): WorkflowDiagram => {
const nodes: Array<WorkflowDiagramNode> = [];
const edges: Array<WorkflowDiagramEdge> = [];

// Helper function to generate nodes and edges recursively
const processNode = (
action: WorkflowAction,
parentNodeId: string,
xPos: number,
yPos: number,
) => {
const nodeId = v4();
nodes.push({
id: nodeId,
data: {
nodeType: 'action',
label: action.name,
},
position: {
x: xPos,
y: yPos,
},
});

// Create an edge from the parent node to this node
edges.push({
id: v4(),
source: parentNodeId,
target: nodeId,
markerEnd: {
type: MarkerType.ArrowClosed,
},
});

// Recursively generate flow for the next action if it exists
if (isDefined(action.nextAction)) {
processNode(action.nextAction, nodeId, xPos + 150, yPos + 100);
}
};

// Start with the trigger node
const triggerNodeId = v4();
nodes.push({
id: triggerNodeId,
data: {
nodeType: 'trigger',
label: trigger.settings.triggerName,
},
position: {
x: 0,
y: 0,
},
});

// If there's a next action, start the recursive generation
if (isDefined(trigger.nextAction)) {
processNode(trigger.nextAction, triggerNodeId, 150, 100);
}

return {
nodes,
edges,
};
};
Loading

0 comments on commit 9975e47

Please sign in to comment.