Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the workflow draft version overriding to the backend #9328

Merged
merged 13 commits into from
Jan 6, 2025
Merged
52 changes: 51 additions & 1 deletion packages/twenty-front/src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ export type Billing = {

/** The different billing plans available */
export enum BillingPlanKey {
Base = 'BASE',
Enterprise = 'ENTERPRISE',
Pro = 'PRO'
}
Expand Down Expand Up @@ -189,6 +188,13 @@ export type ComputeStepOutputSchemaInput = {
step: Scalars['JSON'];
};

export type CreateDraftFromWorkflowVersionInput = {
/** Workflow ID */
workflowId: Scalars['String'];
/** Workflow version ID */
workflowVersionIdToCopy: Scalars['String'];
};

export type CreateFieldInput = {
defaultValue?: InputMaybe<Scalars['JSON']>;
description?: InputMaybe<Scalars['String']>;
Expand Down Expand Up @@ -504,6 +510,7 @@ export type Mutation = {
challenge: LoginToken;
checkoutSession: SessionEntity;
computeStepOutputSchema: Scalars['JSON'];
createDraftFromWorkflowVersion: Scalars['Boolean'];
createOIDCIdentityProvider: SetupSsoOutput;
createOneAppToken: AppToken;
createOneField: Field;
Expand Down Expand Up @@ -602,6 +609,11 @@ export type MutationComputeStepOutputSchemaArgs = {
};


export type MutationCreateDraftFromWorkflowVersionArgs = {
input: CreateDraftFromWorkflowVersionInput;
};


export type MutationCreateOidcIdentityProviderArgs = {
input: SetupOidcSsoInput;
};
Expand Down Expand Up @@ -2180,6 +2192,13 @@ export type DeleteWorkflowVersionStepMutationVariables = Exact<{

export type DeleteWorkflowVersionStepMutation = { __typename?: 'Mutation', deleteWorkflowVersionStep: { __typename?: 'WorkflowAction', id: any, name: string, type: string, settings: any, valid: boolean } };

export type CreateDraftFromWorkflowVersionMutationVariables = Exact<{
input: CreateDraftFromWorkflowVersionInput;
}>;


export type CreateDraftFromWorkflowVersionMutation = { __typename?: 'Mutation', createDraftFromWorkflowVersion: boolean };

export type RunWorkflowVersionMutationVariables = Exact<{
input: RunWorkflowVersionInput;
}>;
Expand Down Expand Up @@ -4096,6 +4115,37 @@ export function useDeleteWorkflowVersionStepMutation(baseOptions?: Apollo.Mutati
export type DeleteWorkflowVersionStepMutationHookResult = ReturnType<typeof useDeleteWorkflowVersionStepMutation>;
export type DeleteWorkflowVersionStepMutationResult = Apollo.MutationResult<DeleteWorkflowVersionStepMutation>;
export type DeleteWorkflowVersionStepMutationOptions = Apollo.BaseMutationOptions<DeleteWorkflowVersionStepMutation, DeleteWorkflowVersionStepMutationVariables>;
export const CreateDraftFromWorkflowVersionDocument = gql`
mutation CreateDraftFromWorkflowVersion($input: CreateDraftFromWorkflowVersionInput!) {
createDraftFromWorkflowVersion(input: $input)
}
`;
export type CreateDraftFromWorkflowVersionMutationFn = Apollo.MutationFunction<CreateDraftFromWorkflowVersionMutation, CreateDraftFromWorkflowVersionMutationVariables>;

/**
* __useCreateDraftFromWorkflowVersionMutation__
*
* To run a mutation, you first call `useCreateDraftFromWorkflowVersionMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCreateDraftFromWorkflowVersionMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [createDraftFromWorkflowVersionMutation, { data, loading, error }] = useCreateDraftFromWorkflowVersionMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useCreateDraftFromWorkflowVersionMutation(baseOptions?: Apollo.MutationHookOptions<CreateDraftFromWorkflowVersionMutation, CreateDraftFromWorkflowVersionMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<CreateDraftFromWorkflowVersionMutation, CreateDraftFromWorkflowVersionMutationVariables>(CreateDraftFromWorkflowVersionDocument, options);
}
export type CreateDraftFromWorkflowVersionMutationHookResult = ReturnType<typeof useCreateDraftFromWorkflowVersionMutation>;
export type CreateDraftFromWorkflowVersionMutationResult = Apollo.MutationResult<CreateDraftFromWorkflowVersionMutation>;
export type CreateDraftFromWorkflowVersionMutationOptions = Apollo.BaseMutationOptions<CreateDraftFromWorkflowVersionMutation, CreateDraftFromWorkflowVersionMutationVariables>;
export const RunWorkflowVersionDocument = gql`
mutation RunWorkflowVersion($input: RunWorkflowVersionInput!) {
runWorkflowVersion(input: $input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
import { OverrideWorkflowDraftConfirmationModal } from '@/workflow/components/OverrideWorkflowDraftConfirmationModal';
import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion';
import { useCreateDraftFromWorkflowVersion } from '@/workflow/hooks/useCreateDraftFromWorkflowVersion';
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState';
Expand All @@ -21,7 +21,8 @@ export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutOb
workflowVersion?.workflow?.id ?? '',
);

const { createNewWorkflowVersion } = useCreateNewWorkflowVersion();
const { createDraftFromWorkflowVersion } =
useCreateDraftFromWorkflowVersion();

const setOpenOverrideWorkflowDraftConfirmationModal = useSetRecoilState(
openOverrideWorkflowDraftConfirmationModalState,
Expand All @@ -45,13 +46,11 @@ export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutOb
if (hasAlreadyDraftVersion) {
setOpenOverrideWorkflowDraftConfirmationModal(true);
} else {
await createNewWorkflowVersion({
await createDraftFromWorkflowVersion({
workflowId: workflowVersion.workflow.id,
name: `v${workflow.versions.length + 1}`,
status: 'DRAFT',
trigger: workflowVersion.trigger,
steps: workflowVersion.steps,
workflowVersionIdToCopy: workflowVersion.id,
});

navigate(
buildShowPageURL(
CoreObjectNameSingular.Workflow,
Expand All @@ -63,12 +62,8 @@ export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutOb

const ConfirmationModal = shouldBeRegistered ? (
<OverrideWorkflowDraftConfirmationModal
draftWorkflowVersionId={workflow?.currentVersion?.id ?? ''}
workflowId={workflow?.id ?? ''}
workflowVersionUpdateInput={{
steps: workflowVersion.steps,
trigger: workflowVersion.trigger,
}}
workflowId={workflowVersion.workflow.id}
workflowVersionIdToCopy={workflowVersion.id}
/>
) : undefined;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,35 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
import {
ConfirmationModal,
StyledCenteredButton,
} from '@/ui/layout/modal/components/ConfirmationModal';
import { useCreateDraftFromWorkflowVersion } from '@/workflow/hooks/useCreateDraftFromWorkflowVersion';
import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState';
import { WorkflowVersion } from '@/workflow/types/Workflow';
import { useNavigate } from 'react-router-dom';
import { useRecoilState } from 'recoil';

export const OverrideWorkflowDraftConfirmationModal = ({
draftWorkflowVersionId,
workflowVersionUpdateInput,
workflowId,
workflowVersionIdToCopy,
}: {
draftWorkflowVersionId: string;
workflowVersionUpdateInput: Pick<WorkflowVersion, 'trigger' | 'steps'>;
workflowId: string;
workflowVersionIdToCopy: string;
}) => {
const [
openOverrideWorkflowDraftConfirmationModal,
setOpenOverrideWorkflowDraftConfirmationModal,
] = useRecoilState(openOverrideWorkflowDraftConfirmationModalState);

const { updateOneRecord: updateOneWorkflowVersion } =
useUpdateOneRecord<WorkflowVersion>({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
});
const { createDraftFromWorkflowVersion } =
useCreateDraftFromWorkflowVersion();

const navigate = useNavigate();

const handleOverrideDraft = async () => {
await updateOneWorkflowVersion({
idToUpdate: draftWorkflowVersionId,
updateOneRecordInput: workflowVersionUpdateInput,
await createDraftFromWorkflowVersion({
workflowId,
workflowVersionIdToCopy,
});

navigate(buildShowPageURL(CoreObjectNameSingular.Workflow, workflowId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
import { OverrideWorkflowDraftConfirmationModal } from '@/workflow/components/OverrideWorkflowDraftConfirmationModal';
import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion';
import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion';
import { useCreateDraftFromWorkflowVersion } from '@/workflow/hooks/useCreateDraftFromWorkflowVersion';
import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion';
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState';
Expand Down Expand Up @@ -74,7 +74,8 @@ export const RecordShowPageWorkflowVersionHeader = ({

const { activateWorkflowVersion } = useActivateWorkflowVersion();
const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion();
const { createNewWorkflowVersion } = useCreateNewWorkflowVersion();
const { createDraftFromWorkflowVersion } =
useCreateDraftFromWorkflowVersion();

const setOpenOverrideWorkflowDraftConfirmationModal = useSetRecoilState(
openOverrideWorkflowDraftConfirmationModalState,
Expand All @@ -94,13 +95,11 @@ export const RecordShowPageWorkflowVersionHeader = ({
if (hasAlreadyDraftVersion) {
setOpenOverrideWorkflowDraftConfirmationModal(true);
} else {
await createNewWorkflowVersion({
await createDraftFromWorkflowVersion({
workflowId: workflowVersion.workflow.id,
name: `v${workflowVersion.workflow.versions.length + 1}`,
status: 'DRAFT',
trigger: workflowVersion.trigger,
steps: workflowVersion.steps,
workflowVersionIdToCopy: workflowVersion.id,
});

navigate(
buildShowPageURL(
CoreObjectNameSingular.Workflow,
Expand Down Expand Up @@ -140,12 +139,8 @@ export const RecordShowPageWorkflowVersionHeader = ({

{isDefined(workflowVersion) && isDefined(draftWorkflowVersion) ? (
<OverrideWorkflowDraftConfirmationModal
draftWorkflowVersionId={draftWorkflowVersion.id}
workflowId={workflowVersion.workflowId}
workflowVersionUpdateInput={{
steps: workflowVersion.steps,
trigger: workflowVersion.trigger,
}}
workflowVersionIdToCopy={workflowVersionId}
/>
) : null}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { gql } from '@apollo/client';

export const OVERRIDE_WORKFLOW_DRAFT_VERSION = gql`
mutation CreateDraftFromWorkflowVersion(
$input: CreateDraftFromWorkflowVersionInput!
) {
createDraftFromWorkflowVersion(input: $input)
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useApolloClient } from '@apollo/client';
import {
CreateDraftFromWorkflowVersionInput,
useCreateDraftFromWorkflowVersionMutation,
} from '~/generated/graphql';

export const useCreateDraftFromWorkflowVersion = () => {
const apolloClient = useApolloClient();

const [mutate] = useCreateDraftFromWorkflowVersionMutation({
client: apolloClient,
});

const createDraftFromWorkflowVersion = async (
input: CreateDraftFromWorkflowVersionInput,
) => {
await mutate({ variables: { input } });
};

return {
createDraftFromWorkflowVersion,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const getServerlessFolder = ({
version,
}: {
serverlessFunction: ServerlessFunctionEntity;
version?: string;
version?: 'draft' | 'latest' | (string & NonNullable<unknown>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: The type string & NonNullable<unknown> is redundant since string is already non-nullable. Consider using just string or creating a specific type/enum for versions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this change helps a lot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use constants instead of hard-coded strings?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't because version can be '1', '2', etc...

}) => {
const computedVersion =
version === 'latest' ? serverlessFunction.latestVersion : version;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Field, InputType } from '@nestjs/graphql';

@InputType()
export class CreateDraftFromWorkflowVersionInput {
@Field(() => String, {
description: 'Workflow ID',
nullable: false,
})
workflowId: string;

@Field(() => String, {
description: 'Workflow version ID',
nullable: false,
})
workflowVersionIdToCopy: string;
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Mutation, Resolver } from '@nestjs/graphql';

import { CreateDraftFromWorkflowVersionInput } from 'src/engine/core-modules/workflow/dtos/create-draft-from-workflow-version-input';
import { CreateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto';
import { DeleteWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/delete-workflow-version-step-input.dto';
import { UpdateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-version-step-input.dto';
import { WorkflowActionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-step.dto';
import { WorkflowTriggerGraphqlApiExceptionFilter } from 'src/engine/core-modules/workflow/filters/workflow-trigger-graphql-api-exception.filter';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto';
import { UpdateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-version-step-input.dto';
import { DeleteWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/delete-workflow-version-step-input.dto';
import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-version-step.workspace-service';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkflowActionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-step.dto';

@Resolver()
@UseGuards(WorkspaceAuthGuard, UserAuthGuard)
Expand Down Expand Up @@ -58,4 +59,24 @@ export class WorkflowVersionStepResolver {
stepId,
});
}

@Mutation(() => Boolean)
async createDraftFromWorkflowVersion(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
{
workflowId,
workflowVersionIdToCopy,
}: CreateDraftFromWorkflowVersionInput,
) {
await this.workflowVersionStepWorkspaceService.createDraftFromWorkflowVersion(
{
workspaceId,
workflowId,
workflowVersionIdToCopy,
},
);

return true;
}
}
Loading
Loading