Stop propagating full workflow in components (#13900)
Workflow, workflow version and workflow runs should not be passed through props or context. These are set in recoil component states and that's where all hooks should look for these. This PR stop propagating workflow with version through all components.
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@ export const CommandMenuWorkflowEditStep = () => {
|
||||
<WorkflowStepContextProvider
|
||||
value={{ workflowVersionId: workflow.currentVersion.id }}
|
||||
>
|
||||
<CommandMenuWorkflowEditStepContent workflow={workflow} />
|
||||
<CommandMenuWorkflowEditStepContent />
|
||||
</WorkflowStepContextProvider>
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
);
|
||||
|
||||
+3
-10
@@ -1,6 +1,5 @@
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail';
|
||||
import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
|
||||
@@ -14,20 +13,14 @@ const StyledContainer = styled.div`
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export const CommandMenuWorkflowEditStepContent = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
export const CommandMenuWorkflowEditStepContent = () => {
|
||||
const flow = useFlowOrThrow();
|
||||
const workflowSelectedNode = useRecoilComponentValue(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow });
|
||||
const { updateStep } = useUpdateStep({
|
||||
workflow,
|
||||
});
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger();
|
||||
const { updateStep } = useUpdateStep();
|
||||
|
||||
if (!isDefined(workflowSelectedNode)) {
|
||||
return null;
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ export const CommandMenuWorkflowSelectTriggerTypeContent = ({
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
const { getIcon } = useIcons();
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow });
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger();
|
||||
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ export const CardComponents: Record<CardType, CardComponentType> = {
|
||||
>
|
||||
<WorkflowVisualizerEffect workflowId={targetableObject.id} />
|
||||
<Suspense fallback={<LoadingSkeleton />}>
|
||||
<WorkflowVisualizer workflowId={targetableObject.id} />
|
||||
<WorkflowVisualizer />
|
||||
</Suspense>
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import {
|
||||
type ExecutionStatus,
|
||||
WorkflowStepExecutionResult,
|
||||
} from '@/workflow/components/WorkflowStepExecutionResult';
|
||||
import { type ServerlessFunctionTestData } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { type ServerlessFunctionTestData } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { ServerlessFunctionExecutionStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
export const ServerlessFunctionExecutionResult = ({
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
|
||||
export const useTestServerlessFunction = ({
|
||||
serverlessFunctionId,
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { ServerlessFunctionExecutionResult } from '@/serverless-functions/components/ServerlessFunctionExecutionResult';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { H2Title, IconPlayerPlay } from 'twenty-ui/display';
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { INDEX_FILE_PATH } from '@/serverless-functions/constants/IndexFilePath'
|
||||
import { getFunctionInputFromSourceCode } from '@/serverless-functions/utils/getFunctionInputFromSourceCode';
|
||||
import { useGetOneServerlessFunction } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunction';
|
||||
import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunctionSourceCode';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { type Dispatch, type SetStateAction, useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { type FindOneServerlessFunctionSourceCodeQuery } from '~/generated-metadata/graphql';
|
||||
|
||||
+72
-32
@@ -1,8 +1,16 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
const mockWorkflowId = '123';
|
||||
const mockWorkflow = {
|
||||
id: mockWorkflowId,
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
},
|
||||
} as WorkflowWithCurrentVersion;
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
@@ -10,43 +18,75 @@ jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useGetUpdatableWorkflowVersion', () => {
|
||||
const mockWorkflow = (status: 'ACTIVE' | 'DRAFT') =>
|
||||
({
|
||||
id: '123',
|
||||
__typename: 'Workflow',
|
||||
statuses: [],
|
||||
lastPublishedVersionId: '1',
|
||||
name: 'toto',
|
||||
versions: [],
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
name: 'toto',
|
||||
createdAt: '2024-07-03T20:03:35.064Z',
|
||||
updatedAt: '2024-07-03T20:03:35.064Z',
|
||||
workflowId: '123',
|
||||
__typename: 'WorkflowVersion',
|
||||
status,
|
||||
steps: [],
|
||||
trigger: null,
|
||||
},
|
||||
}) as WorkflowWithCurrentVersion;
|
||||
jest.mock(
|
||||
'@/ui/utilities/state/component-state/hooks/useRecoilComponentValue',
|
||||
() => ({
|
||||
useRecoilComponentValue: jest.fn(() => mockWorkflowId),
|
||||
}),
|
||||
);
|
||||
|
||||
it('should not create workflow version if draft version exists', async () => {
|
||||
const { result } = renderHook(() => useGetUpdatableWorkflowVersion());
|
||||
const workflowVersionId = await result.current.getUpdatableWorkflowVersion(
|
||||
mockWorkflow('DRAFT'),
|
||||
jest.mock('@/workflow/hooks/useWorkflowWithCurrentVersion', () => ({
|
||||
useWorkflowWithCurrentVersion: jest.fn((workflowId) =>
|
||||
workflowId === mockWorkflowId ? mockWorkflow : undefined,
|
||||
),
|
||||
}));
|
||||
|
||||
describe('useGetUpdatableWorkflowVersionOrThrow', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return draft version id when current version is draft', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useGetUpdatableWorkflowVersionOrThrow(),
|
||||
);
|
||||
const workflowVersionId =
|
||||
await result.current.getUpdatableWorkflowVersion();
|
||||
|
||||
expect(mockCreateDraftFromWorkflowVersion).not.toHaveBeenCalled();
|
||||
expect(workflowVersionId).toEqual('456');
|
||||
});
|
||||
|
||||
it('should create workflow version if no draft version exists', async () => {
|
||||
const { result } = renderHook(() => useGetUpdatableWorkflowVersion());
|
||||
const workflowVersionId = await result.current.getUpdatableWorkflowVersion(
|
||||
mockWorkflow('ACTIVE'),
|
||||
it('should create draft from active version when current version is active', async () => {
|
||||
// Mock the workflow to have an active version
|
||||
const mockActiveWorkflow = {
|
||||
...mockWorkflow,
|
||||
currentVersion: {
|
||||
...mockWorkflow.currentVersion,
|
||||
status: 'ACTIVE',
|
||||
},
|
||||
} as WorkflowWithCurrentVersion;
|
||||
|
||||
const {
|
||||
useWorkflowWithCurrentVersion,
|
||||
} = require('@/workflow/hooks/useWorkflowWithCurrentVersion');
|
||||
useWorkflowWithCurrentVersion.mockReturnValue(mockActiveWorkflow);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGetUpdatableWorkflowVersionOrThrow(),
|
||||
);
|
||||
expect(mockCreateDraftFromWorkflowVersion).toHaveBeenCalled();
|
||||
const workflowVersionId =
|
||||
await result.current.getUpdatableWorkflowVersion();
|
||||
|
||||
expect(mockCreateDraftFromWorkflowVersion).toHaveBeenCalledWith({
|
||||
workflowId: mockWorkflowId,
|
||||
workflowVersionIdToCopy: '456',
|
||||
});
|
||||
expect(workflowVersionId).toEqual('457');
|
||||
});
|
||||
|
||||
it('should throw an error when workflow is not found', async () => {
|
||||
const {
|
||||
useWorkflowWithCurrentVersion,
|
||||
} = require('@/workflow/hooks/useWorkflowWithCurrentVersion');
|
||||
useWorkflowWithCurrentVersion.mockReturnValue(undefined);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useGetUpdatableWorkflowVersionOrThrow(),
|
||||
);
|
||||
|
||||
await expect(result.current.getUpdatableWorkflowVersion()).rejects.toThrow(
|
||||
'Failed to get updatable workflow version',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useCreateDraftFromWorkflowVersion } from '@/workflow/hooks/useCreateDraftFromWorkflowVersion';
|
||||
|
||||
export const useGetUpdatableWorkflowVersion = () => {
|
||||
const { createDraftFromWorkflowVersion } =
|
||||
useCreateDraftFromWorkflowVersion();
|
||||
const getUpdatableWorkflowVersion = async (
|
||||
workflow: WorkflowWithCurrentVersion,
|
||||
) => {
|
||||
if (workflow.currentVersion.status === 'DRAFT') {
|
||||
return workflow.currentVersion.id;
|
||||
}
|
||||
return await createDraftFromWorkflowVersion({
|
||||
workflowId: workflow.id,
|
||||
workflowVersionIdToCopy: workflow.currentVersion.id,
|
||||
});
|
||||
};
|
||||
|
||||
return { getUpdatableWorkflowVersion };
|
||||
};
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useCreateDraftFromWorkflowVersion } from '@/workflow/hooks/useCreateDraftFromWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useGetUpdatableWorkflowVersionOrThrow = () => {
|
||||
const { createDraftFromWorkflowVersion } =
|
||||
useCreateDraftFromWorkflowVersion();
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowVisualizerWorkflowId);
|
||||
|
||||
const getUpdatableWorkflowVersion = async (): Promise<string> => {
|
||||
if (!isDefined(workflowVisualizerWorkflowId) || !isDefined(workflow)) {
|
||||
throw new Error('Failed to get updatable workflow version');
|
||||
}
|
||||
|
||||
if (workflow.currentVersion.status === 'DRAFT') {
|
||||
return workflow.currentVersion.id;
|
||||
}
|
||||
|
||||
const draftVersionId = await createDraftFromWorkflowVersion({
|
||||
workflowId: workflowVisualizerWorkflowId,
|
||||
workflowVersionIdToCopy: workflow.currentVersion.id,
|
||||
});
|
||||
|
||||
if (!isDefined(draftVersionId)) {
|
||||
throw new Error('Failed to create draft version');
|
||||
}
|
||||
|
||||
return draftVersionId;
|
||||
};
|
||||
|
||||
return { getUpdatableWorkflowVersion };
|
||||
};
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '../assertWorkflowWithCurrentVersionIsDefined';
|
||||
|
||||
it('throws when provided workflow is undefined', () => {
|
||||
expect(() => {
|
||||
assertWorkflowWithCurrentVersionIsDefined(undefined);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it("throws when provided workflow's current version is undefined", () => {
|
||||
expect(() => {
|
||||
assertWorkflowWithCurrentVersionIsDefined(
|
||||
{} as unknown as WorkflowWithCurrentVersion,
|
||||
);
|
||||
}).toThrow();
|
||||
});
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
type Workflow,
|
||||
type WorkflowVersion,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
||||
export function assertWorkflowWithCurrentVersionIsDefined(
|
||||
workflow: WorkflowWithCurrentVersion | undefined,
|
||||
): asserts workflow is Workflow & { currentVersion: WorkflowVersion } {
|
||||
if (!isDefined(workflow) || !isDefined(workflow.currentVersion)) {
|
||||
throw new Error('Expected workflow and its current version to be defined');
|
||||
}
|
||||
}
|
||||
+23
-21
@@ -1,5 +1,7 @@
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { WorkflowDiagramBlankEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramBlankEdge';
|
||||
import { WorkflowDiagramCanvasBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase';
|
||||
import { WorkflowDiagramCanvasEditableEffect } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect';
|
||||
@@ -23,14 +25,14 @@ import { addEdge, type Connection, ReactFlowProvider } from '@xyflow/react';
|
||||
import React from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const WorkflowDiagramCanvasEditable = ({
|
||||
workflowWithCurrentVersion,
|
||||
}: {
|
||||
workflowWithCurrentVersion: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
const tagProps = getWorkflowVersionStatusTagProps({
|
||||
workflowVersionStatus: workflowWithCurrentVersion.currentVersion.status,
|
||||
});
|
||||
export const WorkflowDiagramCanvasEditable = () => {
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
workflowVisualizerWorkflowId,
|
||||
);
|
||||
|
||||
const setWorkflowDiagram = useSetRecoilComponentState(
|
||||
workflowDiagramComponentState,
|
||||
@@ -40,21 +42,13 @@ export const WorkflowDiagramCanvasEditable = ({
|
||||
workflowDiagramRightClickMenuPositionState,
|
||||
);
|
||||
|
||||
const { createEdge } = useCreateEdge({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { createEdge } = useCreateEdge();
|
||||
|
||||
const { deleteEdge } = useDeleteEdge({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { deleteEdge } = useDeleteEdge();
|
||||
|
||||
const { updateStep } = useUpdateStep({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { updateStep } = useUpdateStep();
|
||||
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { updateTrigger } = useUpdateWorkflowVersionTrigger();
|
||||
|
||||
const onConnect = (edgeConnect: Connection) => {
|
||||
setWorkflowDiagram((diagram) => {
|
||||
@@ -107,6 +101,14 @@ export const WorkflowDiagramCanvasEditable = ({
|
||||
}
|
||||
};
|
||||
|
||||
if (!isDefined(workflowWithCurrentVersion)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tagProps = getWorkflowVersionStatusTagProps({
|
||||
workflowVersionStatus: workflowWithCurrentVersion.currentVersion.status,
|
||||
});
|
||||
|
||||
const handlePaneContextMenu = ({ x, y }: { x: number; y: number }) => {
|
||||
setWorkflowDiagramRightClickMenuPosition({
|
||||
x,
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ export const WorkflowDiagramDefaultEdgeEditable = ({
|
||||
|
||||
const { createStep } = useCreateStep({ workflow });
|
||||
|
||||
const { deleteEdge } = useDeleteEdge({ workflow });
|
||||
const { deleteEdge } = useDeleteEdge();
|
||||
|
||||
const { startNodeCreation, isNodeCreationStarted } = useStartNodeCreation();
|
||||
|
||||
|
||||
+13
-9
@@ -1,13 +1,13 @@
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import {
|
||||
type WorkflowVersion,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
|
||||
import { getWorkflowVersionDiagram } from '@/workflow/workflow-diagram/utils/getWorkflowVersionDiagram';
|
||||
@@ -18,11 +18,15 @@ import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
|
||||
export const WorkflowDiagramEffect = ({
|
||||
workflowWithCurrentVersion,
|
||||
}: {
|
||||
workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined;
|
||||
}) => {
|
||||
export const WorkflowDiagramEffect = () => {
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
workflowVisualizerWorkflowId,
|
||||
);
|
||||
|
||||
const workflowDiagramState = useRecoilComponentCallbackState(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
|
||||
+2
-9
@@ -9,8 +9,6 @@ import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { WorkflowDiagramBaseEdge } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseEdge';
|
||||
import { WorkflowDiagramEdgeButtonGroup } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeButtonGroup';
|
||||
import { WorkflowDiagramEdgeV2Container } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2Container';
|
||||
@@ -107,15 +105,10 @@ export const WorkflowDiagramFilterEdgeEditable = ({
|
||||
targetY,
|
||||
});
|
||||
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
const workflow = useWorkflowWithCurrentVersion(workflowVisualizerWorkflowId);
|
||||
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
|
||||
const { deleteStep } = useDeleteStep({ workflow });
|
||||
const { deleteEdge } = useDeleteEdge({ workflow });
|
||||
const { deleteStep } = useDeleteStep();
|
||||
const { deleteEdge } = useDeleteEdge();
|
||||
const { startNodeCreation, isNodeCreationStarted } = useStartNodeCreation();
|
||||
|
||||
const setCommandMenuNavigationStack = useSetRecoilState(
|
||||
|
||||
+1
-13
@@ -1,6 +1,4 @@
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { useCloseRightClickMenu } from '@/workflow/workflow-diagram/hooks/useCloseRightClickMenu';
|
||||
import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation';
|
||||
import { useWorkflowDiagramScreenToFlowPosition } from '@/workflow/workflow-diagram/hooks/useWorkflowDiagramScreenToFlowPosition';
|
||||
@@ -43,17 +41,7 @@ export const WorkflowDiagramRightClickCommandMenu = () => {
|
||||
workflowDiagramRightClickMenuPositionState,
|
||||
);
|
||||
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
workflowVisualizerWorkflowId,
|
||||
);
|
||||
|
||||
const { tidyUpWorkflowVersion } = useTidyUpWorkflowVersion({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { tidyUpWorkflowVersion } = useTidyUpWorkflowVersion();
|
||||
|
||||
const handleReorderWorkflowDiagram = async () => {
|
||||
await tidyUpWorkflowVersion();
|
||||
|
||||
+1
-10
@@ -3,9 +3,7 @@ import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandM
|
||||
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '@/workflow/utils/assertWorkflowWithCurrentVersionIsDefined';
|
||||
import { WorkflowDiagramStepNodeEditableContent } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
@@ -31,14 +29,7 @@ export const WorkflowDiagramStepNodeEditable = ({
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
);
|
||||
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
workflowVisualizerWorkflowId,
|
||||
);
|
||||
assertWorkflowWithCurrentVersionIsDefined(workflowWithCurrentVersion);
|
||||
|
||||
const { deleteStep } = useDeleteStep({
|
||||
workflow: workflowWithCurrentVersion,
|
||||
});
|
||||
const { deleteStep } = useDeleteStep();
|
||||
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentState(
|
||||
workflowSelectedNodeComponentState,
|
||||
|
||||
+3
-16
@@ -1,24 +1,11 @@
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { WorkflowDiagramCanvasEditable } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable';
|
||||
import { WorkflowDiagramEffect } from '@/workflow/workflow-diagram/components/WorkflowDiagramEffect';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const WorkflowVisualizer = ({ workflowId }: { workflowId: string }) => {
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId);
|
||||
|
||||
if (!isDefined(workflowWithCurrentVersion)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export const WorkflowVisualizer = () => {
|
||||
return (
|
||||
<>
|
||||
<WorkflowDiagramEffect
|
||||
workflowWithCurrentVersion={workflowWithCurrentVersion}
|
||||
/>
|
||||
<WorkflowDiagramCanvasEditable
|
||||
workflowWithCurrentVersion={workflowWithCurrentVersion}
|
||||
/>
|
||||
<WorkflowDiagramEffect />
|
||||
<WorkflowDiagramCanvasEditable />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+20
-6
@@ -4,7 +4,7 @@ import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
import { useCreateStep } from '../useCreateStep';
|
||||
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
const mockCreateWorkflowVersionStep = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
createWorkflowVersionStep: { createdStep: { id: '1', type: 'CODE' } },
|
||||
@@ -20,9 +20,9 @@ jest.mock(
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
createDraftFromWorkflowVersion: mockCreateDraftFromWorkflowVersion,
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: () => ({
|
||||
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -55,7 +55,14 @@ describe('useCreateStep', () => {
|
||||
versions: [],
|
||||
};
|
||||
|
||||
it('should create step in draft version', async () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create step in workflow version', async () => {
|
||||
const mockWorkflowVersionId = 'version-123';
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
|
||||
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useCreateStep({
|
||||
@@ -74,6 +81,13 @@ describe('useCreateStep', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockCreateWorkflowVersionStep).toHaveBeenCalled();
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
|
||||
expect(mockCreateWorkflowVersionStep).toHaveBeenCalledWith({
|
||||
workflowVersionId: mockWorkflowVersionId,
|
||||
stepType: 'CODE',
|
||||
parentStepId: 'parent-step-id',
|
||||
nextStepId: undefined,
|
||||
position: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+43
-33
@@ -1,17 +1,10 @@
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
const mockDeleteWorkflowVersionStep = jest.fn();
|
||||
const updateOneRecordMock = jest.fn();
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
|
||||
jest.mock('@/object-record/hooks/useUpdateOneRecord', () => ({
|
||||
useUpdateOneRecord: () => ({
|
||||
updateOneRecord: updateOneRecordMock,
|
||||
}),
|
||||
}));
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
const mockDeleteStepsOutputSchema = jest.fn();
|
||||
const mockCloseCommandMenu = jest.fn();
|
||||
|
||||
jest.mock('@/workflow/hooks/useDeleteWorkflowVersionStep', () => ({
|
||||
useDeleteWorkflowVersionStep: () => ({
|
||||
@@ -19,34 +12,51 @@ jest.mock('@/workflow/hooks/useDeleteWorkflowVersionStep', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
createDraftFromWorkflowVersion: mockCreateDraftFromWorkflowVersion,
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: () => ({
|
||||
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('@/workflow/hooks/useStepsOutputSchema', () => ({
|
||||
useStepsOutputSchema: () => ({
|
||||
deleteStepsOutputSchema: mockDeleteStepsOutputSchema,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('@/command-menu/hooks/useCommandMenu', () => ({
|
||||
useCommandMenu: () => ({
|
||||
closeCommandMenu: mockCloseCommandMenu,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useDeleteStep', () => {
|
||||
const mockWorkflow = {
|
||||
id: '123',
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
steps: [],
|
||||
trigger: { type: 'manual' },
|
||||
},
|
||||
versions: [],
|
||||
};
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should delete step in draft version', async () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useDeleteStep({
|
||||
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
|
||||
}),
|
||||
{ wrapper: RecoilRoot },
|
||||
);
|
||||
await result.current.deleteStep('1');
|
||||
it('should delete step and clean up dependencies', async () => {
|
||||
const mockWorkflowVersionId = 'version-123';
|
||||
const mockStepId = 'step-1';
|
||||
const mockDeletedStepIds = ['step-1', 'step-2'];
|
||||
|
||||
expect(mockDeleteWorkflowVersionStep).toHaveBeenCalled();
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
|
||||
mockDeleteWorkflowVersionStep.mockResolvedValue({
|
||||
deletedStepIds: mockDeletedStepIds,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useDeleteStep());
|
||||
await result.current.deleteStep(mockStepId);
|
||||
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
|
||||
expect(mockDeleteWorkflowVersionStep).toHaveBeenCalledWith({
|
||||
workflowVersionId: mockWorkflowVersionId,
|
||||
stepId: mockStepId,
|
||||
});
|
||||
expect(mockCloseCommandMenu).toHaveBeenCalled();
|
||||
expect(mockDeleteStepsOutputSchema).toHaveBeenCalledWith({
|
||||
stepIds: mockDeletedStepIds,
|
||||
workflowVersionId: mockWorkflowVersionId,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+22
-31
@@ -1,15 +1,8 @@
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
|
||||
const mockUpdateWorkflowVersionStep = jest.fn();
|
||||
const mockCreateDraftFromWorkflowVersion = jest.fn().mockResolvedValue('457');
|
||||
|
||||
jest.mock('recoil', () => ({
|
||||
useRecoilValue: () => 'parent-step-id',
|
||||
useSetRecoilState: () => jest.fn(),
|
||||
atom: (params: any) => params,
|
||||
}));
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
|
||||
jest.mock(
|
||||
'@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionStep',
|
||||
@@ -20,35 +13,24 @@ jest.mock(
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useCreateDraftFromWorkflowVersion', () => ({
|
||||
useCreateDraftFromWorkflowVersion: () => ({
|
||||
createDraftFromWorkflowVersion: mockCreateDraftFromWorkflowVersion,
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: () => ({
|
||||
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('useUpdateStep', () => {
|
||||
const mockWorkflow = {
|
||||
id: '123',
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
steps: [],
|
||||
trigger: { type: 'manual' },
|
||||
},
|
||||
versions: [],
|
||||
};
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should update step in draft version', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useUpdateStep({
|
||||
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
|
||||
}),
|
||||
);
|
||||
await result.current.updateStep({
|
||||
it('should update step in workflow version', async () => {
|
||||
const mockWorkflowVersionId = 'version-123';
|
||||
const mockStep = {
|
||||
id: '1',
|
||||
name: 'name',
|
||||
valid: true,
|
||||
type: 'CODE',
|
||||
type: 'CODE' as const,
|
||||
settings: {
|
||||
input: {
|
||||
serverlessFunctionId: 'id',
|
||||
@@ -65,8 +47,17 @@ describe('useUpdateStep', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
expect(mockUpdateWorkflowVersionStep).toHaveBeenCalled();
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
|
||||
|
||||
const { result } = renderHook(() => useUpdateStep());
|
||||
await result.current.updateStep(mockStep);
|
||||
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
|
||||
expect(mockUpdateWorkflowVersionStep).toHaveBeenCalledWith({
|
||||
workflowVersionId: mockWorkflowVersionId,
|
||||
step: mockStep,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge';
|
||||
import { useCreateWorkflowVersionEdge } from '@/workflow/workflow-steps/hooks/useCreateWorkflowVersionEdge';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge';
|
||||
|
||||
export const useCreateEdge = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
export const useCreateEdge = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const { createWorkflowVersionEdge } = useCreateWorkflowVersionEdge();
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const createEdge = async ({ source, target }: WorkflowDiagramEdge) => {
|
||||
if (isLoading) {
|
||||
@@ -24,11 +19,7 @@ export const useCreateEdge = ({
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Cannot find a workflow version to update');
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
const createdEdge = (
|
||||
await createWorkflowVersionEdge({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import {
|
||||
type WorkflowStepType,
|
||||
@@ -24,7 +24,8 @@ export const useCreateStep = ({
|
||||
workflowLastCreatedStepIdComponentState,
|
||||
);
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
if (!isDefined(workflow)) {
|
||||
return {
|
||||
@@ -50,11 +51,7 @@ export const useCreateStep = ({
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error("Couldn't get updatable workflow version");
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
const workflowVersionStepChanges = (
|
||||
await createWorkflowVersionStep({
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '@/workflow/utils/assertWorkflowWithCurrentVersionIsDefined';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { type WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagramEdge';
|
||||
import { useDeleteWorkflowVersionEdge } from '@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionEdge';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useDeleteEdge = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion | undefined;
|
||||
}) => {
|
||||
export const useDeleteEdge = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const { deleteWorkflowVersionEdge } = useDeleteWorkflowVersionEdge();
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const deleteEdge = async ({ source, target }: WorkflowDiagramEdge) => {
|
||||
assertWorkflowWithCurrentVersionIsDefined(workflow);
|
||||
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
@@ -27,11 +19,7 @@ export const useDeleteEdge = ({
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Cannot find a workflow version to update');
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
const deletedEdge = (
|
||||
await deleteWorkflowVersionEdge({
|
||||
|
||||
@@ -1,30 +1,18 @@
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useDeleteWorkflowVersionStep } from '@/workflow/hooks/useDeleteWorkflowVersionStep';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '@/workflow/utils/assertWorkflowWithCurrentVersionIsDefined';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useDeleteStep = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion | undefined;
|
||||
}) => {
|
||||
export const useDeleteStep = () => {
|
||||
const { deleteWorkflowVersionStep } = useDeleteWorkflowVersionStep();
|
||||
const { deleteStepsOutputSchema } = useStepsOutputSchema();
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const deleteStep = async (stepId: string) => {
|
||||
assertWorkflowWithCurrentVersionIsDefined(workflow);
|
||||
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Could not find workflow version');
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
const workflowVersionStepChanges = await deleteWorkflowVersionStep({
|
||||
workflowVersionId,
|
||||
|
||||
@@ -1,29 +1,14 @@
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import {
|
||||
type WorkflowStep,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { type WorkflowStep } from '@/workflow/types/Workflow';
|
||||
import { useUpdateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionStep';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useUpdateStep = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
export const useUpdateStep = () => {
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
const { updateWorkflowVersionStep } = useUpdateWorkflowVersionStep();
|
||||
|
||||
const updateStep = async <T extends WorkflowStep>(updatedStep: T) => {
|
||||
if (!isDefined(workflow.currentVersion)) {
|
||||
throw new Error('Could not find current workflow version');
|
||||
}
|
||||
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Workflow version not found');
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
await updateWorkflowVersionStep({
|
||||
workflowVersionId,
|
||||
|
||||
+5
-4
@@ -8,7 +8,7 @@ import {
|
||||
Breadcrumb,
|
||||
type BreadcrumbProps,
|
||||
} from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
|
||||
import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
|
||||
@@ -30,11 +30,11 @@ import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTab
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/states/serverlessFunctionTestDataFamilyState';
|
||||
import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody';
|
||||
import { WorkflowEditActionServerlessFunctionFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionServerlessFunctionFields';
|
||||
import { WorkflowServerlessFunctionCodeEditor } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowServerlessFunctionCodeEditor';
|
||||
import { WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowServerlessFunctionTabListComponentId';
|
||||
import { serverlessFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/serverlessFunctionTestDataFamilyState';
|
||||
import { WorkflowServerlessFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowServerlessFunctionTabId';
|
||||
import { getWrongExportedFunctionMarkers } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/getWrongExportedFunctionMarkers';
|
||||
import { useActionHeaderTypeOrThrow } from '@/workflow/workflow-steps/workflow-actions/hooks/useActionHeaderTypeOrThrow';
|
||||
@@ -140,7 +140,8 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
);
|
||||
const { updateOneServerlessFunction } =
|
||||
useUpdateOneServerlessFunction(serverlessFunctionId);
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const workflowVisualizerWorkflowId = useRecoilComponentValue(
|
||||
workflowVisualizerWorkflowIdComponentState,
|
||||
@@ -323,7 +324,7 @@ export const WorkflowEditActionServerlessFunction = ({
|
||||
if (actionOptions.readonly === true || !isDefined(workflow)) {
|
||||
return;
|
||||
}
|
||||
await getUpdatableWorkflowVersion(workflow);
|
||||
await getUpdatableWorkflowVersion();
|
||||
await onCodeChange(value);
|
||||
};
|
||||
|
||||
|
||||
+7
-19
@@ -1,9 +1,6 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { type WorkflowTrigger } from '@/workflow/types/Workflow';
|
||||
import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger';
|
||||
import {
|
||||
type WorkflowTrigger,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
|
||||
const mockUpdateOneRecord = jest.fn();
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
@@ -15,8 +12,8 @@ jest.mock('@/object-record/hooks/useUpdateOneRecord', () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersion', () => ({
|
||||
useGetUpdatableWorkflowVersion: jest.fn(() => ({
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: jest.fn(() => ({
|
||||
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
|
||||
})),
|
||||
}));
|
||||
@@ -28,11 +25,6 @@ jest.mock('@/workflow/hooks/useComputeStepOutputSchema', () => ({
|
||||
}));
|
||||
|
||||
describe('useUpdateWorkflowVersionTrigger', () => {
|
||||
const mockWorkflow = {
|
||||
id: 'workflow-id',
|
||||
currentVersion: { id: 'version-id' },
|
||||
} as WorkflowWithCurrentVersion;
|
||||
|
||||
const trigger: WorkflowTrigger = {
|
||||
name: 'Company created',
|
||||
type: 'DATABASE_EVENT',
|
||||
@@ -53,15 +45,13 @@ describe('useUpdateWorkflowVersionTrigger', () => {
|
||||
data: { computeStepOutputSchema: { field1: 'string' } },
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useUpdateWorkflowVersionTrigger({ workflow: mockWorkflow }),
|
||||
);
|
||||
const { result } = renderHook(() => useUpdateWorkflowVersionTrigger());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.updateTrigger(trigger);
|
||||
});
|
||||
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalledWith(mockWorkflow);
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
|
||||
expect(mockComputeStepOutputSchema).toHaveBeenCalledWith({ step: trigger });
|
||||
expect(mockUpdateOneRecord).toHaveBeenCalledWith({
|
||||
idToUpdate: 'version-id',
|
||||
@@ -77,9 +67,7 @@ describe('useUpdateWorkflowVersionTrigger', () => {
|
||||
it('skips output schema computation when disabled', async () => {
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue('version-id');
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useUpdateWorkflowVersionTrigger({ workflow: mockWorkflow }),
|
||||
);
|
||||
const { result } = renderHook(() => useUpdateWorkflowVersionTrigger());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.updateTrigger(trigger, {
|
||||
|
||||
+5
-18
@@ -1,25 +1,20 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { useComputeStepOutputSchema } from '@/workflow/hooks/useComputeStepOutputSchema';
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import {
|
||||
type WorkflowTrigger,
|
||||
type WorkflowVersion,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useUpdateWorkflowVersionTrigger = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
export const useUpdateWorkflowVersionTrigger = () => {
|
||||
const { updateOneRecord: updateOneWorkflowVersion } =
|
||||
useUpdateOneRecord<WorkflowVersion>({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
});
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const { computeStepOutputSchema } = useComputeStepOutputSchema();
|
||||
|
||||
@@ -27,11 +22,7 @@ export const useUpdateWorkflowVersionTrigger = ({
|
||||
updatedTrigger: WorkflowTrigger,
|
||||
options: { computeOutputSchema: boolean } = { computeOutputSchema: true },
|
||||
) => {
|
||||
if (!isDefined(workflow.currentVersion)) {
|
||||
throw new Error('Cannot find current workflow version');
|
||||
}
|
||||
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
if (options.computeOutputSchema) {
|
||||
const outputSchema = (
|
||||
@@ -46,10 +37,6 @@ export const useUpdateWorkflowVersionTrigger = ({
|
||||
};
|
||||
}
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Workflow version not found');
|
||||
}
|
||||
|
||||
await updateOneWorkflowVersion({
|
||||
idToUpdate: workflowVersionId,
|
||||
updateOneRecordInput: {
|
||||
|
||||
+7
-21
@@ -1,8 +1,5 @@
|
||||
import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion';
|
||||
import {
|
||||
type WorkflowVersion,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -23,11 +20,7 @@ import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/state
|
||||
import { getOrganizedDiagram } from '@/workflow/workflow-diagram/utils/getOrganizedDiagram';
|
||||
import { UPDATE_WORKFLOW_VERSION_POSITIONS } from '@/workflow/workflow-version/graphql/mutations/updateWorkflowVersionPositions';
|
||||
|
||||
export const useTidyUpWorkflowVersion = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow?: WorkflowWithCurrentVersion;
|
||||
}) => {
|
||||
export const useTidyUpWorkflowVersion = () => {
|
||||
const [workflowDiagram, setWorkflowDiagram] = useRecoilComponentState(
|
||||
workflowDiagramComponentState,
|
||||
);
|
||||
@@ -49,20 +42,13 @@ export const useTidyUpWorkflowVersion = ({
|
||||
UpdateWorkflowVersionPositionsMutationVariables
|
||||
>(UPDATE_WORKFLOW_VERSION_POSITIONS, { client: apolloCoreClient });
|
||||
|
||||
const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion();
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const updateWorkflowVersionPosition = async (
|
||||
positions: { id: string; position: { x: number; y: number } }[],
|
||||
) => {
|
||||
if (!isDefined(workflow)) {
|
||||
throw new Error('Cannot find a workflow to update');
|
||||
}
|
||||
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion(workflow);
|
||||
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
throw new Error('Cannot find a workflow version to update');
|
||||
}
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
await mutate({ variables: { input: { workflowVersionId, positions } } });
|
||||
|
||||
@@ -115,7 +101,7 @@ export const useTidyUpWorkflowVersion = ({
|
||||
};
|
||||
|
||||
const tidyUpWorkflowVersion = async () => {
|
||||
if (!isDefined(workflowDiagram) || !isDefined(workflow?.currentVersion)) {
|
||||
if (!isDefined(workflowDiagram)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user