Migrate workflow states to component states (#11773)
- Migrated all workflow Recoil states to component states to isolate each workflow visualizer instance. The use case of having two workflow visualizers displayed at the same time appeared recently and will grow in the near future. - We chose to use the `recordId` as the value for the `instanceId` of the component states. Currently, there are a few cases where two workflows or two workflow runs are rendered at the same time. As a consequence, relying on the `recordId` is enough for the moment. - However, there is one case where it's necessary to have a component state scoped to a workflow visualizer instance: the `workflowVisualizerStatusState`. This component is tightly coupled to the `<Reactflow />` component instance rendered in the workflow visualizer, and it must be set to its default value when the component first renders. I achieved that by using another component instance context whose instanceId is an identifier returned by the `useId()` hook in the Workflow Run Card component.
This commit is contained in:
committed by
GitHub
parent
8b68dce795
commit
1543c900ae
@ -1,9 +1,10 @@
|
||||
import { flowState } from '@/workflow/states/flowState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useFlowOrThrow = () => {
|
||||
const flow = useRecoilValue(flowState);
|
||||
const flow = useRecoilComponentValueV2(flowComponentState);
|
||||
|
||||
if (!isDefined(flow)) {
|
||||
throw new Error('Expected the flow to be defined');
|
||||
}
|
||||
|
||||
@ -3,11 +3,12 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { flowState } from '@/workflow/states/flowState';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowRunIdState } from '@/workflow/states/workflowRunIdState';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowVisualizerWorkflowRunIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowRunIdComponentState';
|
||||
import { WorkflowRun } from '@/workflow/types/Workflow';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { getWorkflowVisualizerComponentInstanceId } from '@/workflow/utils/getWorkflowVisualizerComponentInstanceId';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { generateWorkflowRunDiagram } from '@/workflow/workflow-diagram/utils/generateWorkflowRunDiagram';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
@ -58,17 +59,46 @@ export const useRunWorkflowRunOpeningInCommandMenuSideEffects = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
set(workflowRunIdState, workflowRunRecord.id);
|
||||
set(workflowIdState, workflowRunRecord.workflowId);
|
||||
set(flowState, {
|
||||
workflowVersionId: workflowRunRecord.workflowVersionId,
|
||||
trigger: workflowRunRecord.output.flow.trigger,
|
||||
steps: workflowRunRecord.output.flow.steps,
|
||||
});
|
||||
set(workflowSelectedNodeState, stepToOpenByDefault.id);
|
||||
set(
|
||||
workflowVisualizerWorkflowRunIdComponentState.atomFamily({
|
||||
instanceId: getWorkflowVisualizerComponentInstanceId({
|
||||
recordId,
|
||||
}),
|
||||
}),
|
||||
workflowRunRecord.id,
|
||||
);
|
||||
set(
|
||||
workflowVisualizerWorkflowIdComponentState.atomFamily({
|
||||
instanceId: getWorkflowVisualizerComponentInstanceId({
|
||||
recordId,
|
||||
}),
|
||||
}),
|
||||
workflowRunRecord.workflowId,
|
||||
);
|
||||
set(
|
||||
flowComponentState.atomFamily({
|
||||
instanceId: getWorkflowVisualizerComponentInstanceId({
|
||||
recordId,
|
||||
}),
|
||||
}),
|
||||
{
|
||||
workflowVersionId: workflowRunRecord.workflowVersionId,
|
||||
trigger: workflowRunRecord.output.flow.trigger,
|
||||
steps: workflowRunRecord.output.flow.steps,
|
||||
},
|
||||
);
|
||||
set(
|
||||
workflowSelectedNodeComponentState.atomFamily({
|
||||
instanceId: getWorkflowVisualizerComponentInstanceId({
|
||||
recordId,
|
||||
}),
|
||||
}),
|
||||
stepToOpenByDefault.id,
|
||||
);
|
||||
|
||||
openWorkflowRunViewStepInCommandMenu({
|
||||
workflowId: workflowRunRecord.workflowId,
|
||||
workflowRunId: workflowRunRecord.id,
|
||||
title: stepToOpenByDefault.data.name,
|
||||
icon: getIcon(getWorkflowNodeIconKey(stepToOpenByDefault.data)),
|
||||
workflowSelectedNode: stepToOpenByDefault.id,
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { workflowRunIdState } from '@/workflow/states/workflowRunIdState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { workflowVisualizerWorkflowRunIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowRunIdComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useWorkflowRunIdOrThrow = () => {
|
||||
const workflowRunId = useRecoilValue(workflowRunIdState);
|
||||
const workflowRunId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowRunIdComponentState,
|
||||
);
|
||||
|
||||
if (!isDefined(workflowRunId)) {
|
||||
throw new Error('Expected the workflow run ID to be defined');
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowAction, WorkflowTrigger } from '@/workflow/types/Workflow';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const flowComponentState = createComponentStateV2<
|
||||
| {
|
||||
workflowVersionId: string;
|
||||
trigger: WorkflowTrigger | null;
|
||||
steps: WorkflowAction[] | null;
|
||||
}
|
||||
| undefined
|
||||
>({
|
||||
key: 'flowComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,14 +0,0 @@
|
||||
import { WorkflowAction, WorkflowTrigger } from '@/workflow/types/Workflow';
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const flowState = createState<
|
||||
| {
|
||||
workflowVersionId: string;
|
||||
trigger: WorkflowTrigger | null;
|
||||
steps: WorkflowAction[] | null;
|
||||
}
|
||||
| undefined
|
||||
>({
|
||||
key: 'flowState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -1,5 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
export const workflowIdState = createState<string | undefined>({
|
||||
key: 'workflowIdState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowLastCreatedStepIdComponentState = createComponentStateV2<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowLastCreatedStepIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,5 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
export const workflowLastCreatedStepIdState = createState<string | undefined>({
|
||||
key: 'workflowLastCreatedStepIdState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowRunIdState = createState<string | undefined>({
|
||||
key: 'workflowRunIdState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowVisualizerWorkflowIdComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'workflowVisualizerWorkflowIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowVisualizerWorkflowRunIdComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'workflowVisualizerWorkflowRunIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowVisualizerWorkflowVersionIdComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'workflowVisualizerWorkflowVersionIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
export const getWorkflowVisualizerComponentInstanceId = ({
|
||||
recordId,
|
||||
}: {
|
||||
recordId: string;
|
||||
}) => {
|
||||
return recordId;
|
||||
};
|
||||
@ -1,8 +1,9 @@
|
||||
import { useListenRightDrawerClose } from '@/ui/layout/right-drawer/hooks/useListenRightDrawerClose';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { WorkflowDiagramCustomMarkers } from '@/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers';
|
||||
import { useRightDrawerState } from '@/workflow/workflow-diagram/hooks/useRightDrawerState';
|
||||
import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState';
|
||||
import { workflowReactFlowRefState } from '@/workflow/workflow-diagram/states/workflowReactFlowRefState';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramEdgeType,
|
||||
@ -26,7 +27,6 @@ import {
|
||||
} from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Tag, TagColor } from 'twenty-ui/components';
|
||||
import { THEME_COMMON } from 'twenty-ui/theme';
|
||||
@ -121,7 +121,9 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
|
||||
const reactflow = useReactFlow();
|
||||
|
||||
const workflowDiagram = useRecoilValue(workflowDiagramState);
|
||||
const workflowDiagram = useRecoilComponentValueV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
|
||||
const { nodes, edges } = useMemo(
|
||||
() =>
|
||||
@ -137,14 +139,8 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
THEME_COMMON.rightDrawerWidth.replace('px', ''),
|
||||
);
|
||||
|
||||
const setWorkflowDiagram = useSetRecoilState(workflowDiagramState);
|
||||
|
||||
const setWorkflowReactFlowRef = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(node: HTMLDivElement | null) => {
|
||||
set(workflowReactFlowRefState, { current: node });
|
||||
},
|
||||
[],
|
||||
const setWorkflowDiagram = useSetRecoilComponentStateV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
|
||||
const handleEdgesChange = (
|
||||
@ -199,24 +195,18 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
);
|
||||
}, [reactflow, rightDrawerState, rightDrawerWidth]);
|
||||
|
||||
const handleNodesChanges = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(changes: NodeChange<WorkflowDiagramNode>[]) => {
|
||||
set(workflowDiagramState, (diagram) => {
|
||||
if (!isDefined(diagram)) {
|
||||
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.',
|
||||
);
|
||||
}
|
||||
const handleNodesChanges = (changes: NodeChange<WorkflowDiagramNode>[]) => {
|
||||
setWorkflowDiagram((diagram) => {
|
||||
if (!isDefined(diagram)) {
|
||||
return diagram;
|
||||
}
|
||||
|
||||
return {
|
||||
...diagram,
|
||||
nodes: applyNodeChanges(changes, diagram.nodes),
|
||||
};
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
return {
|
||||
...diagram,
|
||||
nodes: applyNodeChanges(changes, diagram.nodes),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const handleInit = () => {
|
||||
if (!isDefined(containerRef.current)) {
|
||||
@ -239,7 +229,6 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
<WorkflowDiagramCustomMarkers />
|
||||
|
||||
<ReactFlow
|
||||
ref={setWorkflowReactFlowRef}
|
||||
onInit={handleInit}
|
||||
minZoom={defaultFitViewOptions.minZoom}
|
||||
maxZoom={defaultFitViewOptions.maxZoom}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
|
||||
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { EMPTY_TRIGGER_STEP_ID } from '@/workflow/workflow-diagram/constants/EmptyTriggerStepId';
|
||||
import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation';
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagramNode,
|
||||
WorkflowDiagramStepNodeData,
|
||||
@ -29,7 +31,9 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
openWorkflowEditStepInCommandMenu,
|
||||
} = useWorkflowCommandMenu();
|
||||
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const setCommandMenuNavigationStack = useSetRecoilState(
|
||||
commandMenuNavigationStackState,
|
||||
@ -37,7 +41,9 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const handleSelectionChange = useCallback(
|
||||
({ nodes }: OnSelectionChangeParams) => {
|
||||
@ -53,8 +59,8 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
|
||||
const isEmptyTriggerNode = selectedNode.type === EMPTY_TRIGGER_STEP_ID;
|
||||
if (isEmptyTriggerNode) {
|
||||
if (isDefined(workflowId)) {
|
||||
openWorkflowTriggerTypeInCommandMenu(workflowId);
|
||||
if (isDefined(workflowVisualizerWorkflowId)) {
|
||||
openWorkflowTriggerTypeInCommandMenu(workflowVisualizerWorkflowId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -71,9 +77,9 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
|
||||
setWorkflowSelectedNode(selectedNode.id);
|
||||
|
||||
if (isDefined(workflowId)) {
|
||||
if (isDefined(workflowVisualizerWorkflowId)) {
|
||||
openWorkflowEditStepInCommandMenu(
|
||||
workflowId,
|
||||
workflowVisualizerWorkflowId,
|
||||
selectedNodeData.name,
|
||||
getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
);
|
||||
@ -84,7 +90,7 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
[
|
||||
isInRightDrawer,
|
||||
setCommandMenuNavigationStack,
|
||||
workflowId,
|
||||
workflowVisualizerWorkflowId,
|
||||
openWorkflowTriggerTypeInCommandMenu,
|
||||
startNodeCreation,
|
||||
openWorkflowEditStepInCommandMenu,
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowVisualizerWorkflowVersionIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowVersionIdComponentState';
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagramNode,
|
||||
WorkflowDiagramStepNodeData,
|
||||
@ -9,19 +12,34 @@ import {
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
export const WorkflowDiagramCanvasReadonlyEffect = () => {
|
||||
const { getIcon } = useIcons();
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
const { openWorkflowViewStepInCommandMenu } = useWorkflowCommandMenu();
|
||||
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflowVisualizerWorkflowVersionId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowVersionIdComponentState,
|
||||
);
|
||||
|
||||
const handleSelectionChange = useCallback(
|
||||
({ nodes }: OnSelectionChangeParams) => {
|
||||
if (
|
||||
!(
|
||||
isDefined(workflowVisualizerWorkflowId) &&
|
||||
isDefined(workflowVisualizerWorkflowVersionId)
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedNode = nodes[0] as WorkflowDiagramNode | undefined;
|
||||
|
||||
if (!isDefined(selectedNode)) {
|
||||
@ -32,18 +50,18 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => {
|
||||
|
||||
const selectedNodeData = selectedNode.data as WorkflowDiagramStepNodeData;
|
||||
|
||||
if (isDefined(workflowId)) {
|
||||
openWorkflowViewStepInCommandMenu(
|
||||
workflowId,
|
||||
selectedNodeData.name,
|
||||
getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
);
|
||||
}
|
||||
openWorkflowViewStepInCommandMenu({
|
||||
workflowId: workflowVisualizerWorkflowId,
|
||||
workflowVersionId: workflowVisualizerWorkflowVersionId,
|
||||
title: selectedNodeData.name,
|
||||
icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
});
|
||||
},
|
||||
[
|
||||
setWorkflowSelectedNode,
|
||||
openWorkflowViewStepInCommandMenu,
|
||||
workflowId,
|
||||
workflowVisualizerWorkflowId,
|
||||
workflowVisualizerWorkflowVersionId,
|
||||
getIcon,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { flowState } from '@/workflow/states/flowState';
|
||||
import { workflowLastCreatedStepIdState } from '@/workflow/states/workflowLastCreatedStepIdState';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import {
|
||||
WorkflowVersion,
|
||||
WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
|
||||
import { addCreateStepNodes } from '@/workflow/workflow-diagram/utils/addCreateStepNodes';
|
||||
import { getWorkflowVersionDiagram } from '@/workflow/workflow-diagram/utils/getWorkflowVersionDiagram';
|
||||
import { mergeWorkflowDiagrams } from '@/workflow/workflow-diagram/utils/mergeWorkflowDiagrams';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const WorkflowDiagramEffect = ({
|
||||
@ -20,10 +22,19 @@ export const WorkflowDiagramEffect = ({
|
||||
}: {
|
||||
workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined;
|
||||
}) => {
|
||||
const setWorkflowDiagram = useSetRecoilState(workflowDiagramState);
|
||||
const setFlow = useSetRecoilState(flowState);
|
||||
const workflowDiagramState = useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
const setWorkflowDiagram = useSetRecoilComponentStateV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
const setFlow = useSetRecoilComponentStateV2(flowComponentState);
|
||||
const { populateStepsOutputSchema } = useStepsOutputSchema();
|
||||
|
||||
const workflowLastCreatedStepIdState = useRecoilComponentCallbackStateV2(
|
||||
workflowLastCreatedStepIdComponentState,
|
||||
);
|
||||
|
||||
const computeAndMergeNewWorkflowDiagram = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
return (currentVersion: WorkflowVersion) => {
|
||||
@ -64,7 +75,7 @@ export const WorkflowDiagramEffect = ({
|
||||
set(workflowDiagramState, mergedWorkflowDiagram);
|
||||
};
|
||||
},
|
||||
[],
|
||||
[workflowLastCreatedStepIdState, workflowDiagramState],
|
||||
);
|
||||
|
||||
const currentVersion = workflowWithCurrentVersion?.currentVersion;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '@/workflow/utils/assertWorkflowWithCurrentVersionIsDefined';
|
||||
import { WorkflowDiagramStepNodeEditableContent } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent';
|
||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const WorkflowDiagramStepNodeEditable = ({
|
||||
id,
|
||||
@ -15,9 +15,13 @@ export const WorkflowDiagramStepNodeEditable = ({
|
||||
data: WorkflowDiagramStepNodeData;
|
||||
selected?: boolean;
|
||||
}) => {
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId);
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
workflowVisualizerWorkflowId,
|
||||
);
|
||||
assertWorkflowWithCurrentVersionIsDefined(workflowWithCurrentVersion);
|
||||
|
||||
const { deleteStep } = useDeleteStep({
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowDiagramStatusState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusState';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowDiagramStatusComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { WorkflowRunDiagramNode } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
@ -15,10 +17,25 @@ export const WorkflowRunDiagramCanvasEffect = () => {
|
||||
|
||||
const { openWorkflowRunViewStepInCommandMenu } = useWorkflowCommandMenu();
|
||||
|
||||
const workflowRunId = useWorkflowRunIdOrThrow();
|
||||
|
||||
const workflowVisualizerWorkflowIdState = useRecoilComponentCallbackStateV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflowDiagramStatusState = useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramStatusComponentState,
|
||||
);
|
||||
const workflowSelectedNodeState = useRecoilComponentCallbackStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const handleSelectionChange = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
({ nodes }: OnSelectionChangeParams) => {
|
||||
const workflowId = getSnapshotValue(snapshot, workflowIdState);
|
||||
const workflowId = getSnapshotValue(
|
||||
snapshot,
|
||||
workflowVisualizerWorkflowIdState,
|
||||
);
|
||||
|
||||
if (!isDefined(workflowId)) {
|
||||
throw new Error('Expected the workflowId to be defined.');
|
||||
@ -49,13 +66,21 @@ export const WorkflowRunDiagramCanvasEffect = () => {
|
||||
|
||||
openWorkflowRunViewStepInCommandMenu({
|
||||
workflowId,
|
||||
workflowRunId,
|
||||
title: selectedNodeData.name,
|
||||
icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
workflowSelectedNode: selectedNode.id,
|
||||
stepExecutionStatus: selectedNodeData.runStatus,
|
||||
});
|
||||
},
|
||||
[getIcon, openWorkflowRunViewStepInCommandMenu],
|
||||
[
|
||||
workflowVisualizerWorkflowIdState,
|
||||
workflowDiagramStatusState,
|
||||
workflowSelectedNodeState,
|
||||
openWorkflowRunViewStepInCommandMenu,
|
||||
workflowRunId,
|
||||
getIcon,
|
||||
],
|
||||
);
|
||||
|
||||
useOnSelectionChange({
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
|
||||
import { WorkflowRunDiagramCanvas } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas';
|
||||
import { workflowDiagramStatusState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusState';
|
||||
import { workflowDiagramStatusComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusComponentState';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -15,7 +15,9 @@ export const WorkflowRunVisualizer = ({
|
||||
workflowRunId: string;
|
||||
}) => {
|
||||
const workflowRun = useWorkflowRun({ workflowRunId });
|
||||
const workflowDiagramStatus = useRecoilValue(workflowDiagramStatusState);
|
||||
const workflowDiagramStatus = useRecoilComponentValueV2(
|
||||
workflowDiagramStatusComponentState,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(workflowRun) ||
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
|
||||
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
|
||||
import { flowState } from '@/workflow/states/flowState';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowRunIdState } from '@/workflow/states/workflowRunIdState';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowVisualizerWorkflowRunIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowRunIdComponentState';
|
||||
import { WorkflowRunOutput } from '@/workflow/types/Workflow';
|
||||
import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState';
|
||||
import { workflowDiagramStatusState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusState';
|
||||
import { workflowRunStepToOpenByDefaultState } from '@/workflow/workflow-diagram/states/workflowRunStepToOpenByDefaultState';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
import { workflowDiagramStatusComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusComponentState';
|
||||
import { workflowRunStepToOpenByDefaultComponentState } from '@/workflow/workflow-diagram/states/workflowRunStepToOpenByDefaultComponentState';
|
||||
import { generateWorkflowRunDiagram } from '@/workflow/workflow-diagram/utils/generateWorkflowRunDiagram';
|
||||
import { selectWorkflowDiagramNode } from '@/workflow/workflow-diagram/utils/selectWorkflowDiagramNode';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const WorkflowRunVisualizerEffect = ({
|
||||
@ -23,8 +26,24 @@ export const WorkflowRunVisualizerEffect = ({
|
||||
const workflowRun = useWorkflowRun({ workflowRunId });
|
||||
const workflowVersion = useWorkflowVersion(workflowRun?.workflowVersionId);
|
||||
|
||||
const setWorkflowRunId = useSetRecoilState(workflowRunIdState);
|
||||
const setWorkflowId = useSetRecoilState(workflowIdState);
|
||||
const setWorkflowRunId = useSetRecoilComponentStateV2(
|
||||
workflowVisualizerWorkflowRunIdComponentState,
|
||||
);
|
||||
const setWorkflowVisualizerWorkflowId = useSetRecoilComponentStateV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const flowState = useRecoilComponentCallbackStateV2(flowComponentState);
|
||||
const workflowDiagramState = useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
const workflowDiagramStatusState = useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramStatusComponentState,
|
||||
);
|
||||
const workflowRunStepToOpenByDefaultState = useRecoilComponentCallbackStateV2(
|
||||
workflowRunStepToOpenByDefaultComponentState,
|
||||
);
|
||||
|
||||
const { populateStepsOutputSchema } = useStepsOutputSchema();
|
||||
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
@ -38,11 +57,11 @@ export const WorkflowRunVisualizerEffect = ({
|
||||
return;
|
||||
}
|
||||
|
||||
setWorkflowId(workflowRun.workflowId);
|
||||
}, [setWorkflowId, workflowRun]);
|
||||
setWorkflowVisualizerWorkflowId(workflowRun.workflowId);
|
||||
}, [setWorkflowVisualizerWorkflowId, workflowRun]);
|
||||
|
||||
const handleWorkflowRunDiagramGeneration = useRecoilCallback(
|
||||
({ set }) =>
|
||||
({ snapshot, set }) =>
|
||||
({
|
||||
workflowRunOutput,
|
||||
workflowVersionId,
|
||||
@ -59,7 +78,14 @@ export const WorkflowRunVisualizerEffect = ({
|
||||
return;
|
||||
}
|
||||
|
||||
set(workflowDiagramStatusState, 'computing-diagram');
|
||||
const workflowDiagramStatus = getSnapshotValue(
|
||||
snapshot,
|
||||
workflowDiagramStatusState,
|
||||
);
|
||||
|
||||
if (workflowDiagramStatus !== 'done') {
|
||||
set(workflowDiagramStatusState, 'computing-diagram');
|
||||
}
|
||||
|
||||
set(flowState, {
|
||||
workflowVersionId,
|
||||
@ -89,9 +115,16 @@ export const WorkflowRunVisualizerEffect = ({
|
||||
set(workflowDiagramState, baseWorkflowRunDiagram);
|
||||
}
|
||||
|
||||
set(workflowDiagramStatusState, 'computing-dimensions');
|
||||
if (workflowDiagramStatus !== 'done') {
|
||||
set(workflowDiagramStatusState, 'computing-dimensions');
|
||||
}
|
||||
},
|
||||
[],
|
||||
[
|
||||
flowState,
|
||||
workflowDiagramState,
|
||||
workflowDiagramStatusState,
|
||||
workflowRunStepToOpenByDefaultState,
|
||||
],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
|
||||
import { flowState } from '@/workflow/states/flowState';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowVisualizerWorkflowVersionIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowVersionIdComponentState';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
import { getWorkflowVersionDiagram } from '@/workflow/workflow-diagram/utils/getWorkflowVersionDiagram';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const WorkflowVersionVisualizerEffect = ({
|
||||
@ -15,10 +16,19 @@ export const WorkflowVersionVisualizerEffect = ({
|
||||
}) => {
|
||||
const workflowVersion = useWorkflowVersion(workflowVersionId);
|
||||
|
||||
const setFlow = useSetRecoilState(flowState);
|
||||
const setWorkflowDiagram = useSetRecoilState(workflowDiagramState);
|
||||
const setWorkflowId = useSetRecoilState(workflowIdState);
|
||||
const setFlow = useSetRecoilComponentStateV2(flowComponentState);
|
||||
const setWorkflowDiagram = useSetRecoilComponentStateV2(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
const setWorkflowVisualizerWorkflowId = useSetRecoilComponentStateV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const setWorkflowVisualizerWorkflowVersionId = useSetRecoilComponentStateV2(
|
||||
workflowVisualizerWorkflowVersionIdComponentState,
|
||||
);
|
||||
|
||||
const { populateStepsOutputSchema } = useStepsOutputSchema();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(workflowVersion)) {
|
||||
setFlow(undefined);
|
||||
@ -32,8 +42,14 @@ export const WorkflowVersionVisualizerEffect = ({
|
||||
steps: workflowVersion.steps,
|
||||
});
|
||||
|
||||
setWorkflowId(workflowVersion.workflowId);
|
||||
}, [setFlow, setWorkflowId, workflowVersion]);
|
||||
setWorkflowVisualizerWorkflowId(workflowVersion.workflowId);
|
||||
setWorkflowVisualizerWorkflowVersionId(workflowVersion.id);
|
||||
}, [
|
||||
setFlow,
|
||||
setWorkflowVisualizerWorkflowId,
|
||||
setWorkflowVisualizerWorkflowVersionId,
|
||||
workflowVersion,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(workflowVersion)) {
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const WorkflowVisualizerEffect = ({
|
||||
workflowId,
|
||||
}: {
|
||||
workflowId: string;
|
||||
}) => {
|
||||
const setWorkflowId = useSetRecoilState(workflowIdState);
|
||||
const setWorkflowVisualizerWorkflowId = useSetRecoilComponentStateV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setWorkflowId(workflowId);
|
||||
}, [setWorkflowId, workflowId]);
|
||||
setWorkflowVisualizerWorkflowId(workflowId);
|
||||
}, [setWorkflowVisualizerWorkflowId, workflowId]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -9,11 +9,12 @@ import { WorkflowDiagramStepNodeReadonly } from '@/workflow/workflow-diagram/com
|
||||
import { WorkflowDiagramSuccessEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramSuccessEdge';
|
||||
import { WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION } from '@/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration';
|
||||
import { WORKFLOW_VISUALIZER_EDGE_SUCCESS_CONFIGURATION } from '@/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeSuccessConfiguration';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { ReactflowDecorator } from '~/testing/decorators/ReactflowDecorator';
|
||||
import { WorkspaceDecorator } from '~/testing/decorators/WorkspaceDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { workflowDiagramState } from '../../states/workflowDiagramState';
|
||||
import { workflowDiagramComponentState } from '../../states/workflowDiagramComponentState';
|
||||
import { WorkflowDiagramCanvasBase } from '../WorkflowDiagramCanvasBase';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -51,63 +52,79 @@ export const DefaultEdge: Story = {
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(workflowDiagramState, {
|
||||
nodes: [
|
||||
(Story) => {
|
||||
const workflowVisualizerComponentInstanceId =
|
||||
'workflow-visualizer-test-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
workflowDiagramComponentState.atomFamily({
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}),
|
||||
{
|
||||
id: 'trigger-1',
|
||||
type: 'default',
|
||||
position: { x: 100, y: 100 },
|
||||
data: {
|
||||
nodeType: 'trigger',
|
||||
triggerType: 'DATABASE_EVENT',
|
||||
name: 'When record is created',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
id: 'trigger-1',
|
||||
type: 'default',
|
||||
position: { x: 100, y: 100 },
|
||||
data: {
|
||||
nodeType: 'trigger',
|
||||
triggerType: 'DATABASE_EVENT',
|
||||
name: 'When record is created',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'action-1',
|
||||
type: 'default',
|
||||
position: { x: 300, y: 100 },
|
||||
data: {
|
||||
nodeType: 'action',
|
||||
actionType: 'CREATE_RECORD',
|
||||
name: 'Create record',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'create-step-1',
|
||||
type: 'create-step',
|
||||
position: { x: 500, y: 100 },
|
||||
data: {
|
||||
nodeType: 'create-step',
|
||||
parentNodeId: 'action-1',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION,
|
||||
id: 'edge-1',
|
||||
source: 'trigger-1',
|
||||
target: 'action-1',
|
||||
},
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION,
|
||||
id: 'edge-2',
|
||||
source: 'action-1',
|
||||
target: 'create-step-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'action-1',
|
||||
type: 'default',
|
||||
position: { x: 300, y: 100 },
|
||||
data: {
|
||||
nodeType: 'action',
|
||||
actionType: 'CREATE_RECORD',
|
||||
name: 'Create record',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'create-step-1',
|
||||
type: 'create-step',
|
||||
position: { x: 500, y: 100 },
|
||||
data: {
|
||||
nodeType: 'create-step',
|
||||
parentNodeId: 'action-1',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION,
|
||||
id: 'edge-1',
|
||||
source: 'trigger-1',
|
||||
target: 'action-1',
|
||||
},
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION,
|
||||
id: 'edge-2',
|
||||
source: 'action-1',
|
||||
target: 'create-step-1',
|
||||
},
|
||||
],
|
||||
});
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<Story />
|
||||
</StyledContainer>
|
||||
</RecoilRoot>
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<Story />
|
||||
</StyledContainer>
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -124,49 +141,65 @@ export const SuccessEdge: Story = {
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(workflowDiagramState, {
|
||||
nodes: [
|
||||
(Story) => {
|
||||
const workflowVisualizerComponentInstanceId =
|
||||
'workflow-visualizer-test-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
workflowDiagramComponentState.atomFamily({
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}),
|
||||
{
|
||||
id: 'trigger-1',
|
||||
type: 'default',
|
||||
position: { x: 100, y: 100 },
|
||||
data: {
|
||||
nodeType: 'trigger',
|
||||
triggerType: 'DATABASE_EVENT',
|
||||
name: 'When record is created',
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
id: 'trigger-1',
|
||||
type: 'default',
|
||||
position: { x: 100, y: 100 },
|
||||
data: {
|
||||
nodeType: 'trigger',
|
||||
triggerType: 'DATABASE_EVENT',
|
||||
name: 'When record is created',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'action-1',
|
||||
type: 'default',
|
||||
position: { x: 300, y: 100 },
|
||||
data: {
|
||||
nodeType: 'action',
|
||||
actionType: 'CREATE_RECORD',
|
||||
name: 'Create record',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_SUCCESS_CONFIGURATION,
|
||||
id: 'edge-1',
|
||||
source: 'trigger-1',
|
||||
target: 'action-1',
|
||||
type: 'success',
|
||||
label: '1 item',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'action-1',
|
||||
type: 'default',
|
||||
position: { x: 300, y: 100 },
|
||||
data: {
|
||||
nodeType: 'action',
|
||||
actionType: 'CREATE_RECORD',
|
||||
name: 'Create record',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
...WORKFLOW_VISUALIZER_EDGE_SUCCESS_CONFIGURATION,
|
||||
id: 'edge-1',
|
||||
source: 'trigger-1',
|
||||
target: 'action-1',
|
||||
type: 'success',
|
||||
label: '1 item',
|
||||
},
|
||||
],
|
||||
});
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<Story />
|
||||
</StyledContainer>
|
||||
</RecoilRoot>
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<Story />
|
||||
</StyledContainer>
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -1,15 +1,25 @@
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { workflowDiagramTriggerNodeSelectionComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionComponentState';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { useReactFlow } from '@xyflow/react';
|
||||
import { RecoilRoot, useRecoilState } from 'recoil';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
jest.mock('@xyflow/react', () => ({
|
||||
useReactFlow: jest.fn(),
|
||||
}));
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
<RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: 'test-instance-id',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useTriggerNodeSelection', () => {
|
||||
@ -31,7 +41,9 @@ describe('useTriggerNodeSelection', () => {
|
||||
const [
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
] = useRecoilState(workflowDiagramTriggerNodeSelectionState);
|
||||
] = useRecoilComponentStateV2(
|
||||
workflowDiagramTriggerNodeSelectionComponentState,
|
||||
);
|
||||
|
||||
useTriggerNodeSelection();
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowDiagramStatusState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusState';
|
||||
import { workflowRunStepToOpenByDefaultState } from '@/workflow/workflow-diagram/states/workflowRunStepToOpenByDefaultState';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowDiagramStatusComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusComponentState';
|
||||
import { workflowRunStepToOpenByDefaultComponentState } from '@/workflow/workflow-diagram/states/workflowRunStepToOpenByDefaultComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
@ -17,6 +19,21 @@ export const useHandleWorkflowRunDiagramCanvasInit = () => {
|
||||
const { openWorkflowRunViewStepInCommandMenu } = useWorkflowCommandMenu();
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
|
||||
const workflowRunId = useWorkflowRunIdOrThrow();
|
||||
|
||||
const workflowVisualizerWorkflowIdState = useRecoilComponentCallbackStateV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflowDiagramStatusState = useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramStatusComponentState,
|
||||
);
|
||||
const workflowRunStepToOpenByDefaultState = useRecoilComponentCallbackStateV2(
|
||||
workflowRunStepToOpenByDefaultComponentState,
|
||||
);
|
||||
const workflowSelectedNodeState = useRecoilComponentCallbackStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const handleWorkflowRunDiagramCanvasInit = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
() => {
|
||||
@ -43,8 +60,11 @@ export const useHandleWorkflowRunDiagramCanvasInit = () => {
|
||||
);
|
||||
|
||||
if (isDefined(workflowStepToOpenByDefault)) {
|
||||
const workflowId = getSnapshotValue(snapshot, workflowIdState);
|
||||
if (!isDefined(workflowId)) {
|
||||
const workflowVisualizerWorkflowId = getSnapshotValue(
|
||||
snapshot,
|
||||
workflowVisualizerWorkflowIdState,
|
||||
);
|
||||
if (!isDefined(workflowVisualizerWorkflowId)) {
|
||||
throw new Error(
|
||||
'The workflow id must be set; ensure the workflow id is always set before rendering the workflow diagram.',
|
||||
);
|
||||
@ -53,7 +73,8 @@ export const useHandleWorkflowRunDiagramCanvasInit = () => {
|
||||
set(workflowSelectedNodeState, workflowStepToOpenByDefault.id);
|
||||
|
||||
openWorkflowRunViewStepInCommandMenu({
|
||||
workflowId,
|
||||
workflowId: workflowVisualizerWorkflowId,
|
||||
workflowRunId,
|
||||
title: workflowStepToOpenByDefault.data.name,
|
||||
icon: getIcon(
|
||||
getWorkflowNodeIconKey(workflowStepToOpenByDefault.data),
|
||||
@ -65,7 +86,16 @@ export const useHandleWorkflowRunDiagramCanvasInit = () => {
|
||||
set(workflowRunStepToOpenByDefaultState, undefined);
|
||||
}
|
||||
},
|
||||
[getIcon, isInRightDrawer, openWorkflowRunViewStepInCommandMenu],
|
||||
[
|
||||
workflowDiagramStatusState,
|
||||
isInRightDrawer,
|
||||
workflowRunStepToOpenByDefaultState,
|
||||
workflowVisualizerWorkflowIdState,
|
||||
workflowSelectedNodeState,
|
||||
openWorkflowRunViewStepInCommandMenu,
|
||||
workflowRunId,
|
||||
getIcon,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowCreateStepFromParentStepIdState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { workflowCreateStepFromParentStepIdComponentState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useStartNodeCreation = () => {
|
||||
const setWorkflowCreateStepFromParentStepId = useSetRecoilState(
|
||||
workflowCreateStepFromParentStepIdState,
|
||||
const setWorkflowCreateStepFromParentStepId = useSetRecoilComponentStateV2(
|
||||
workflowCreateStepFromParentStepIdComponentState,
|
||||
);
|
||||
const { openStepSelectInCommandMenu } = useWorkflowCommandMenu();
|
||||
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
/**
|
||||
* This function is used in a context where dependencies shouldn't change much.
|
||||
@ -22,14 +25,14 @@ export const useStartNodeCreation = () => {
|
||||
(parentNodeId: string) => {
|
||||
setWorkflowCreateStepFromParentStepId(parentNodeId);
|
||||
|
||||
if (isDefined(workflowId)) {
|
||||
openStepSelectInCommandMenu(workflowId);
|
||||
if (isDefined(workflowVisualizerWorkflowId)) {
|
||||
openStepSelectInCommandMenu(workflowVisualizerWorkflowId);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[
|
||||
setWorkflowCreateStepFromParentStepId,
|
||||
workflowId,
|
||||
workflowVisualizerWorkflowId,
|
||||
openStepSelectInCommandMenu,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { workflowDiagramTriggerNodeSelectionComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionComponentState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramNode,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { useReactFlow } from '@xyflow/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useTriggerNodeSelection = () => {
|
||||
@ -14,7 +14,9 @@ export const useTriggerNodeSelection = () => {
|
||||
const [
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
] = useRecoilState(workflowDiagramTriggerNodeSelectionState);
|
||||
] = useRecoilComponentStateV2(
|
||||
workflowDiagramTriggerNodeSelectionComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(workflowDiagramTriggerNodeSelection)) {
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useWorkflowSelectedNodeOrThrow = () => {
|
||||
const workflowSelectedNode = useRecoilValue(workflowSelectedNodeState);
|
||||
const workflowSelectedNode = useRecoilComponentValueV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
if (!isDefined(workflowSelectedNode)) {
|
||||
throw new Error(
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const WorkflowRunVisualizerComponentInstanceContext =
|
||||
createComponentInstanceContext({
|
||||
instanceId: '',
|
||||
});
|
||||
@ -0,0 +1,6 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const WorkflowVisualizerComponentInstanceContext =
|
||||
createComponentInstanceContext({
|
||||
instanceId: '',
|
||||
});
|
||||
@ -0,0 +1,11 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { WorkflowDiagram } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
|
||||
export const workflowDiagramComponentState = createComponentStateV2<
|
||||
WorkflowDiagram | undefined
|
||||
>({
|
||||
key: 'workflowDiagramComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
import { WorkflowDiagram } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowDiagramState = createState<WorkflowDiagram | undefined>({
|
||||
key: 'workflowDiagramState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,12 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowRunVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowRunVisualizerComponentInstanceContext';
|
||||
import { WorkflowDiagramStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagramStatus';
|
||||
|
||||
// This state must be fresh every time the Reactflow component is mounted.
|
||||
// We use another instance context whose instanceId is an id unique to the component hierarchy.
|
||||
export const workflowDiagramStatusComponentState =
|
||||
createComponentStateV2<WorkflowDiagramStatus>({
|
||||
key: 'workflowDiagramStatusComponentState',
|
||||
defaultValue: 'computing-diagram',
|
||||
componentInstanceContext: WorkflowRunVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowDiagramStatusState = createState<
|
||||
'computing-diagram' | 'computing-dimensions' | 'done'
|
||||
>({
|
||||
key: 'workflowDiagramStatusState',
|
||||
defaultValue: 'computing-diagram',
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowDiagramTriggerNodeSelectionComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'workflowDiagramTriggerNodeSelectionComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
export const workflowDiagramTriggerNodeSelectionState = createState<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowDiagramTriggerNodeSelectionState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { RefObject } from 'react';
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowReactFlowRefState =
|
||||
createState<RefObject<HTMLDivElement> | null>({
|
||||
key: 'workflowReactFlowRefState',
|
||||
defaultValue: null,
|
||||
});
|
||||
@ -0,0 +1,16 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { WorkflowRunDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
|
||||
export const workflowRunStepToOpenByDefaultComponentState =
|
||||
createComponentStateV2<
|
||||
| {
|
||||
id: string;
|
||||
data: WorkflowRunDiagramStepNodeData;
|
||||
}
|
||||
| undefined
|
||||
>({
|
||||
key: 'workflowRunStepToOpenByDefaultComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,13 +0,0 @@
|
||||
import { WorkflowRunDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowRunStepToOpenByDefaultState = createState<
|
||||
| {
|
||||
id: string;
|
||||
data: WorkflowRunDiagramStepNodeData;
|
||||
}
|
||||
| undefined
|
||||
>({
|
||||
key: 'workflowStepIdToOpenByDefaultState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowSelectedNodeComponentState = createComponentStateV2<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowSelectedNodeComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const workflowSelectedNodeState = createState<string | undefined>({
|
||||
key: 'workflowSelectedNodeState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
export type WorkflowDiagramStatus =
|
||||
| 'computing-diagram'
|
||||
| 'computing-dimensions'
|
||||
| 'done';
|
||||
@ -1,53 +0,0 @@
|
||||
import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useCreateStep } from '../useCreateStep';
|
||||
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
const mockCreateWorkflowVersionStep = jest.fn().mockResolvedValue({
|
||||
data: { createWorkflowVersionStep: { id: '1', type: 'CODE' } },
|
||||
});
|
||||
|
||||
jest.mock('recoil', () => ({
|
||||
useRecoilValue: () => 'parent-step-id',
|
||||
useSetRecoilState: () => jest.fn(),
|
||||
atom: (params: any) => params,
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
'@/workflow/workflow-steps/hooks/useCreateWorkflowVersionStep',
|
||||
() => ({
|
||||
useCreateWorkflowVersionStep: () => ({
|
||||
createWorkflowVersionStep: mockCreateWorkflowVersionStep,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
createDraftFromWorkflowVersion: mockCreateDraftFromWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useCreateStep', () => {
|
||||
const mockWorkflow = {
|
||||
id: '123',
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
steps: [],
|
||||
trigger: { type: 'manual' },
|
||||
},
|
||||
versions: [],
|
||||
};
|
||||
|
||||
it('should create step in draft version', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useCreateStep({
|
||||
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
|
||||
}),
|
||||
);
|
||||
await result.current.createStep('CODE');
|
||||
|
||||
expect(mockCreateWorkflowVersionStep).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,80 @@
|
||||
import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { workflowCreateStepFromParentStepIdComponentState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdComponentState';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { useCreateStep } from '../useCreateStep';
|
||||
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
const mockCreateWorkflowVersionStep = jest.fn().mockResolvedValue({
|
||||
data: { createWorkflowVersionStep: { id: '1', type: 'CODE' } },
|
||||
});
|
||||
|
||||
jest.mock(
|
||||
'@/workflow/workflow-steps/hooks/useCreateWorkflowVersionStep',
|
||||
() => ({
|
||||
useCreateWorkflowVersionStep: () => ({
|
||||
createWorkflowVersionStep: mockCreateWorkflowVersionStep,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
createDraftFromWorkflowVersion: mockCreateDraftFromWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
const workflowVisualizerComponentInstanceId =
|
||||
'workflow-visualizer-instance-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
workflowCreateStepFromParentStepIdComponentState.atomFamily({
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}),
|
||||
'parent-step-id',
|
||||
);
|
||||
}}
|
||||
>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useCreateStep', () => {
|
||||
const mockWorkflow = {
|
||||
id: '123',
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
steps: [],
|
||||
trigger: { type: 'manual' },
|
||||
},
|
||||
versions: [],
|
||||
};
|
||||
|
||||
it('should create step in draft version', async () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useCreateStep({
|
||||
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
|
||||
}),
|
||||
{
|
||||
wrapper,
|
||||
},
|
||||
);
|
||||
await result.current.createStep('CODE');
|
||||
|
||||
expect(mockCreateWorkflowVersionStep).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@ -1,13 +1,14 @@
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { workflowLastCreatedStepIdState } from '@/workflow/states/workflowLastCreatedStepIdState';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import {
|
||||
WorkflowStepType,
|
||||
WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { useCreateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useCreateWorkflowVersionStep';
|
||||
import { workflowCreateStepFromParentStepIdState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdState';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { workflowCreateStepFromParentStepIdComponentState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCreateStep = ({
|
||||
@ -16,13 +17,15 @@ export const useCreateStep = ({
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
const { createWorkflowVersionStep } = useCreateWorkflowVersionStep();
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const setWorkflowLastCreatedStepId = useSetRecoilState(
|
||||
workflowLastCreatedStepIdState,
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
const setWorkflowLastCreatedStepId = useSetRecoilComponentStateV2(
|
||||
workflowLastCreatedStepIdComponentState,
|
||||
);
|
||||
|
||||
const workflowCreateStepFromParentStepId = useRecoilValue(
|
||||
workflowCreateStepFromParentStepIdState,
|
||||
const workflowCreateStepFromParentStepId = useRecoilComponentValueV2(
|
||||
workflowCreateStepFromParentStepIdComponentState,
|
||||
);
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
export const workflowCreateStepFromParentStepIdComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'workflowCreateStepFromParentStepIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: WorkflowVisualizerComponentInstanceContext,
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
export const workflowCreateStepFromParentStepIdState = createState<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowCreateStepFromParentStepId',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -3,7 +3,7 @@ import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-func
|
||||
import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepHeader } from '@/workflow/workflow-steps/components/WorkflowStepHeader';
|
||||
import { setNestedValue } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/setNestedValue';
|
||||
@ -36,11 +36,11 @@ import { Monaco } from '@monaco-editor/react';
|
||||
import { editor } from 'monaco-editor';
|
||||
import { AutoTypings } from 'monaco-editor-auto-typings';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { CodeEditor } from 'twenty-ui/input';
|
||||
import { IconCode, IconPlayerPlay, useIcons } from 'twenty-ui/display';
|
||||
import { CodeEditor } from 'twenty-ui/input';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
const StyledCodeEditorContainer = styled.div`
|
||||
display: flex;
|
||||
@ -82,8 +82,10 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
useUpdateOneServerlessFunction(serverlessFunctionId);
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowId);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowVisualizerWorkflowId);
|
||||
const { availablePackages } = useGetAvailablePackages({
|
||||
id: serverlessFunctionId,
|
||||
});
|
||||
|
||||
@ -8,7 +8,8 @@ import { FormTextFieldInput } from '@/object-record/record-field/form-types/comp
|
||||
import { useTriggerApisOAuth } from '@/settings/accounts/hooks/useTriggerApiOAuth';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { WorkflowSendEmailAction } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepHeader } from '@/workflow/workflow-steps/components/WorkflowStepHeader';
|
||||
@ -20,11 +21,11 @@ import { useEffect, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
||||
import { IconPlus, useIcons } from 'twenty-ui/display';
|
||||
import { SelectOption } from 'twenty-ui/input';
|
||||
import { JsonValue } from 'type-fest';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { IconPlus, useIcons } from 'twenty-ui/display';
|
||||
import { SelectOption } from 'twenty-ui/input';
|
||||
|
||||
type WorkflowEditActionSendEmailProps = {
|
||||
action: WorkflowSendEmailAction;
|
||||
@ -53,8 +54,10 @@ export const WorkflowEditActionSendEmail = ({
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const { triggerApisOAuth } = useTriggerApisOAuth();
|
||||
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const redirectUrl = `/object/workflow/${workflowId}`;
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const redirectUrl = `/object/workflow/${workflowVisualizerWorkflowId}`;
|
||||
|
||||
const [formData, setFormData] = useState<SendEmailFormData>({
|
||||
connectedAccountId: action.settings.input.connectedAccountId,
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { RightDrawerWorkflowSelectTriggerTypeContent } from '@/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerTypeContent';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RightDrawerWorkflowSelectTriggerType = () => {
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowId);
|
||||
|
||||
if (!isDefined(workflow)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <RightDrawerWorkflowSelectTriggerTypeContent workflow={workflow} />;
|
||||
};
|
||||
@ -1,86 +0,0 @@
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import {
|
||||
WorkflowTriggerType,
|
||||
WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { RightDrawerStepListContainer } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepContainer';
|
||||
import { RightDrawerWorkflowSelectStepTitle } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepTitle';
|
||||
import { DATABASE_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/DatabaseTriggerTypes';
|
||||
import { OTHER_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/OtherTriggerTypes';
|
||||
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
|
||||
import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger';
|
||||
import { getTriggerDefaultDefinition } from '@/workflow/workflow-trigger/utils/getTriggerDefaultDefinition';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { MenuItemCommand } from 'twenty-ui/navigation';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
export const RightDrawerWorkflowSelectTriggerTypeContent = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
const { getIcon } = useIcons();
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow });
|
||||
|
||||
const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
|
||||
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();
|
||||
|
||||
const handleTriggerTypeClick = ({
|
||||
type,
|
||||
defaultLabel,
|
||||
icon,
|
||||
}: {
|
||||
type: WorkflowTriggerType;
|
||||
defaultLabel: string;
|
||||
icon: string;
|
||||
}) => {
|
||||
return async () => {
|
||||
await updateTrigger(
|
||||
getTriggerDefaultDefinition({
|
||||
defaultLabel,
|
||||
type,
|
||||
activeObjectMetadataItems,
|
||||
}),
|
||||
);
|
||||
|
||||
setWorkflowSelectedNode(TRIGGER_STEP_ID);
|
||||
|
||||
openWorkflowEditStepInCommandMenu(
|
||||
workflow.id,
|
||||
defaultLabel,
|
||||
getIcon(icon),
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<RightDrawerStepListContainer>
|
||||
<RightDrawerWorkflowSelectStepTitle>
|
||||
Data
|
||||
</RightDrawerWorkflowSelectStepTitle>
|
||||
{DATABASE_TRIGGER_TYPES.map((action) => (
|
||||
<MenuItemCommand
|
||||
key={action.defaultLabel}
|
||||
LeftIcon={getIcon(action.icon)}
|
||||
text={action.defaultLabel}
|
||||
onClick={handleTriggerTypeClick(action)}
|
||||
/>
|
||||
))}
|
||||
<RightDrawerWorkflowSelectStepTitle>
|
||||
Others
|
||||
</RightDrawerWorkflowSelectStepTitle>
|
||||
{OTHER_TRIGGER_TYPES.map((action) => (
|
||||
<MenuItemCommand
|
||||
key={action.defaultLabel}
|
||||
LeftIcon={getIcon(action.icon)}
|
||||
text={action.defaultLabel}
|
||||
onClick={handleTriggerTypeClick(action)}
|
||||
/>
|
||||
))}
|
||||
</RightDrawerStepListContainer>
|
||||
);
|
||||
};
|
||||
@ -5,7 +5,8 @@ import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/Snac
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { WorkflowWebhookTrigger } from '@/workflow/types/Workflow';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowStepHeader } from '@/workflow/workflow-steps/components/WorkflowStepHeader';
|
||||
@ -54,7 +55,9 @@ export const WorkflowEditTriggerWebhookForm = ({
|
||||
const [errorMessages, setErrorMessages] = useState<FormErrorMessages>({});
|
||||
const [errorMessagesVisible, setErrorMessagesVisible] = useState(false);
|
||||
const { getIcon } = useIcons();
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
const onBlur = () => {
|
||||
@ -66,7 +69,7 @@ export const WorkflowEditTriggerWebhookForm = ({
|
||||
const headerIcon = getTriggerIcon(trigger);
|
||||
const headerType = getTriggerHeaderType(trigger);
|
||||
|
||||
const webhookUrl = `${REACT_APP_SERVER_BASE_URL}/webhooks/workflows/${currentWorkspace?.id}/${workflowId}`;
|
||||
const webhookUrl = `${REACT_APP_SERVER_BASE_URL}/webhooks/workflows/${currentWorkspace?.id}/${workflowVisualizerWorkflowId}`;
|
||||
const displayWebhookUrl = webhookUrl.replace(/^(https?:\/\/)?(www\.)?/, '');
|
||||
|
||||
const copyToClipboard = async () => {
|
||||
|
||||
@ -13,13 +13,12 @@ import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isReco
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab/states/activeTabIdComponentState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { workflowDiagramTriggerNodeSelectionComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath';
|
||||
import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel';
|
||||
import { isLinkOutputSchema } from '@/workflow/workflow-variables/utils/isLinkOutputSchema';
|
||||
import { useState } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
IconChevronLeft,
|
||||
@ -42,13 +41,15 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
||||
const [currentPath, setCurrentPath] = useState<string[]>([]);
|
||||
const [searchInputValue, setSearchInputValue] = useState('');
|
||||
const { getIcon } = useIcons();
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
const setActiveTabId = useSetRecoilComponentStateV2(
|
||||
activeTabIdComponentState,
|
||||
'workflow-serverless-function-tab-list-component-id',
|
||||
);
|
||||
const setWorkflowDiagramTriggerNodeSelection = useSetRecoilState(
|
||||
workflowDiagramTriggerNodeSelectionState,
|
||||
const setWorkflowDiagramTriggerNodeSelection = useSetRecoilComponentStateV2(
|
||||
workflowDiagramTriggerNodeSelectionComponentState,
|
||||
);
|
||||
|
||||
const getDisplayedSubStepFields = () => {
|
||||
|
||||
Reference in New Issue
Block a user