From 7756b472a49e3886c986cb05d7e6b801cb607695 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Mon, 30 Jun 2025 16:44:41 +0200 Subject: [PATCH] Run workflow version on multiple records (#12969) Fixes https://github.com/twentyhq/core-team-issues/issues/776 Until we have loops implemented, we still allow the user to select multiple records for manual trigger. A workflow run will be triggered for each record selected. The display of multiple runs in the side panel is not ideal. After discussion with @Bonapara, we will load all runs into the side panel until we have the inbox. Once we have the inbox, we will use the side panel when only one run is triggered. https://github.com/user-attachments/assets/b563b4f1-0705-45aa-b296-c1b41abf4815 --- .../hooks/useRunWorkflowRecordActions.tsx | 49 +++++++++++++------ ...ionMenuContextProviderWorkflowsEnabled.tsx | 6 +-- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx index 2123aef4b..71596f60d 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx @@ -9,10 +9,11 @@ import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/use import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion'; import { msg } from '@lingui/core/macro'; -import { useRecoilValue } from 'recoil'; +import { WorkflowVersion } from '@/workflow/types/Workflow'; +import { COMMAND_MENU_DEFAULT_ICON } from '@/workflow/workflow-trigger/constants/CommandMenuDefaultIcon'; +import { useRecoilCallback } from 'recoil'; import { capitalize, isDefined } from 'twenty-shared/utils'; import { useIcons } from 'twenty-ui/display'; -import { COMMAND_MENU_DEFAULT_ICON } from '@/workflow/workflow-trigger/constants/CommandMenuDefaultIcon'; export const useRunWorkflowRecordActions = ({ objectMetadataItem, @@ -26,15 +27,11 @@ export const useRunWorkflowRecordActions = ({ contextStoreTargetedRecordsRuleComponentState, ); - const selectedRecordId = + const selectedRecordIds = contextStoreTargetedRecordsRule.mode === 'selection' - ? contextStoreTargetedRecordsRule.selectedRecordIds[0] + ? contextStoreTargetedRecordsRule.selectedRecordIds : undefined; - const selectedRecord = useRecoilValue( - recordStoreFamilyState(selectedRecordId ?? ''), - ); - const { records: activeWorkflowVersions } = useActiveWorkflowVersionsWithManualTrigger({ objectMetadataItem, @@ -43,6 +40,31 @@ export const useRunWorkflowRecordActions = ({ const { runWorkflowVersion } = useRunWorkflowVersion(); + const runWorkflowVersionOnSelectedRecords = useRecoilCallback( + ({ snapshot }) => + async ( + selectedRecordIds: string[], + activeWorkflowVersion: WorkflowVersion, + ) => { + for (const selectedRecordId of selectedRecordIds) { + const selectedRecord = snapshot + .getLoadable(recordStoreFamilyState(selectedRecordId)) + .getValue(); + + if (!isDefined(selectedRecord)) { + continue; + } + + await runWorkflowVersion({ + workflowId: activeWorkflowVersion.workflowId, + workflowVersionId: activeWorkflowVersion.id, + payload: selectedRecord, + }); + } + }, + [runWorkflowVersion], + ); + return activeWorkflowVersions .filter((activeWorkflowVersion) => isDefined(activeWorkflowVersion.workflow), @@ -66,15 +88,14 @@ export const useRunWorkflowRecordActions = ({ component: ( { - if (!isDefined(selectedRecord)) { + if (!isDefined(selectedRecordIds)) { return; } - await runWorkflowVersion({ - workflowId: activeWorkflowVersion.workflowId, - workflowVersionId: activeWorkflowVersion.id, - payload: selectedRecord, - }); + await runWorkflowVersionOnSelectedRecords( + selectedRecordIds, + activeWorkflowVersion, + ); }} closeSidePanelOnCommandMenuListActionExecution={false} /> diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabled.tsx b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabled.tsx index ae2e6f730..7ac6e8d17 100644 --- a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabled.tsx +++ b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabled.tsx @@ -43,13 +43,13 @@ export const ActionMenuContextProviderWorkflowsEnabled = ({ contextStoreTargetedRecordsRuleComponentState, ); - const isSingleRecordSelection = + const isRecordSelection = contextStoreTargetedRecordsRule.mode === 'selection' && - contextStoreTargetedRecordsRule.selectedRecordIds.length === 1; + contextStoreTargetedRecordsRule.selectedRecordIds.length > 0; const runWorkflowRecordActions = useRunWorkflowRecordActions({ objectMetadataItem, - skip: !isSingleRecordSelection, + skip: !isRecordSelection, }); const runWorkflowRecordAgnosticActions =