Implement contextual actions for the workflows (#8814)

Implemented the following actions for the workflows:
- Test Workflow
- Discard Draft
- Activate Draft
- Activate Workflow Last Published Version
- Deactivate Workflow
- See Workflow Executions
- See Workflow Active Version
- See Workflow Versions History

And the following actions for the workflow versions:
- Use As Draft
- See Workflow Versions History
- See Workflow Executions

Video example:


https://github.com/user-attachments/assets/016956a6-6f2e-4de5-9605-d6e14526cbb3

A few of these actions are links to the relations of the workflow object
(link to a filtered table). To generalize this behavior, I will create
an hook named `useSeeRelationsActionSingleRecordAction` to automatically
generate links to a showPage if the relation is a Many To One or to a
filtered table if the relation is a One to Many for all the record
types.
I will also create actions which will allow to create a relation.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Raphaël Bosi
2024-12-03 12:09:51 +01:00
committed by GitHub
parent 7b2d9894f3
commit 32194a88b3
45 changed files with 2334 additions and 254 deletions

View File

@ -7,14 +7,17 @@ import {
} from '@/ui/layout/modal/components/ConfirmationModal';
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,
}: {
draftWorkflowVersionId: string;
workflowVersionUpdateInput: Pick<WorkflowVersion, 'trigger' | 'steps'>;
workflowId: string;
}) => {
const [
openOverrideWorkflowDraftConfirmationModal,
@ -26,11 +29,15 @@ export const OverrideWorkflowDraftConfirmationModal = ({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
});
const navigate = useNavigate();
const handleOverrideDraft = async () => {
await updateOneWorkflowVersion({
idToUpdate: draftWorkflowVersionId,
updateOneRecordInput: workflowVersionUpdateInput,
});
navigate(buildShowPageURL(CoreObjectNameSingular.Workflow, workflowId));
};
return (

View File

@ -71,6 +71,7 @@ export const RecordShowPageWorkflowHeader = ({
await runWorkflowVersion({
workflowVersionId: workflowWithCurrentVersion.currentVersion.id,
workflowName: workflowWithCurrentVersion.name,
});
enqueueSnackBar('', {

View File

@ -131,6 +131,7 @@ export const RecordShowPageWorkflowVersionHeader = ({
{isDefined(workflowVersion) && isDefined(draftWorkflowVersion) ? (
<OverrideWorkflowDraftConfirmationModal
draftWorkflowVersionId={draftWorkflowVersion.id}
workflowId={workflowVersion.workflowId}
workflowVersionUpdateInput={{
steps: workflowVersion.steps,
trigger: workflowVersion.trigger,

View File

@ -0,0 +1,43 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { Workflow, WorkflowVersion } from '@/workflow/types/Workflow';
export const useActiveWorkflowVersion = (workflowId: string) => {
const { records: workflowVersions } = useFindManyRecords<
WorkflowVersion & {
workflow: Omit<Workflow, 'versions'> & {
versions: Array<{ __typename: string }>;
};
}
>({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
filter: {
workflowId: {
eq: workflowId,
},
status: {
eq: 'ACTIVE',
},
},
recordGqlFields: {
id: true,
name: true,
createdAt: true,
updatedAt: true,
workflowId: true,
trigger: true,
steps: true,
status: true,
workflow: {
id: true,
name: true,
statuses: true,
versions: {
totalCount: true,
},
},
},
});
return workflowVersions?.[0];
};

View File

@ -1,10 +1,15 @@
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { RUN_WORKFLOW_VERSION } from '@/workflow/graphql/mutations/runWorkflowVersion';
import { useMutation } from '@apollo/client';
import { useTheme } from '@emotion/react';
import { IconSettingsAutomation } from 'twenty-ui';
import {
RunWorkflowVersionMutation,
RunWorkflowVersionMutationVariables,
} from '~/generated/graphql';
import { capitalize } from '~/utils/string/capitalize';
export const useRunWorkflowVersion = () => {
const apolloMetadataClient = useApolloMetadataClient();
@ -15,16 +20,33 @@ export const useRunWorkflowVersion = () => {
client: apolloMetadataClient,
});
const { enqueueSnackBar } = useSnackBar();
const theme = useTheme();
const runWorkflowVersion = async ({
workflowVersionId,
workflowName,
payload,
}: {
workflowVersionId: string;
workflowName: string;
payload?: Record<string, any>;
}) => {
await mutate({
variables: { input: { workflowVersionId, payload } },
});
enqueueSnackBar('', {
variant: SnackBarVariant.Success,
title: `${capitalize(workflowName)} starting...`,
icon: (
<IconSettingsAutomation
size={16}
color={theme.snackBar.success.color}
/>
),
});
};
return { runWorkflowVersion };

View File

@ -17,6 +17,7 @@ export const useWorkflowWithCurrentVersion = (
id: true,
name: true,
statuses: true,
lastPublishedVersionId: true,
versions: true,
},
skip: !isDefined(workflowId),