Add duplicate step action (#14392)
https://github.com/user-attachments/assets/ac89440c-6f84-4d2a-b88a-da7ddfb181eb
This commit is contained in:
+3
-21
@@ -1,4 +1,3 @@
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
@@ -44,17 +43,6 @@ const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
};
|
||||
|
||||
describe('useCreateStep', () => {
|
||||
const mockWorkflow = {
|
||||
id: '123',
|
||||
currentVersion: {
|
||||
id: '456',
|
||||
status: 'DRAFT',
|
||||
steps: [],
|
||||
trigger: { type: 'manual' },
|
||||
},
|
||||
versions: [],
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
@@ -63,15 +51,9 @@ describe('useCreateStep', () => {
|
||||
const mockWorkflowVersionId = 'version-123';
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
|
||||
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useCreateStep({
|
||||
workflow: mockWorkflow as unknown as WorkflowWithCurrentVersion,
|
||||
}),
|
||||
{
|
||||
wrapper,
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(() => useCreateStep(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.createStep({
|
||||
|
||||
+7
-4
@@ -6,11 +6,14 @@ const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
const mockDeleteStepsOutputSchema = jest.fn();
|
||||
const mockCloseCommandMenu = jest.fn();
|
||||
|
||||
jest.mock('@/workflow/hooks/useDeleteWorkflowVersionStep', () => ({
|
||||
useDeleteWorkflowVersionStep: () => ({
|
||||
deleteWorkflowVersionStep: mockDeleteWorkflowVersionStep,
|
||||
jest.mock(
|
||||
'@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionStep',
|
||||
() => ({
|
||||
useDeleteWorkflowVersionStep: () => ({
|
||||
deleteWorkflowVersionStep: mockDeleteWorkflowVersionStep,
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: () => ({
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import { useDuplicateStep } from '@/workflow/workflow-steps/hooks/useDuplicateStep';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { WorkflowVisualizerComponentInstanceContext } from '../../../workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext';
|
||||
|
||||
const mockGetUpdatableWorkflowVersion = jest.fn();
|
||||
const mockDuplicateWorkflowVersionStep = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
duplicateWorkflowVersionStep: { createdStep: { id: '2', type: 'CODE' } },
|
||||
},
|
||||
});
|
||||
|
||||
jest.mock(
|
||||
'@/workflow/workflow-steps/hooks/useDuplicateWorkflowVersionStep',
|
||||
() => ({
|
||||
useDuplicateWorkflowVersionStep: () => ({
|
||||
duplicateWorkflowVersionStep: mockDuplicateWorkflowVersionStep,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow', () => ({
|
||||
useGetUpdatableWorkflowVersionOrThrow: () => ({
|
||||
getUpdatableWorkflowVersion: mockGetUpdatableWorkflowVersion,
|
||||
}),
|
||||
}));
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
const workflowVisualizerComponentInstanceId =
|
||||
'workflow-visualizer-instance-id';
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<WorkflowVisualizerComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: workflowVisualizerComponentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WorkflowVisualizerComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useDuplicateStep', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should create step in workflow version', async () => {
|
||||
const mockWorkflowVersionId = 'version-123';
|
||||
mockGetUpdatableWorkflowVersion.mockResolvedValue(mockWorkflowVersionId);
|
||||
|
||||
const { result } = renderHook(() => useDuplicateStep(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.duplicateStep({
|
||||
stepId: 'step-1',
|
||||
});
|
||||
});
|
||||
|
||||
expect(mockGetUpdatableWorkflowVersion).toHaveBeenCalled();
|
||||
expect(mockDuplicateWorkflowVersionStep).toHaveBeenCalledWith({
|
||||
stepId: 'step-1',
|
||||
workflowVersionId: mockWorkflowVersionId,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,20 +1,13 @@
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import {
|
||||
type WorkflowStepType,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { type WorkflowStepType } from '@/workflow/types/Workflow';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { useCreateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useCreateWorkflowVersionStep';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCreateStep = ({
|
||||
workflow,
|
||||
}: {
|
||||
workflow: WorkflowWithCurrentVersion | undefined;
|
||||
}) => {
|
||||
export const useCreateStep = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { createWorkflowVersionStep } = useCreateWorkflowVersionStep();
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentState(
|
||||
@@ -27,12 +20,6 @@ export const useCreateStep = ({
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
if (!isDefined(workflow)) {
|
||||
return {
|
||||
createStep: async () => undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const createStep = async ({
|
||||
newStepType,
|
||||
parentStepId,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useDeleteWorkflowVersionStep } from '@/workflow/hooks/useDeleteWorkflowVersionStep';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
|
||||
import { useDeleteWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useDeleteWorkflowVersionStep';
|
||||
|
||||
export const useDeleteStep = () => {
|
||||
const { deleteWorkflowVersionStep } = useDeleteWorkflowVersionStep();
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { DELETE_WORKFLOW_VERSION_STEP } from '@/workflow/graphql/mutations/deleteWorkflowVersionStep';
|
||||
import { useUpdateWorkflowVersionCache } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionCache';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import {
|
||||
type DeleteWorkflowVersionStepInput,
|
||||
type DeleteWorkflowVersionStepMutation,
|
||||
type DeleteWorkflowVersionStepMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useDeleteWorkflowVersionStep = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
const { updateWorkflowVersionCache } = useUpdateWorkflowVersionCache();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
DeleteWorkflowVersionStepMutation,
|
||||
DeleteWorkflowVersionStepMutationVariables
|
||||
>(DELETE_WORKFLOW_VERSION_STEP, {
|
||||
client: apolloCoreClient,
|
||||
});
|
||||
|
||||
const deleteWorkflowVersionStep = async (
|
||||
input: DeleteWorkflowVersionStepInput,
|
||||
) => {
|
||||
const result = await mutate({ variables: { input } });
|
||||
|
||||
const workflowVersionStepChanges = result?.data?.deleteWorkflowVersionStep;
|
||||
|
||||
updateWorkflowVersionCache({
|
||||
workflowVersionStepChanges,
|
||||
workflowVersionId: input.workflowVersionId,
|
||||
});
|
||||
|
||||
return workflowVersionStepChanges;
|
||||
};
|
||||
|
||||
return { deleteWorkflowVersionStep };
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { workflowLastCreatedStepIdComponentState } from '@/workflow/states/workflowLastCreatedStepIdComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import { useDuplicateWorkflowVersionStep } from '@/workflow/workflow-steps/hooks/useDuplicateWorkflowVersionStep';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useDuplicateStep = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { duplicateWorkflowVersionStep } = useDuplicateWorkflowVersionStep();
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentState(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
const setWorkflowLastCreatedStepId = useSetRecoilComponentState(
|
||||
workflowLastCreatedStepIdComponentState,
|
||||
);
|
||||
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow();
|
||||
|
||||
const duplicateStep = async ({ stepId }: { stepId: string }) => {
|
||||
if (isLoading === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
const workflowVersionStepChanges = (
|
||||
await duplicateWorkflowVersionStep({
|
||||
workflowVersionId,
|
||||
stepId,
|
||||
})
|
||||
)?.data?.duplicateWorkflowVersionStep;
|
||||
|
||||
const createdStep = workflowVersionStepChanges?.createdStep;
|
||||
|
||||
if (!isDefined(createdStep)) {
|
||||
throw new Error("Couldn't duplicate step");
|
||||
}
|
||||
|
||||
setWorkflowSelectedNode(createdStep.id);
|
||||
setWorkflowLastCreatedStepId(createdStep.id);
|
||||
|
||||
return createdStep;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
duplicateStep,
|
||||
};
|
||||
};
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { DUPLICATE_WORKFLOW_VERSION_STEP } from '@/workflow/graphql/mutations/duplicateWorkflowVersionStep';
|
||||
import { flowComponentState } from '@/workflow/states/flowComponentState';
|
||||
import { useUpdateWorkflowVersionCache } from '@/workflow/workflow-steps/hooks/useUpdateWorkflowVersionCache';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type DuplicateWorkflowVersionStepInput,
|
||||
type DuplicateWorkflowVersionStepMutation,
|
||||
type DuplicateWorkflowVersionStepMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useDuplicateWorkflowVersionStep = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
const { updateWorkflowVersionCache } = useUpdateWorkflowVersionCache();
|
||||
|
||||
const setFlow = useSetRecoilComponentState(flowComponentState);
|
||||
|
||||
const [mutate] = useMutation<
|
||||
DuplicateWorkflowVersionStepMutation,
|
||||
DuplicateWorkflowVersionStepMutationVariables
|
||||
>(DUPLICATE_WORKFLOW_VERSION_STEP, {
|
||||
client: apolloCoreClient,
|
||||
});
|
||||
|
||||
const duplicateWorkflowVersionStep = async (
|
||||
input: DuplicateWorkflowVersionStepInput,
|
||||
) => {
|
||||
const result = await mutate({
|
||||
variables: { input },
|
||||
});
|
||||
|
||||
const workflowVersionStepChanges =
|
||||
result?.data?.duplicateWorkflowVersionStep;
|
||||
|
||||
const updatedWorkflowVersion = updateWorkflowVersionCache({
|
||||
workflowVersionStepChanges,
|
||||
workflowVersionId: input.workflowVersionId,
|
||||
});
|
||||
|
||||
if (isDefined(updatedWorkflowVersion)) {
|
||||
setFlow({
|
||||
workflowVersionId: updatedWorkflowVersion.id,
|
||||
trigger: updatedWorkflowVersion.trigger,
|
||||
steps: updatedWorkflowVersion.steps,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return { duplicateWorkflowVersionStep };
|
||||
};
|
||||
Reference in New Issue
Block a user