From f7adf1698e0ee3d6aab71615568058a5be4f93f0 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Fri, 30 Jan 2026 10:24:07 +0100 Subject: [PATCH] Improve API + set functions in state (#17560) Prefetch functions and set these in state --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .../src/generated-metadata/graphql.ts | 6 ++-- .../twenty-front/src/generated/graphql.ts | 6 ++-- .../app/components/AppRouterProviders.tsx | 4 +-- .../CommandMenuWorkflowSelectAction.tsx | 23 +++++++++----- .../CommandMenuWorkflowCreateStepContent.tsx | 3 +- ...CommandMenuWorkflowEditStepTypeContent.tsx | 23 ++++---------- .../hooks/useGetManyLogicFunctions.ts | 24 --------------- .../states/logicFunctionsState.ts | 10 +++++++ ...rEffect.tsx => MetadataProviderEffect.tsx} | 15 +++++++++- .../workflow-steps/hooks/useCreateStep.ts | 9 ++---- .../ai/components/SettingsToolsTable.tsx | 7 +++-- .../src/testing/decorators/PageDecorator.tsx | 4 +-- .../create-workflow-version-step-input.dto.ts | 13 +++----- ...-step-operations.workspace-service.spec.ts | 17 +++++++++-- ...version-step-creation.workspace-service.ts | 6 ++-- ...rsion-step-operations.workspace-service.ts | 30 +++++++++++++++---- ...w-version-step-update.workspace-service.ts | 3 +- .../workflow-version-step.module.ts | 4 ++- .../types/workflow-action-settings.type.ts | 2 ++ 19 files changed, 111 insertions(+), 98 deletions(-) delete mode 100644 packages/twenty-front/src/modules/settings/logic-functions/hooks/useGetManyLogicFunctions.ts create mode 100644 packages/twenty-front/src/modules/settings/logic-functions/states/logicFunctionsState.ts rename packages/twenty-front/src/modules/users/components/{UserAndViewsProviderEffect.tsx => MetadataProviderEffect.tsx} (93%) diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index f0ac9a2e42..227847d199 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1145,12 +1145,10 @@ export type CreateWorkflowVersionEdgeInput = { }; export type CreateWorkflowVersionStepInput = { + /** Default settings for the step */ + defaultSettings?: InputMaybe; /** Step ID */ id?: InputMaybe; - /** Logic function ID */ - logicFunctionId?: InputMaybe; - /** Step name */ - name?: InputMaybe; /** Next step ID */ nextStepId?: InputMaybe; /** Parent step connection options */ diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index 5e742a0c14..437ad78264 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -1112,12 +1112,10 @@ export type CreateWorkflowVersionEdgeInput = { }; export type CreateWorkflowVersionStepInput = { + /** Default settings for the step */ + defaultSettings?: InputMaybe; /** Step ID */ id?: InputMaybe; - /** Logic function ID */ - logicFunctionId?: InputMaybe; - /** Step name */ - name?: InputMaybe; /** Next step ID */ nextStepId?: InputMaybe; /** Parent step connection options */ diff --git a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx index 81a9749cb4..0203f5b8ca 100644 --- a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx +++ b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx @@ -23,7 +23,7 @@ import { BaseThemeProvider } from '@/ui/theme/components/BaseThemeProvider'; import { UserThemeProviderEffect } from '@/ui/theme/components/UserThemeProviderEffect'; import { PageFavicon } from '@/ui/utilities/page-favicon/components/PageFavicon'; import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle'; -import { UserAndViewsProviderEffect } from '@/users/components/UserAndViewsProviderEffect'; +import { MetadataProviderEffect } from '@/users/components/MetadataProviderEffect'; import { UserProvider } from '@/users/components/UserProvider'; import { WorkspaceProviderEffect } from '@/workspace/components/WorkspaceProviderEffect'; import { StrictMode } from 'react'; @@ -38,7 +38,7 @@ export const AppRouterProviders = () => { - + diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx index 1d8bc27f3c..8d3a6fa747 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx @@ -1,5 +1,5 @@ import { WorkflowActionMenuItems } from '@/command-menu/pages/workflow/action/components/WorkflowActionMenuItems'; -import { useGetManyLogicFunctions } from '@/settings/logic-functions/hooks/useGetManyLogicFunctions'; +import { logicFunctionsState } from '@/settings/logic-functions/states/logicFunctionsState'; import { type WorkflowActionType } from '@/workflow/types/Workflow'; import { RightDrawerStepListContainer } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepContainer'; import { RightDrawerWorkflowSelectStepTitle } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepTitle'; @@ -12,13 +12,15 @@ import { getActionIconColorOrThrow } from '@/workflow/workflow-steps/workflow-ac import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useTheme } from '@emotion/react'; import { useLingui } from '@lingui/react/macro'; +import { useRecoilValue } from 'recoil'; import { IconFunction } from 'twenty-ui/display'; import { MenuItem } from 'twenty-ui/navigation'; import { FeatureFlagKey } from '~/generated/graphql'; -export type WorkflowActionSelection = - | { type: WorkflowActionType; logicFunctionId?: undefined; name?: undefined } - | { type: 'LOGIC_FUNCTION'; logicFunctionId: string; name: string }; +export type WorkflowActionSelection = { + type: WorkflowActionType; + defaultSettings?: Record; +}; export const CommandMenuWorkflowSelectAction = ({ onActionSelected, @@ -30,7 +32,7 @@ export const CommandMenuWorkflowSelectAction = ({ const { t } = useLingui(); - const { logicFunctions } = useGetManyLogicFunctions(); + const logicFunctions = useRecoilValue(logicFunctionsState); const toolFunctions = logicFunctions.filter((fn) => fn.isTool === true); @@ -38,8 +40,13 @@ export const CommandMenuWorkflowSelectAction = ({ onActionSelected({ type: actionType }); }; - const handleFunctionClick = (logicFunctionId: string, name: string) => { - onActionSelected({ type: 'LOGIC_FUNCTION', logicFunctionId, name }); + const handleFunctionClick = (logicFunctionId: string) => { + onActionSelected({ + type: 'LOGIC_FUNCTION', + defaultSettings: { + input: { logicFunctionId, logicFunctionInput: {} }, + }, + }); }; return ( @@ -107,7 +114,7 @@ export const CommandMenuWorkflowSelectAction = ({ /> )} text={fn.name} - onClick={() => handleFunctionClick(fn.id, fn.name)} + onClick={() => handleFunctionClick(fn.id)} /> ))} diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/create/components/CommandMenuWorkflowCreateStepContent.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/create/components/CommandMenuWorkflowCreateStepContent.tsx index e1bb6753c1..7b53697131 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/create/components/CommandMenuWorkflowCreateStepContent.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/create/components/CommandMenuWorkflowCreateStepContent.tsx @@ -74,8 +74,7 @@ export const CommandMenuWorkflowCreateStepContent = () => { nextStepId, position, connectionOptions, - logicFunctionId: selection.logicFunctionId, - name: selection.name, + defaultSettings: selection.defaultSettings, }); if (!isDefined(createdStep)) { diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepTypeContent.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepTypeContent.tsx index 1e8abe431f..19c80b3208 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepTypeContent.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepTypeContent.tsx @@ -52,24 +52,11 @@ export const CommandMenuWorkflowEditStepTypeContent = () => { throw new Error('Step not found'); } - const stepUpdate = - selection.type === 'LOGIC_FUNCTION' - ? { - ...existingStep, - type: selection.type, - name: selection.name, - settings: { - ...existingStep.settings, - input: { - logicFunctionId: selection.logicFunctionId, - logicFunctionInput: {}, - }, - }, - } - : { - ...existingStep, - type: selection.type, - }; + const stepUpdate = { + ...existingStep, + type: selection.type, + settings: selection.defaultSettings ?? existingStep.settings, + }; const { updatedStep } = await updateStep(stepUpdate as WorkflowAction); diff --git a/packages/twenty-front/src/modules/settings/logic-functions/hooks/useGetManyLogicFunctions.ts b/packages/twenty-front/src/modules/settings/logic-functions/hooks/useGetManyLogicFunctions.ts deleted file mode 100644 index f7679dfd39..0000000000 --- a/packages/twenty-front/src/modules/settings/logic-functions/hooks/useGetManyLogicFunctions.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient'; -import { FIND_MANY_LOGIC_FUNCTIONS } from '@/settings/logic-functions/graphql/queries/findManyLogicFunctions'; -import { useQuery } from '@apollo/client'; -import { - type GetManyLogicFunctionsQuery, - type GetManyLogicFunctionsQueryVariables, -} from '~/generated-metadata/graphql'; - -export const useGetManyLogicFunctions = () => { - const apolloMetadataClient = useApolloCoreClient(); - - const { data, loading, error } = useQuery< - GetManyLogicFunctionsQuery, - GetManyLogicFunctionsQueryVariables - >(FIND_MANY_LOGIC_FUNCTIONS, { - client: apolloMetadataClient ?? undefined, - }); - - return { - logicFunctions: data?.findManyLogicFunctions || [], - loading, - error, - }; -}; diff --git a/packages/twenty-front/src/modules/settings/logic-functions/states/logicFunctionsState.ts b/packages/twenty-front/src/modules/settings/logic-functions/states/logicFunctionsState.ts new file mode 100644 index 0000000000..149efd828f --- /dev/null +++ b/packages/twenty-front/src/modules/settings/logic-functions/states/logicFunctionsState.ts @@ -0,0 +1,10 @@ +import { createState } from 'twenty-ui/utilities'; +import { type GetManyLogicFunctionsQuery } from '~/generated-metadata/graphql'; + +export type LogicFunction = + GetManyLogicFunctionsQuery['findManyLogicFunctions'][number]; + +export const logicFunctionsState = createState({ + key: 'logicFunctionsState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/users/components/UserAndViewsProviderEffect.tsx b/packages/twenty-front/src/modules/users/components/MetadataProviderEffect.tsx similarity index 93% rename from packages/twenty-front/src/modules/users/components/UserAndViewsProviderEffect.tsx rename to packages/twenty-front/src/modules/users/components/MetadataProviderEffect.tsx index eed4e0122e..1e31bac0b0 100644 --- a/packages/twenty-front/src/modules/users/components/UserAndViewsProviderEffect.tsx +++ b/packages/twenty-front/src/modules/users/components/MetadataProviderEffect.tsx @@ -10,6 +10,7 @@ import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMemb import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState'; import { useInitializeFormatPreferences } from '@/localization/hooks/useInitializeFormatPreferences'; +import { logicFunctionsState } from '@/settings/logic-functions/states/logicFunctionsState'; import { getDateFnsLocale } from '@/ui/field/display/utils/getDateFnsLocale.util'; import { coreViewsState } from '@/views/states/coreViewState'; import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations'; @@ -24,13 +25,14 @@ import { type WorkspaceMember, useFindAllCoreViewsQuery, useGetCurrentUserQuery, + useGetManyLogicFunctionsQuery, } from '~/generated-metadata/graphql'; import { dateLocaleState } from '~/localization/states/dateLocaleState'; import { dynamicActivate } from '~/utils/i18n/dynamicActivate'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isMatchingLocation } from '~/utils/isMatchingLocation'; -export const UserAndViewsProviderEffect = () => { +export const MetadataProviderEffect = () => { const location = useLocation(); const [isCurrentUserLoaded, setIsCurrentUserLoaded] = useRecoilState( @@ -45,6 +47,7 @@ export const UserAndViewsProviderEffect = () => { const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState); const setCurrentUserWorkspace = useSetRecoilState(currentUserWorkspaceState); const setAvailableWorkspaces = useSetRecoilState(availableWorkspacesState); + const setLogicFunctions = useSetRecoilState(logicFunctionsState); const { initializeFormatPreferences } = useInitializeFormatPreferences(); const isLoggedIn = useIsLogged(); @@ -104,6 +107,16 @@ export const UserAndViewsProviderEffect = () => { skip: shouldSkip, }); + const { data: logicFunctionsData } = useGetManyLogicFunctionsQuery({ + skip: !isLoggedIn, + }); + + useEffect(() => { + if (isDefined(logicFunctionsData?.findManyLogicFunctions)) { + setLogicFunctions(logicFunctionsData.findManyLogicFunctions); + } + }, [logicFunctionsData?.findManyLogicFunctions, setLogicFunctions]); + useEffect(() => { if (!userQueryLoading) { setLocalIsCurrentUserLoaded(true); diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateStep.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateStep.ts index 5714f70609..6d866294e0 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateStep.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateStep.ts @@ -36,8 +36,7 @@ export const useCreateStep = () => { connectionOptions, shouldSelectNode = true, workflowVersionId: providedWorkflowVersionId, - logicFunctionId, - name, + defaultSettings, }: { newStepType: WorkflowActionType; parentStepId: string | undefined; @@ -46,8 +45,7 @@ export const useCreateStep = () => { connectionOptions?: WorkflowStepConnectionOptions; shouldSelectNode?: boolean; workflowVersionId?: string; - logicFunctionId?: string; - name?: string; + defaultSettings?: Record; }) => { if (isLoading === true) { return; @@ -69,8 +67,7 @@ export const useCreateStep = () => { nextStepId, position, parentStepConnectionOptions: connectionOptions, - logicFunctionId, - name, + defaultSettings, }) )?.data?.createWorkflowVersionStep; diff --git a/packages/twenty-front/src/pages/settings/ai/components/SettingsToolsTable.tsx b/packages/twenty-front/src/pages/settings/ai/components/SettingsToolsTable.tsx index c02d097ee4..8e444be515 100644 --- a/packages/twenty-front/src/pages/settings/ai/components/SettingsToolsTable.tsx +++ b/packages/twenty-front/src/pages/settings/ai/components/SettingsToolsTable.tsx @@ -2,10 +2,11 @@ import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; import { useMemo, useState } from 'react'; import Skeleton from 'react-loading-skeleton'; +import { useRecoilValue } from 'recoil'; import { useGetToolIndex } from '@/ai/hooks/useGetToolIndex'; -import { useGetManyLogicFunctions } from '@/settings/logic-functions/hooks/useGetManyLogicFunctions'; import { usePersistLogicFunction } from '@/settings/logic-functions/hooks/usePersistLogicFunction'; +import { logicFunctionsState } from '@/settings/logic-functions/states/logicFunctionsState'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput'; import { Table } from '@/ui/layout/table/components/Table'; @@ -59,7 +60,7 @@ const DEFAULT_TOOL_INPUT_SCHEMA = { }; export const SettingsToolsTable = () => { - const { logicFunctions, loading } = useGetManyLogicFunctions(); + const logicFunctions = useRecoilValue(logicFunctionsState); const { toolIndex, loading: toolIndexLoading } = useGetToolIndex(); const { createLogicFunction } = usePersistLogicFunction(); @@ -116,7 +117,7 @@ export const SettingsToolsTable = () => { [systemTools, builtInSearchTerm], ); - const showSkeleton = (loading || toolIndexLoading) && tools.length === 0; + const showSkeleton = toolIndexLoading && tools.length === 0; const handleCreateTool = async () => { setIsCreating(true); diff --git a/packages/twenty-front/src/testing/decorators/PageDecorator.tsx b/packages/twenty-front/src/testing/decorators/PageDecorator.tsx index 5db9261960..8d3f1398c4 100644 --- a/packages/twenty-front/src/testing/decorators/PageDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/PageDecorator.tsx @@ -15,7 +15,7 @@ import { ClientConfigProviderEffect } from '@/client-config/components/ClientCon import { ApolloCoreClientMockedProvider } from '@/object-metadata/hooks/__mocks__/ApolloCoreClientMockedProvider'; import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout'; -import { UserAndViewsProviderEffect } from '@/users/components/UserAndViewsProviderEffect'; +import { MetadataProviderEffect } from '@/users/components/MetadataProviderEffect'; import { ClientConfigProvider } from '~/modules/client-config/components/ClientConfigProvider'; import { UserProvider } from '~/modules/users/components/UserProvider'; import { mockedApolloClient } from '~/testing/mockedApolloClient'; @@ -85,7 +85,7 @@ const Providers = () => { - + diff --git a/packages/twenty-server/src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto.ts b/packages/twenty-server/src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto.ts index 6e4d15e763..ff7cda3498 100644 --- a/packages/twenty-server/src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto.ts @@ -5,6 +5,7 @@ import graphqlTypeJson from 'graphql-type-json'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { WorkflowStepPositionInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-step-position-input.dto'; import { WorkflowStepConnectionOptions } from 'src/modules/workflow/workflow-builder/workflow-version-step/types/WorkflowStepCreationOptions'; +import { WorkflowActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type'; import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type'; @InputType() @@ -52,15 +53,9 @@ export class CreateWorkflowVersionStepInput { }) id?: string; - @Field(() => String, { - description: 'Step name', + @Field(() => graphqlTypeJson, { + description: 'Default settings for the step', nullable: true, }) - name?: string; - - @Field(() => UUIDScalarType, { - description: 'Logic function ID', - nullable: true, - }) - logicFunctionId?: string; + defaultSettings?: WorkflowActionSettings; } diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/__tests__/workflow-version-step-operations.workspace-service.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/__tests__/workflow-version-step-operations.workspace-service.spec.ts index 103dc3629f..97957a9754 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/__tests__/workflow-version-step-operations.workspace-service.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/__tests__/workflow-version-step-operations.workspace-service.spec.ts @@ -3,12 +3,14 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { AiAgentRoleService } from 'src/engine/metadata-modules/ai/ai-agent-role/ai-agent-role.service'; import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity'; -import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity'; +import { createEmptyAllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-all-flat-entity-maps.constant'; +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { LogicFunctionRuntime } from 'src/engine/metadata-modules/logic-function/logic-function.entity'; import { LogicFunctionService } from 'src/engine/metadata-modules/logic-function/logic-function.service'; import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity'; +import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity'; import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; @@ -114,6 +116,15 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => { provide: WorkspaceCacheService, useValue: workspaceCacheService, }, + { + provide: WorkspaceManyOrAllFlatEntityMapsCacheService, + useValue: { + flushFlatEntityMaps: jest.fn(), + getOrRecomputeManyOrAllFlatEntityMaps: jest + .fn() + .mockResolvedValue(createEmptyAllFlatEntityMaps()), + }, + }, ], }).compile(); diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-creation.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-creation.workspace-service.ts index 49c4eb7738..b89e1f0294 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-creation.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-creation.workspace-service.ts @@ -38,8 +38,7 @@ export class WorkflowVersionStepCreationWorkspaceService { position, parentStepConnectionOptions, id, - logicFunctionId, - name, + defaultSettings, } = input; const workflowVersion = @@ -61,8 +60,7 @@ export class WorkflowVersionStepCreationWorkspaceService { position, workflowVersionId, id, - logicFunctionId, - name, + defaultSettings, }, ); diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service.ts index f8049437f5..32c7eb1ef7 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service.ts @@ -20,7 +20,9 @@ import { type WorkflowStepPositionInput } from 'src/engine/core-modules/workflow import { AiAgentRoleService } from 'src/engine/metadata-modules/ai/ai-agent-role/ai-agent-role.service'; import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity'; import { DEFAULT_SMART_MODEL } from 'src/engine/metadata-modules/ai/ai-models/constants/ai-models.const'; +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { LogicFunctionService } from 'src/engine/metadata-modules/logic-function/logic-function.service'; +import { findFlatLogicFunctionOrThrow } from 'src/engine/metadata-modules/logic-function/utils/find-flat-logic-function-or-throw.util'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity'; import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; @@ -72,6 +74,7 @@ export class WorkflowVersionStepOperationsWorkspaceService { private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService, private readonly aiAgentRoleService: AiAgentRoleService, private readonly workspaceCacheService: WorkspaceCacheService, + private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, ) {} async runWorkflowVersionStepDeletionSideEffects({ @@ -135,16 +138,14 @@ export class WorkflowVersionStepOperationsWorkspaceService { workflowVersionId, position, id, - logicFunctionId, - name, + defaultSettings, }: { type: WorkflowActionType; workspaceId: string; workflowVersionId: string; position?: WorkflowStepPositionInput; id?: string; - logicFunctionId?: string; - name?: string; + defaultSettings?: Record; }): Promise<{ builtStep: WorkflowAction; additionalCreatedSteps?: WorkflowAction[]; @@ -200,17 +201,34 @@ export class WorkflowVersionStepOperationsWorkspaceService { }; } case WorkflowActionType.LOGIC_FUNCTION: { - if (!logicFunctionId) { + const logicFunctionId = ( + defaultSettings?.input as { logicFunctionId: string } | undefined + )?.logicFunctionId; + + if (!isDefined(logicFunctionId)) { throw new WorkflowVersionStepException( 'Logic function ID is required for LOGIC_FUNCTION step', WorkflowVersionStepExceptionCode.INVALID_REQUEST, ); } + const { flatLogicFunctionMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatLogicFunctionMaps'], + }, + ); + + const flatLogicFunction = findFlatLogicFunctionOrThrow({ + id: logicFunctionId, + flatLogicFunctionMaps, + }); + return { builtStep: { ...baseStep, - name: name ?? 'Logic Function', + name: flatLogicFunction.name, type: WorkflowActionType.LOGIC_FUNCTION, settings: { ...BASE_STEP_DEFINITION, diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-update.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-update.workspace-service.ts index 5c8364efc4..160ca8a51a 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-update.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-update.workspace-service.ts @@ -8,8 +8,8 @@ import { WorkflowVersionStepExceptionCode, } from 'src/modules/workflow/common/exceptions/workflow-version-step.exception'; import { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service'; -import { WorkflowVersionStepOperationsWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service'; import { WorkflowVersionStepHelpersWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-helpers.workspace-service'; +import { WorkflowVersionStepOperationsWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step-operations.workspace-service'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type'; @Injectable() @@ -114,6 +114,7 @@ export class WorkflowVersionStepUpdateWorkspaceService { workspaceId, position: newStep.position, workflowVersionId, + defaultSettings: newStep.settings, }, ); diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.module.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.module.ts index 3bc26df059..54fc35e8d6 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.module.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-version-step/workflow-version-step.module.ts @@ -4,10 +4,11 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { AiAgentRoleModule } from 'src/engine/metadata-modules/ai/ai-agent-role/ai-agent-role.module'; import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity'; +import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module'; +import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity'; import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity'; -import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module'; import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module'; import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module'; import { WorkflowSchemaModule } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.module'; @@ -31,6 +32,7 @@ import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workfl RoleTargetEntity, RoleEntity, ]), + WorkspaceManyOrAllFlatEntityMapsCacheModule, ], providers: [ WorkflowVersionStepWorkspaceService, diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts index 89c9b4379a..cab545570a 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-settings.type.ts @@ -7,6 +7,7 @@ import { type WorkflowFormActionSettings } from 'src/modules/workflow/workflow-e import { type WorkflowHttpRequestActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/http-request/types/workflow-http-request-action-settings.type'; import { type WorkflowIfElseActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/if-else/types/workflow-if-else-action-settings.type'; import { type WorkflowIteratorActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/iterator/types/workflow-iterator-action-settings.type'; +import { type WorkflowLogicFunctionActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/logic-function/types/workflow-logic-function-action-settings.type'; import { type WorkflowSendEmailActionSettings } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/types/workflow-send-email-action-settings.type'; import { type WorkflowCreateRecordActionSettings, @@ -29,6 +30,7 @@ export type BaseWorkflowActionSettings = { }; export type WorkflowActionSettings = + | WorkflowLogicFunctionActionSettings | WorkflowSendEmailActionSettings | WorkflowCodeActionSettings | WorkflowCreateRecordActionSettings