diff --git a/packages/twenty-front/src/modules/auth/components/VerifyEmailEffect.tsx b/packages/twenty-front/src/modules/auth/components/VerifyEmailEffect.tsx
index c817b8d764..a2bcf266c8 100644
--- a/packages/twenty-front/src/modules/auth/components/VerifyEmailEffect.tsx
+++ b/packages/twenty-front/src/modules/auth/components/VerifyEmailEffect.tsx
@@ -5,13 +5,14 @@ import { ApolloError } from '@apollo/client';
import { verifyEmailRedirectPathState } from '@/app/states/verifyEmailRedirectPathState';
import { useVerifyLogin } from '@/auth/hooks/useVerifyLogin';
+import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
import { useIsCurrentLocationOnAWorkspace } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspace';
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
import { Modal } from '@/ui/layout/modal/components/Modal';
import { useLingui } from '@lingui/react/macro';
import { useEffect, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
-import { useSetRecoilState } from 'recoil';
+import { useRecoilValue, useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
@@ -40,6 +41,7 @@ export const VerifyEmailEffect = () => {
const { redirectToWorkspaceDomain } = useRedirectToWorkspaceDomain();
const { verifyLoginToken } = useVerifyLogin();
const { isOnAWorkspace } = useIsCurrentLocationOnAWorkspace();
+ const clientConfigApiStatus = useRecoilValue(clientConfigApiStatusState);
const { t } = useLingui();
useEffect(() => {
@@ -112,10 +114,15 @@ export const VerifyEmailEffect = () => {
}
};
+ if (!clientConfigApiStatus.isLoadedOnce) {
+ return;
+ }
+
verifyEmailToken();
+
// Verify email only needs to run once at mount
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ }, [clientConfigApiStatus.isLoadedOnce]);
if (isError) {
return (
diff --git a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx
index 977bd22e39..a596d27c26 100644
--- a/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx
+++ b/packages/twenty-front/src/modules/client-config/components/ClientConfigProviderEffect.tsx
@@ -1,105 +1,14 @@
import { useClientConfig } from '@/client-config/hooks/useClientConfig';
-import { aiModelsState } from '@/client-config/states/aiModelsState';
-import { apiConfigState } from '@/client-config/states/apiConfigState';
-import { appVersionState } from '@/client-config/states/appVersionState';
-import { authProvidersState } from '@/client-config/states/authProvidersState';
-import { billingState } from '@/client-config/states/billingState';
-import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
-import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
-import { captchaState } from '@/client-config/states/captchaState';
-import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionIdState';
import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
-import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabledState';
-import { isAttachmentPreviewEnabledState } from '@/client-config/states/isAttachmentPreviewEnabledState';
-import { isConfigVariablesInDbEnabledState } from '@/client-config/states/isConfigVariablesInDbEnabledState';
-import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
-import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState';
-import { isGoogleCalendarEnabledState } from '@/client-config/states/isGoogleCalendarEnabledState';
-import { isGoogleMessagingEnabledState } from '@/client-config/states/isGoogleMessagingEnabledState';
-import { isImapSmtpCaldavEnabledState } from '@/client-config/states/isImapSmtpCaldavEnabledState';
-import { isMicrosoftCalendarEnabledState } from '@/client-config/states/isMicrosoftCalendarEnabledState';
-import { isMicrosoftMessagingEnabledState } from '@/client-config/states/isMicrosoftMessagingEnabledState';
-import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
-import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState';
-import { sentryConfigState } from '@/client-config/states/sentryConfigState';
-import { supportChatState } from '@/client-config/states/supportChatState';
-import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
import { useEffect } from 'react';
-import { useRecoilState, useSetRecoilState } from 'recoil';
+import { useRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
export const ClientConfigProviderEffect = () => {
- const setIsAnalyticsEnabled = useSetRecoilState(isAnalyticsEnabledState);
- const setDomainConfiguration = useSetRecoilState(domainConfigurationState);
- const setAuthProviders = useSetRecoilState(authProvidersState);
- const setAiModels = useSetRecoilState(aiModelsState);
-
- const setIsDeveloperDefaultSignInPrefilled = useSetRecoilState(
- isDeveloperDefaultSignInPrefilledState,
- );
- const setIsMultiWorkspaceEnabled = useSetRecoilState(
- isMultiWorkspaceEnabledState,
- );
- const setIsEmailVerificationRequired = useSetRecoilState(
- isEmailVerificationRequiredState,
- );
-
- const setBilling = useSetRecoilState(billingState);
- const setSupportChat = useSetRecoilState(supportChatState);
-
- const setSentryConfig = useSetRecoilState(sentryConfigState);
const [clientConfigApiStatus, setClientConfigApiStatus] = useRecoilState(
clientConfigApiStatusState,
);
- const setCaptcha = useSetRecoilState(captchaState);
-
- const setChromeExtensionId = useSetRecoilState(chromeExtensionIdState);
-
- const setApiConfig = useSetRecoilState(apiConfigState);
-
- const setCanManageFeatureFlags = useSetRecoilState(
- canManageFeatureFlagsState,
- );
-
- const setLabPublicFeatureFlags = useSetRecoilState(
- labPublicFeatureFlagsState,
- );
-
- const setMicrosoftMessagingEnabled = useSetRecoilState(
- isMicrosoftMessagingEnabledState,
- );
-
- const setMicrosoftCalendarEnabled = useSetRecoilState(
- isMicrosoftCalendarEnabledState,
- );
-
- const setGoogleMessagingEnabled = useSetRecoilState(
- isGoogleMessagingEnabledState,
- );
-
- const setGoogleCalendarEnabled = useSetRecoilState(
- isGoogleCalendarEnabledState,
- );
-
- const setIsAttachmentPreviewEnabled = useSetRecoilState(
- isAttachmentPreviewEnabledState,
- );
-
- const setIsConfigVariablesInDbEnabled = useSetRecoilState(
- isConfigVariablesInDbEnabledState,
- );
-
- const setCalendarBookingPageId = useSetRecoilState(
- calendarBookingPageIdState,
- );
-
- const setIsImapSmtpCaldavEnabled = useSetRecoilState(
- isImapSmtpCaldavEnabledState,
- );
-
- const setAppVersion = useSetRecoilState(appVersionState);
-
const { data, loading, error, fetchClientConfig } = useClientConfig();
useEffect(() => {
@@ -130,98 +39,7 @@ export const ClientConfigProviderEffect = () => {
if (!isDefined(data?.clientConfig)) {
return;
}
-
- setClientConfigApiStatus((currentStatus) => ({
- ...currentStatus,
- isErrored: false,
- error: undefined,
- }));
- setAppVersion(data.clientConfig.appVersion);
- setAuthProviders({
- google: data?.clientConfig.authProviders.google,
- microsoft: data?.clientConfig.authProviders.microsoft,
- password: data?.clientConfig.authProviders.password,
- magicLink: false,
- sso: data?.clientConfig.authProviders.sso,
- });
- setAiModels(data?.clientConfig.aiModels || []);
- setIsAnalyticsEnabled(data?.clientConfig.analyticsEnabled);
- setIsDeveloperDefaultSignInPrefilled(data?.clientConfig.signInPrefilled);
- setIsMultiWorkspaceEnabled(data?.clientConfig.isMultiWorkspaceEnabled);
- setIsEmailVerificationRequired(
- data?.clientConfig.isEmailVerificationRequired,
- );
- setBilling(data?.clientConfig.billing);
- setSupportChat(data?.clientConfig.support);
-
- setSentryConfig({
- dsn: data?.clientConfig?.sentry?.dsn,
- release: data?.clientConfig?.sentry?.release,
- environment: data?.clientConfig?.sentry?.environment,
- });
-
- setCaptcha({
- provider: data?.clientConfig?.captcha?.provider,
- siteKey: data?.clientConfig?.captcha?.siteKey,
- });
-
- setChromeExtensionId(data?.clientConfig?.chromeExtensionId);
- setApiConfig(data?.clientConfig?.api);
- setDomainConfiguration({
- defaultSubdomain: data?.clientConfig?.defaultSubdomain,
- frontDomain: data?.clientConfig?.frontDomain,
- });
- setCanManageFeatureFlags(data?.clientConfig?.canManageFeatureFlags);
- setLabPublicFeatureFlags(data?.clientConfig?.publicFeatureFlags);
- setMicrosoftMessagingEnabled(
- data?.clientConfig?.isMicrosoftMessagingEnabled,
- );
- setMicrosoftCalendarEnabled(data?.clientConfig?.isMicrosoftCalendarEnabled);
- setGoogleMessagingEnabled(data?.clientConfig?.isGoogleMessagingEnabled);
- setGoogleCalendarEnabled(data?.clientConfig?.isGoogleCalendarEnabled);
- setIsAttachmentPreviewEnabled(
- data?.clientConfig?.isAttachmentPreviewEnabled,
- );
- setIsConfigVariablesInDbEnabled(
- data?.clientConfig?.isConfigVariablesInDbEnabled,
- );
- setClientConfigApiStatus((currentStatus) => ({
- ...currentStatus,
- isSaved: true,
- }));
-
- setCalendarBookingPageId(data?.clientConfig?.calendarBookingPageId ?? null);
- setIsImapSmtpCaldavEnabled(data?.clientConfig?.isImapSmtpCaldavEnabled);
- }, [
- data,
- loading,
- error,
- setIsDeveloperDefaultSignInPrefilled,
- setIsMultiWorkspaceEnabled,
- setIsEmailVerificationRequired,
- setSupportChat,
- setBilling,
- setSentryConfig,
- setClientConfigApiStatus,
- setCaptcha,
- setChromeExtensionId,
- setApiConfig,
- setIsAnalyticsEnabled,
- setDomainConfiguration,
- setAuthProviders,
- setAiModels,
- setCanManageFeatureFlags,
- setLabPublicFeatureFlags,
- setMicrosoftMessagingEnabled,
- setMicrosoftCalendarEnabled,
- setGoogleMessagingEnabled,
- setGoogleCalendarEnabled,
- setIsAttachmentPreviewEnabled,
- setIsConfigVariablesInDbEnabled,
- setCalendarBookingPageId,
- setIsImapSmtpCaldavEnabled,
- setAppVersion,
- ]);
+ }, [data?.clientConfig, error, loading, setClientConfigApiStatus]);
return <>>;
};
diff --git a/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts b/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts
index c92a961818..262da88689 100644
--- a/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts
+++ b/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts
@@ -1,6 +1,30 @@
+import { aiModelsState } from '@/client-config/states/aiModelsState';
+import { apiConfigState } from '@/client-config/states/apiConfigState';
+import { appVersionState } from '@/client-config/states/appVersionState';
+import { authProvidersState } from '@/client-config/states/authProvidersState';
+import { billingState } from '@/client-config/states/billingState';
+import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
+import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
+import { captchaState } from '@/client-config/states/captchaState';
+import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionIdState';
+import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabledState';
+import { isAttachmentPreviewEnabledState } from '@/client-config/states/isAttachmentPreviewEnabledState';
+import { isConfigVariablesInDbEnabledState } from '@/client-config/states/isConfigVariablesInDbEnabledState';
+import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
+import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState';
+import { isGoogleCalendarEnabledState } from '@/client-config/states/isGoogleCalendarEnabledState';
+import { isGoogleMessagingEnabledState } from '@/client-config/states/isGoogleMessagingEnabledState';
+import { isImapSmtpCaldavEnabledState } from '@/client-config/states/isImapSmtpCaldavEnabledState';
+import { isMicrosoftCalendarEnabledState } from '@/client-config/states/isMicrosoftCalendarEnabledState';
+import { isMicrosoftMessagingEnabledState } from '@/client-config/states/isMicrosoftMessagingEnabledState';
+import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
+import { labPublicFeatureFlagsState } from '@/client-config/states/labPublicFeatureFlagsState';
+import { sentryConfigState } from '@/client-config/states/sentryConfigState';
+import { supportChatState } from '@/client-config/states/supportChatState';
import { type ClientConfig } from '@/client-config/types/ClientConfig';
+import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
import { useCallback } from 'react';
-import { useRecoilValue, useSetRecoilState } from 'recoil';
+import { useRecoilState, useSetRecoilState } from 'recoil';
import { clientConfigApiStatusState } from '../states/clientConfigApiStatusState';
import { getClientConfig } from '../utils/getClientConfig';
@@ -13,11 +37,77 @@ type UseClientConfigResult = {
};
export const useClientConfig = (): UseClientConfigResult => {
- const clientConfigApiStatus = useRecoilValue(clientConfigApiStatusState);
- const setClientConfigApiStatus = useSetRecoilState(
+ const setIsAnalyticsEnabled = useSetRecoilState(isAnalyticsEnabledState);
+ const setDomainConfiguration = useSetRecoilState(domainConfigurationState);
+ const setAuthProviders = useSetRecoilState(authProvidersState);
+ const setAiModels = useSetRecoilState(aiModelsState);
+
+ const setIsDeveloperDefaultSignInPrefilled = useSetRecoilState(
+ isDeveloperDefaultSignInPrefilledState,
+ );
+ const setIsMultiWorkspaceEnabled = useSetRecoilState(
+ isMultiWorkspaceEnabledState,
+ );
+ const setIsEmailVerificationRequired = useSetRecoilState(
+ isEmailVerificationRequiredState,
+ );
+
+ const setBilling = useSetRecoilState(billingState);
+ const setSupportChat = useSetRecoilState(supportChatState);
+
+ const setSentryConfig = useSetRecoilState(sentryConfigState);
+ const [clientConfigApiStatus, setClientConfigApiStatus] = useRecoilState(
clientConfigApiStatusState,
);
+ const setCaptcha = useSetRecoilState(captchaState);
+
+ const setChromeExtensionId = useSetRecoilState(chromeExtensionIdState);
+
+ const setApiConfig = useSetRecoilState(apiConfigState);
+
+ const setCanManageFeatureFlags = useSetRecoilState(
+ canManageFeatureFlagsState,
+ );
+
+ const setLabPublicFeatureFlags = useSetRecoilState(
+ labPublicFeatureFlagsState,
+ );
+
+ const setMicrosoftMessagingEnabled = useSetRecoilState(
+ isMicrosoftMessagingEnabledState,
+ );
+
+ const setMicrosoftCalendarEnabled = useSetRecoilState(
+ isMicrosoftCalendarEnabledState,
+ );
+
+ const setGoogleMessagingEnabled = useSetRecoilState(
+ isGoogleMessagingEnabledState,
+ );
+
+ const setGoogleCalendarEnabled = useSetRecoilState(
+ isGoogleCalendarEnabledState,
+ );
+
+ const setIsAttachmentPreviewEnabled = useSetRecoilState(
+ isAttachmentPreviewEnabledState,
+ );
+
+ const setIsConfigVariablesInDbEnabled = useSetRecoilState(
+ isConfigVariablesInDbEnabledState,
+ );
+
+ const setCalendarBookingPageId = useSetRecoilState(
+ calendarBookingPageIdState,
+ );
+
+ const setIsImapSmtpCaldavEnabled = useSetRecoilState(
+ isImapSmtpCaldavEnabledState,
+ );
+
+ const setAppVersion = useSetRecoilState(appVersionState);
+
const fetchClientConfig = useCallback(async () => {
setClientConfigApiStatus((prev) => ({
...prev,
@@ -34,6 +124,61 @@ export const useClientConfig = (): UseClientConfigResult => {
error: undefined,
data: { clientConfig },
}));
+ setClientConfigApiStatus((currentStatus) => ({
+ ...currentStatus,
+ isErrored: false,
+ error: undefined,
+ }));
+ setAppVersion(clientConfig.appVersion);
+ setAuthProviders({
+ google: clientConfig.authProviders.google,
+ microsoft: clientConfig.authProviders.microsoft,
+ password: clientConfig.authProviders.password,
+ magicLink: false,
+ sso: clientConfig.authProviders.sso,
+ });
+ setAiModels(clientConfig.aiModels || []);
+ setIsAnalyticsEnabled(clientConfig.analyticsEnabled);
+ setIsDeveloperDefaultSignInPrefilled(clientConfig.signInPrefilled);
+ setIsMultiWorkspaceEnabled(clientConfig.isMultiWorkspaceEnabled);
+ setIsEmailVerificationRequired(clientConfig.isEmailVerificationRequired);
+ setBilling(clientConfig.billing);
+ setSupportChat(clientConfig.support);
+
+ setSentryConfig({
+ dsn: clientConfig?.sentry?.dsn,
+ release: clientConfig?.sentry?.release,
+ environment: clientConfig?.sentry?.environment,
+ });
+
+ setCaptcha({
+ provider: clientConfig?.captcha?.provider,
+ siteKey: clientConfig?.captcha?.siteKey,
+ });
+
+ setChromeExtensionId(clientConfig?.chromeExtensionId);
+ setApiConfig(clientConfig?.api);
+ setDomainConfiguration({
+ defaultSubdomain: clientConfig?.defaultSubdomain,
+ frontDomain: clientConfig?.frontDomain,
+ });
+ setCanManageFeatureFlags(clientConfig?.canManageFeatureFlags);
+ setLabPublicFeatureFlags(clientConfig?.publicFeatureFlags);
+ setMicrosoftMessagingEnabled(clientConfig?.isMicrosoftMessagingEnabled);
+ setMicrosoftCalendarEnabled(clientConfig?.isMicrosoftCalendarEnabled);
+ setGoogleMessagingEnabled(clientConfig?.isGoogleMessagingEnabled);
+ setGoogleCalendarEnabled(clientConfig?.isGoogleCalendarEnabled);
+ setIsAttachmentPreviewEnabled(clientConfig?.isAttachmentPreviewEnabled);
+ setIsConfigVariablesInDbEnabled(
+ clientConfig?.isConfigVariablesInDbEnabled,
+ );
+ setClientConfigApiStatus((currentStatus) => ({
+ ...currentStatus,
+ isSaved: true,
+ }));
+
+ setCalendarBookingPageId(clientConfig?.calendarBookingPageId ?? null);
+ setIsImapSmtpCaldavEnabled(clientConfig?.isImapSmtpCaldavEnabled);
} catch (err) {
const error =
err instanceof Error ? err : new Error('Failed to fetch client config');
@@ -45,7 +190,33 @@ export const useClientConfig = (): UseClientConfigResult => {
error,
}));
}
- }, [setClientConfigApiStatus]);
+ }, [
+ setAiModels,
+ setApiConfig,
+ setAppVersion,
+ setAuthProviders,
+ setBilling,
+ setCalendarBookingPageId,
+ setCanManageFeatureFlags,
+ setCaptcha,
+ setChromeExtensionId,
+ setClientConfigApiStatus,
+ setDomainConfiguration,
+ setGoogleCalendarEnabled,
+ setGoogleMessagingEnabled,
+ setIsAnalyticsEnabled,
+ setIsAttachmentPreviewEnabled,
+ setIsConfigVariablesInDbEnabled,
+ setIsDeveloperDefaultSignInPrefilled,
+ setIsEmailVerificationRequired,
+ setIsImapSmtpCaldavEnabled,
+ setIsMultiWorkspaceEnabled,
+ setLabPublicFeatureFlags,
+ setMicrosoftCalendarEnabled,
+ setMicrosoftMessagingEnabled,
+ setSentryConfig,
+ setSupportChat,
+ ]);
return {
data: clientConfigApiStatus.data,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx
index 1106a0c565..9e300880e9 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterFieldSelect.tsx
@@ -2,7 +2,7 @@ import { SelectControl } from '@/ui/input/components/SelectControl';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useWorkflowVersionIdOrThrow } from '@/workflow/hooks/useWorkflowVersionIdOrThrow';
import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector';
-import { useGetFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem';
+import { useFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useFilterFieldMetadataItem';
import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings';
import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext';
import { getViewFilterOperands } from '@/workflow/workflow-steps/workflow-actions/filter-action/utils/getStepFilterOperands';
@@ -15,6 +15,7 @@ import { useContext } from 'react';
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { type StepFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
+import { useIcons } from 'twenty-ui/display';
import { FieldMetadataType } from '~/generated-metadata/graphql';
type WorkflowStepFilterFieldSelectProps = {
@@ -50,7 +51,12 @@ export const WorkflowStepFilterFieldSelect = ({
}),
);
- const { getFilterFieldMetadataItem } = useGetFilterFieldMetadataItem();
+ const { getIcon } = useIcons();
+
+ const {
+ fieldMetadataItem: filterFieldMetadataItem,
+ objectMetadataItem: filterObjectMetadataItem,
+ } = useFilterFieldMetadataItem(stepFilter.fieldMetadataId ?? '');
const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({
shouldDisplayRecordFields,
@@ -66,7 +72,7 @@ export const WorkflowStepFilterFieldSelect = ({
rawVariableName: variableName,
part: 'stepId',
});
- const currentStepOutputSchema = snapshot
+ const [currentStepOutputSchema] = snapshot
.getLoadable(
stepsOutputSchemaFamilySelector({
workflowVersionId,
@@ -81,35 +87,25 @@ export const WorkflowStepFilterFieldSelect = ({
fieldMetadataId,
compositeFieldSubFieldName,
} = searchVariableThroughOutputSchema({
- stepOutputSchema: currentStepOutputSchema?.[0],
+ stepOutputSchema: currentStepOutputSchema,
rawVariableName: variableName,
isFullRecord: false,
});
- const {
- fieldMetadataItem: selectedFieldMetadataItem,
- objectMetadataItem,
- } = isDefined(fieldMetadataId)
- ? getFilterFieldMetadataItem(fieldMetadataId)
- : {
- fieldMetadataItem: undefined,
- objectMetadataItem: undefined,
- };
-
const filterType = isDefined(fieldMetadataId)
- ? (selectedFieldMetadataItem?.type ?? 'unknown')
+ ? (filterFieldMetadataItem?.type ?? 'unknown')
: variableType;
const isFullRecord =
- selectedFieldMetadataItem?.name === 'id' &&
- isDefined(objectMetadataItem?.labelSingular);
+ filterFieldMetadataItem?.name === 'id' &&
+ isDefined(filterObjectMetadataItem?.labelSingular);
upsertStepFilterSettings({
stepFilterToUpsert: {
...stepFilter,
stepOutputKey: variableName,
displayValue: isFullRecord
- ? objectMetadataItem.labelSingular
+ ? filterObjectMetadataItem.labelSingular
: (variableLabel ?? ''),
type: filterType ?? 'unknown',
value: '',
@@ -126,7 +122,8 @@ export const WorkflowStepFilterFieldSelect = ({
upsertStepFilterSettings,
stepFilter,
workflowVersionId,
- getFilterFieldMetadataItem,
+ filterFieldMetadataItem,
+ filterObjectMetadataItem,
],
);
@@ -144,13 +141,11 @@ export const WorkflowStepFilterFieldSelect = ({
const label =
isSelectedFieldNotFound || !isDefined(stepFilter.displayValue)
? t`Select a field from a previous step`
- : stepFilter.displayValue;
+ : variableLabel;
const dropdownId = `step-filter-field-${stepFilter.id}`;
- const isReadonly = readonly ?? false;
-
- if (isReadonly || noAvailableVariables) {
+ if (noAvailableVariables) {
return (
+ }
+ dropdownComponents={[]}
+ />
+ );
+ }
+
+ if (readonly === true) {
+ return (
+
@@ -174,12 +188,14 @@ export const WorkflowStepFilterFieldSelect = ({
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx
index 0a5bc7892e..c9a3dbe16f 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueInput.tsx
@@ -7,7 +7,7 @@ import { FormTextFieldInput } from '@/object-record/record-field/ui/form-types/c
import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata';
import { WorkflowStepFilterValueCompositeInput } from '@/workflow/workflow-steps/workflow-actions/filter-action/components/WorkflowStepFilterValueCompositeInput';
-import { useGetFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem';
+import { useFilterFieldMetadataItem } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useFilterFieldMetadataItem';
import { useUpsertStepFilterSettings } from '@/workflow/workflow-steps/workflow-actions/filter-action/hooks/useUpsertStepFilterSettings';
import { WorkflowStepFilterContext } from '@/workflow/workflow-steps/workflow-actions/filter-action/states/context/WorkflowStepFilterContext';
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
@@ -62,7 +62,6 @@ export const WorkflowStepFilterValueInput = ({
const { readonly } = useContext(WorkflowStepFilterContext);
const { upsertStepFilterSettings } = useUpsertStepFilterSettings();
- const { getFilterFieldMetadataItem } = useGetFilterFieldMetadataItem();
const handleValueChange = (value: JsonValue) => {
const valueToUpsert = isString(value)
@@ -85,10 +84,6 @@ export const WorkflowStepFilterValueInput = ({
(stepFilter && !configurableViewFilterOperands.has(stepFilter.operand)) ??
true;
- if (isDisabled || operandHasNoInput) {
- return null;
- }
-
const {
fieldMetadataId,
type: variableType,
@@ -96,12 +91,11 @@ export const WorkflowStepFilterValueInput = ({
} = stepFilter;
const { fieldMetadataItem: selectedFieldMetadataItem, objectMetadataItem } =
- isDefined(fieldMetadataId)
- ? getFilterFieldMetadataItem(fieldMetadataId)
- : {
- fieldMetadataItem: undefined,
- objectMetadataItem: undefined,
- };
+ useFilterFieldMetadataItem(fieldMetadataId ?? '');
+
+ if (isDisabled || operandHasNoInput) {
+ return null;
+ }
const isFilterableByMultiSelectValue =
variableType === FieldMetadataType.MULTI_SELECT ||
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useFilterFieldMetadataItem.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useFilterFieldMetadataItem.ts
new file mode 100644
index 0000000000..8f3204ea22
--- /dev/null
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useFilterFieldMetadataItem.ts
@@ -0,0 +1,18 @@
+import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
+
+export const useFilterFieldMetadataItem = (fieldMetadataId: string) => {
+ const { objectMetadataItems } = useObjectMetadataItems();
+
+ const objectMetadataItem = objectMetadataItems.find((objectMetadataItem) =>
+ objectMetadataItem.fields.some((field) => field.id === fieldMetadataId),
+ );
+
+ const fieldMetadataItem = objectMetadataItem?.fields.find(
+ (field) => field.id === fieldMetadataId,
+ );
+
+ return {
+ objectMetadataItem,
+ fieldMetadataItem,
+ };
+};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts
deleted file mode 100644
index dff4240032..0000000000
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/filter-action/hooks/useGetFilterFieldMetadataItem.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
-import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
-import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { isDefined } from 'twenty-shared/utils';
-
-export const useGetFilterFieldMetadataItem = () => {
- const { objectMetadataItems } = useObjectMetadataItems();
-
- const getFilterFieldMetadataItem = (
- fieldMetadataId: string,
- ): {
- fieldMetadataItem: FieldMetadataItem | undefined;
- objectMetadataItem: ObjectMetadataItem | undefined;
- } => {
- for (const objectMetadataItem of objectMetadataItems) {
- const field = objectMetadataItem.fields.find(
- (field) => field.id === fieldMetadataId,
- );
- if (isDefined(field)) {
- return {
- fieldMetadataItem: field,
- objectMetadataItem: objectMetadataItem,
- };
- }
- }
- return {
- fieldMetadataItem: undefined,
- objectMetadataItem: undefined,
- };
- };
-
- return {
- getFilterFieldMetadataItem,
- };
-};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx
index e300ddcad4..1520df5fd0 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx
@@ -62,17 +62,17 @@ export const WorkflowVariablesDropdownFieldItems = ({
/>
- {filteredOptions.map(([key, subStep]) => (
+ {filteredOptions.map(([key, option]) => (
handleSelectField(key)}
- text={subStep.label || key}
- hasSubMenu={!subStep.isLeaf}
- LeftIcon={subStep.icon ? getIcon(subStep.icon) : undefined}
+ text={option.label || key}
+ hasSubMenu={!option.isLeaf}
+ LeftIcon={option.icon ? getIcon(option.icon) : undefined}
contextualText={
- subStep.isLeaf ? subStep?.value?.toString() : undefined
+ option.isLeaf ? option?.value?.toString() : undefined
}
/>
))}
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useVariableDropdown.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useVariableDropdown.ts
index fa26a86c9c..4e345ec42c 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useVariableDropdown.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useVariableDropdown.ts
@@ -33,6 +33,7 @@ type UseVariableDropdownReturn = {
setSearchInputValue: (value: string) => void;
handleSelectField: (key: string) => void;
goBack: () => void;
+ // TODO: fix typing here
filteredOptions: [string, any][];
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/types/StepOutputSchema.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/types/StepOutputSchema.ts
index 8a30d63a1a..48cc49fe11 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/types/StepOutputSchema.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/types/StepOutputSchema.ts
@@ -31,6 +31,10 @@ type Link = {
export type BaseOutputSchema = Record;
+export type FieldOutputSchema = (Leaf | Node) & {
+ fieldMetadataId: string;
+};
+
export type RecordOutputSchema = {
object: {
nameSingular: string;
@@ -38,7 +42,7 @@ export type RecordOutputSchema = {
objectMetadataId: string;
isRelationField?: boolean;
} & Leaf;
- fields: BaseOutputSchema;
+ fields: Record;
_outputSchemaType: 'RECORD';
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getCurrentSubStepFromPath.test.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getCurrentSubStepFromPath.test.ts
index 1b689d3930..44e6b1fcec 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getCurrentSubStepFromPath.test.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getCurrentSubStepFromPath.test.ts
@@ -19,7 +19,12 @@ const mockStep = {
objectMetadataId: '123',
},
fields: {
- name: { label: 'Name', value: 'Twenty', isLeaf: true },
+ name: {
+ label: 'Name',
+ value: 'Twenty',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
},
_outputSchemaType: 'RECORD',
},
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts
index 0af0ad7f79..c8d56dfe38 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts
@@ -19,16 +19,42 @@ const mockStep = {
objectMetadataId: '123',
},
fields: {
- name: { label: 'Name', value: 'Twenty', isLeaf: true },
+ name: {
+ label: 'Name',
+ value: 'Twenty',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174001',
+ },
address: {
- label: 'Address',
- value: {
- street: { label: 'Street', value: '123 Main St', isLeaf: true },
- city: { label: 'City', value: 'New York', isLeaf: true },
- state: { label: 'State', value: 'NY', isLeaf: true },
- zip: { label: 'Zip', value: '10001', isLeaf: true },
- },
isLeaf: false,
+ label: 'Address',
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ value: {
+ street: {
+ label: 'Street',
+ value: '123 Main St',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ city: {
+ label: 'City',
+ value: 'New York',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ state: {
+ label: 'State',
+ value: 'NY',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ zip: {
+ label: 'Zip',
+ value: '10001',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ },
},
},
_outputSchemaType: 'RECORD',
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/searchVariableThroughOutputSchema.test.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/searchVariableThroughOutputSchema.test.ts
index 26fabd45fd..590776f251 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/searchVariableThroughOutputSchema.test.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/searchVariableThroughOutputSchema.test.ts
@@ -22,8 +22,18 @@ describe('searchVariableThroughOutputSchema', () => {
objectMetadataId: '123',
},
fields: {
- name: { label: 'Name', value: 'Twenty', isLeaf: true },
- address: { label: 'Address', value: '123 Main St', isLeaf: true },
+ name: {
+ label: 'Name',
+ value: 'Twenty',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ address: {
+ label: 'Address',
+ value: '123 Main St',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
},
_outputSchemaType: 'RECORD',
},
@@ -42,12 +52,23 @@ describe('searchVariableThroughOutputSchema', () => {
objectMetadataId: '123',
},
fields: {
- firstName: { label: 'First Name', value: 'Jane', isLeaf: true },
- lastName: { label: 'Last Name', value: 'Doe', isLeaf: true },
+ firstName: {
+ label: 'First Name',
+ value: 'Jane',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
+ lastName: {
+ label: 'Last Name',
+ value: 'Doe',
+ isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ },
email: {
label: 'Email',
value: 'jane@example.com',
isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
},
},
_outputSchemaType: 'RECORD',
@@ -90,6 +111,8 @@ describe('searchVariableThroughOutputSchema', () => {
});
expect(result).toEqual({
+ compositeFieldSubFieldName: undefined,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
variableLabel: 'Name',
variablePathLabel: 'Step 1 > Company > Name',
variableType: 'unknown',
@@ -104,6 +127,8 @@ describe('searchVariableThroughOutputSchema', () => {
});
expect(result).toEqual({
+ compositeFieldSubFieldName: undefined,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
variableLabel: 'Email',
variablePathLabel: 'Step 1 > Person > Email',
variableType: 'unknown',
@@ -237,6 +262,7 @@ describe('searchVariableThroughOutputSchema', () => {
label: 'Id',
value: '123e4567-e89b-12d3-a456-426614174000',
isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
},
'properties.after.name': {
icon: 'IconBuildingSkyscraper',
@@ -244,22 +270,28 @@ describe('searchVariableThroughOutputSchema', () => {
label: 'Name',
value: 'My text',
isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
},
'properties.after.annualRecurringRevenue': {
icon: 'IconMoneybag',
label: 'ARR',
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
value: {
amountMicros: {
type: FieldMetadataType.NUMERIC,
label: ' Amount Micros',
value: null,
isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ isCompositeSubField: true,
},
currencyCode: {
type: FieldMetadataType.TEXT,
label: ' Currency Code',
value: 'My text',
isLeaf: true,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
+ isCompositeSubField: true,
},
},
isLeaf: false,
@@ -285,6 +317,8 @@ describe('searchVariableThroughOutputSchema', () => {
});
expect(result).toEqual({
+ compositeFieldSubFieldName: undefined,
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
variableLabel: 'Name',
variablePathLabel: 'Record is Created > Name',
variableType: FieldMetadataType.TEXT,
@@ -300,6 +334,8 @@ describe('searchVariableThroughOutputSchema', () => {
});
expect(result).toEqual({
+ compositeFieldSubFieldName: 'amountMicros',
+ fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
variableLabel: ' Amount Micros',
variablePathLabel: 'Record is Created > ARR > Amount Micros',
variableType: FieldMetadataType.NUMERIC,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/filterOutputSchema.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/filterOutputSchema.ts
index 27da693603..8570bdaed9 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/filterOutputSchema.ts
+++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/filterOutputSchema.ts
@@ -1,6 +1,7 @@
import { type InputSchemaPropertyType } from '@/workflow/types/InputSchema';
import {
type BaseOutputSchema,
+ type FieldOutputSchema,
type OutputSchema,
type RecordOutputSchema,
} from '@/workflow/workflow-variables/types/StepOutputSchema';
@@ -35,7 +36,7 @@ const filterRecordOutputSchema = ({
shouldDisplayRecordFields: boolean;
shouldDisplayRecordObjects: boolean;
}): RecordOutputSchema | undefined => {
- const filteredFields: BaseOutputSchema = {};
+ const filteredFields: Record = {};
let hasValidFields = false;
for (const key in outputSchema.fields) {
@@ -135,8 +136,8 @@ const filterRecordOutputSchemaFieldsByType = ({
}: {
outputSchema: RecordOutputSchema;
fieldTypesToExclude: InputSchemaPropertyType[];
-}) => {
- const filteredFields: BaseOutputSchema = {};
+}): RecordOutputSchema => {
+ const filteredFields: Record = {};
for (const key in outputSchema.fields) {
const field = outputSchema.fields[key];
diff --git a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/constants/workflow-data-seeds.constants.ts b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/constants/workflow-data-seeds.constants.ts
deleted file mode 100644
index e4071346ae..0000000000
--- a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/constants/workflow-data-seeds.constants.ts
+++ /dev/null
@@ -1,991 +0,0 @@
-import { WorkflowStatus } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
-import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
-import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
-
-type WorkflowDataSeed = {
- id: string;
- name: string;
- lastPublishedVersionId: string;
- statuses: WorkflowStatus[];
- position: number;
- createdBySource: string;
- createdByWorkspaceMemberId: string;
- createdByName: string;
- createdByContext: object;
-};
-
-type WorkflowVersionDataSeed = {
- id: string;
- name: string;
- trigger: string;
- steps: string;
- status: WorkflowVersionStatus;
- position: number;
- workflowId: string;
-};
-
-export const WORKFLOW_DATA_SEED_COLUMNS: (keyof WorkflowDataSeed)[] = [
- 'id',
- 'name',
- 'lastPublishedVersionId',
- 'statuses',
- 'position',
- 'createdBySource',
- 'createdByWorkspaceMemberId',
- 'createdByName',
- 'createdByContext',
-];
-
-export const WORKFLOW_VERSION_DATA_SEED_COLUMNS: (keyof WorkflowVersionDataSeed)[] =
- ['id', 'name', 'trigger', 'steps', 'status', 'position', 'workflowId'];
-
-export const WORKFLOW_DATA_SEED_IDS = {
- ID_1: '20202020-8532-47bd-a4fe-2c1e5c4aeed3',
-};
-
-export const WORKFLOW_VERSION_DATA_SEED_IDS = {
- ID_1: '20202020-9cd5-44a8-8b2f-1160b01f06dd',
-};
-
-export const WORKFLOW_DATA_SEEDS: WorkflowDataSeed[] = [
- {
- id: WORKFLOW_DATA_SEED_IDS.ID_1,
- name: 'Quick Lead',
- lastPublishedVersionId: WORKFLOW_VERSION_DATA_SEED_IDS.ID_1,
- statuses: [WorkflowStatus.ACTIVE],
- position: 1,
- createdBySource: 'MANUAL',
- createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
- createdByName: 'Tim A',
- createdByContext: {},
- },
-];
-
-export const WORKFLOW_VERSION_DATA_SEEDS: WorkflowVersionDataSeed[] = [
- {
- id: WORKFLOW_VERSION_DATA_SEED_IDS.ID_1,
- name: 'v1',
- trigger: JSON.stringify({
- name: 'Launch manually',
- type: 'MANUAL',
- position: {
- x: 0,
- y: 0,
- },
- settings: { outputSchema: {} },
- nextStepIds: ['6e089bc9-aabd-435f-865f-f31c01c8f4a7'],
- }),
- steps: JSON.stringify([
- {
- id: '6e089bc9-aabd-435f-865f-f31c01c8f4a7',
- name: 'Quick Lead Form',
- type: 'FORM',
- valid: false,
- position: {
- x: 0,
- y: 141,
- },
- settings: {
- input: [
- {
- id: '14d669f0-5249-4fa4-b0bb-f8bd408328d5',
- name: 'firstName',
- type: 'TEXT',
- label: 'First name',
- placeholder: 'Tim',
- },
- {
- id: '4eb6ce85-d231-4aef-9837-744490c026d0',
- name: 'lastName',
- type: 'TEXT',
- label: 'Last Name',
- placeholder: 'Apple',
- },
- {
- id: 'adbf0e9f-1427-49be-b4fb-092b34d97350',
- name: 'email',
- type: 'TEXT',
- label: 'Email',
- placeholder: 'timapple@apple.com',
- },
- {
- id: '4ffc7992-9e65-4a4d-9baf-b52e62f2c273',
- name: 'jobTitle',
- type: 'TEXT',
- label: 'Job title',
- placeholder: 'CEO',
- },
- {
- id: '42f11926-04ea-4924-94a4-2293cc748362',
- name: 'companyName',
- type: 'TEXT',
- label: 'Company name',
- placeholder: 'Apple',
- },
- {
- id: 'd6ca80ee-26cd-466d-91bf-984d7205451c',
- name: 'companyDomain',
- type: 'TEXT',
- label: 'Company domain',
- placeholder: 'https://www.apple.com',
- },
- ],
- outputSchema: {
- email: {
- type: 'TEXT',
- label: 'Email',
- value: 'My text',
- isLeaf: true,
- },
- jobTitle: {
- type: 'TEXT',
- label: 'Job title',
- value: 'My text',
- isLeaf: true,
- },
- lastName: {
- type: 'TEXT',
- label: 'Last Name',
- value: 'My text',
- isLeaf: true,
- },
- firstName: {
- type: 'TEXT',
- label: 'First name',
- value: 'My text',
- isLeaf: true,
- },
- companyName: {
- type: 'TEXT',
- label: 'Company name',
- value: 'My text',
- isLeaf: true,
- },
- companyDomain: {
- type: 'TEXT',
- label: 'Company domain',
- value: 'My text',
- isLeaf: true,
- },
- },
- errorHandlingOptions: {
- retryOnFailure: { value: false },
- continueOnFailure: { value: false },
- },
- },
- __typename: 'WorkflowAction',
- nextStepIds: ['0715b6cd-7cc1-4b98-971b-00f54dfe643b'],
- },
- {
- id: '0715b6cd-7cc1-4b98-971b-00f54dfe643b',
- name: 'Create Company',
- type: 'CREATE_RECORD',
- valid: false,
- position: {
- x: 0.5,
- y: 282,
- },
- settings: {
- input: {
- objectName: 'company',
- objectRecord: {
- name: '{{6e089bc9-aabd-435f-865f-f31c01c8f4a7.companyName}}',
- domainName: {
- primaryLinkUrl:
- '{{6e089bc9-aabd-435f-865f-f31c01c8f4a7.companyDomain}}',
- primaryLinkLabel: '',
- },
- },
- },
- outputSchema: {
- fields: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconBuildingSkyscraper',
- type: 'TEXT',
- label: 'Name',
- value: 'My text',
- isLeaf: true,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- address: {
- icon: 'IconMap',
- label: 'Address',
- value: {
- addressLat: {
- type: 'NUMERIC',
- label: ' Address Lat',
- value: null,
- isLeaf: true,
- },
- addressLng: {
- type: 'NUMERIC',
- label: ' Address Lng',
- value: null,
- isLeaf: true,
- },
- addressCity: {
- type: 'TEXT',
- label: ' Address City',
- value: 'My text',
- isLeaf: true,
- },
- addressState: {
- type: 'TEXT',
- label: ' Address State',
- value: 'My text',
- isLeaf: true,
- },
- addressCountry: {
- type: 'TEXT',
- label: ' Address Country',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet1: {
- type: 'TEXT',
- label: ' Address Street1',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet2: {
- type: 'TEXT',
- label: ' Address Street2',
- value: 'My text',
- isLeaf: true,
- },
- addressPostcode: {
- type: 'TEXT',
- label: ' Address Postcode',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- employees: {
- icon: 'IconUsers',
- type: 'NUMBER',
- label: 'Employees',
- value: 20,
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- domainName: {
- icon: 'IconLink',
- label: 'Domain Name',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- accountOwner: {
- icon: 'IconUserCircle',
- label: 'Account Owner',
- value: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconCircleUser',
- label: 'Name',
- value: {
- lastName: {
- type: 'TEXT',
- label: ' Last Name',
- value: 'My text',
- isLeaf: true,
- },
- firstName: {
- type: 'TEXT',
- label: ' First Name',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- userEmail: {
- icon: 'IconMail',
- type: 'TEXT',
- label: 'User Email',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- idealCustomerProfile: {
- icon: 'IconTarget',
- type: 'BOOLEAN',
- label: 'ICP',
- value: true,
- isLeaf: true,
- },
- annualRecurringRevenue: {
- icon: 'IconMoneybag',
- label: 'ARR',
- value: {
- amountMicros: {
- type: 'NUMERIC',
- label: ' Amount Micros',
- value: null,
- isLeaf: true,
- },
- currencyCode: {
- type: 'TEXT',
- label: ' Currency Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
- object: {
- icon: 'IconBuildingSkyscraper',
- label: 'Company',
- value: 'A company',
- isLeaf: true,
- fieldIdName: 'id',
- nameSingular: 'company',
- },
- _outputSchemaType: 'RECORD',
- },
- errorHandlingOptions: {
- retryOnFailure: { value: false },
- continueOnFailure: { value: false },
- },
- },
- __typename: 'WorkflowAction',
- nextStepIds: ['6f553ea7-b00e-4371-9d88-d8298568a246'],
- },
- {
- id: '6f553ea7-b00e-4371-9d88-d8298568a246',
- name: 'Create Person',
- type: 'CREATE_RECORD',
- valid: false,
- position: {
- x: 8.5,
- y: 423,
- },
- settings: {
- input: {
- objectName: 'person',
- objectRecord: {
- name: {
- lastName: '{{6e089bc9-aabd-435f-865f-f31c01c8f4a7.lastName}}',
- firstName: '{{6e089bc9-aabd-435f-865f-f31c01c8f4a7.firstName}}',
- },
- emails: {
- primaryEmail: '{{6e089bc9-aabd-435f-865f-f31c01c8f4a7.email}}',
- additionalEmails: [],
- },
- company: {
- id: '{{0715b6cd-7cc1-4b98-971b-00f54dfe643b.id}}',
- },
- },
- },
- outputSchema: {
- fields: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- city: {
- icon: 'IconMap',
- type: 'TEXT',
- label: 'City',
- value: 'My text',
- isLeaf: true,
- },
- name: {
- icon: 'IconUser',
- label: 'Name',
- value: {
- lastName: {
- type: 'TEXT',
- label: ' Last Name',
- value: 'My text',
- isLeaf: true,
- },
- firstName: {
- type: 'TEXT',
- label: ' First Name',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- emails: {
- icon: 'IconMail',
- label: 'Emails',
- value: {
- primaryEmail: {
- type: 'TEXT',
- label: ' Primary Email',
- value: 'My text',
- isLeaf: true,
- },
- additionalEmails: {
- type: 'RAW_JSON',
- label: ' Additional Emails',
- value: null,
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- phones: {
- icon: 'IconPhone',
- label: 'Phones',
- value: {
- additionalPhones: {
- type: 'RAW_JSON',
- label: ' Additional Phones',
- value: null,
- isLeaf: true,
- },
- primaryPhoneNumber: {
- type: 'TEXT',
- label: ' Primary Phone Number',
- value: 'My text',
- isLeaf: true,
- },
- primaryPhoneCallingCode: {
- type: 'TEXT',
- label: ' Primary Phone Calling Code',
- value: 'My text',
- isLeaf: true,
- },
- primaryPhoneCountryCode: {
- type: 'TEXT',
- label: ' Primary Phone Country Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- company: {
- icon: 'IconBuildingSkyscraper',
- label: 'Company',
- value: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconBuildingSkyscraper',
- type: 'TEXT',
- label: 'Name',
- value: 'My text',
- isLeaf: true,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- address: {
- icon: 'IconMap',
- label: 'Address',
- value: {
- addressLat: {
- type: 'NUMERIC',
- label: ' Address Lat',
- value: null,
- isLeaf: true,
- },
- addressLng: {
- type: 'NUMERIC',
- label: ' Address Lng',
- value: null,
- isLeaf: true,
- },
- addressCity: {
- type: 'TEXT',
- label: ' Address City',
- value: 'My text',
- isLeaf: true,
- },
- addressState: {
- type: 'TEXT',
- label: ' Address State',
- value: 'My text',
- isLeaf: true,
- },
- addressCountry: {
- type: 'TEXT',
- label: ' Address Country',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet1: {
- type: 'TEXT',
- label: ' Address Street1',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet2: {
- type: 'TEXT',
- label: ' Address Street2',
- value: 'My text',
- isLeaf: true,
- },
- addressPostcode: {
- type: 'TEXT',
- label: ' Address Postcode',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- employees: {
- icon: 'IconUsers',
- type: 'NUMBER',
- label: 'Employees',
- value: 20,
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- domainName: {
- icon: 'IconLink',
- label: 'Domain Name',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- idealCustomerProfile: {
- icon: 'IconTarget',
- type: 'BOOLEAN',
- label: 'ICP',
- value: true,
- isLeaf: true,
- },
- annualRecurringRevenue: {
- icon: 'IconMoneybag',
- label: 'ARR',
- value: {
- amountMicros: {
- type: 'NUMERIC',
- label: ' Amount Micros',
- value: null,
- isLeaf: true,
- },
- currencyCode: {
- type: 'TEXT',
- label: ' Currency Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
- isLeaf: false,
- },
- jobTitle: {
- icon: 'IconBriefcase',
- type: 'TEXT',
- label: 'Job Title',
- value: 'My text',
- isLeaf: true,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
- object: {
- icon: 'IconUser',
- label: 'Person',
- value: 'A person',
- isLeaf: true,
- fieldIdName: 'id',
- nameSingular: 'person',
- },
- _outputSchemaType: 'RECORD',
- },
- errorHandlingOptions: {
- retryOnFailure: { value: false },
- continueOnFailure: { value: false },
- },
- },
- __typename: 'WorkflowAction',
- nextStepIds: null,
- },
- ]),
- status: WorkflowVersionStatus.ACTIVE,
- position: 1,
- workflowId: WORKFLOW_DATA_SEED_IDS.ID_1,
- },
-];
diff --git a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service.ts b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service.ts
index fc41cc102a..9e38bf37d2 100644
--- a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service.ts
@@ -81,18 +81,13 @@ import {
TASK_TARGET_DATA_SEED_COLUMNS,
TASK_TARGET_DATA_SEEDS,
} from 'src/engine/workspace-manager/dev-seeder/data/constants/task-target-data-seeds.constant';
-import {
- WORKFLOW_DATA_SEED_COLUMNS,
- WORKFLOW_DATA_SEEDS,
- WORKFLOW_VERSION_DATA_SEED_COLUMNS,
- WORKFLOW_VERSION_DATA_SEEDS,
-} from 'src/engine/workspace-manager/dev-seeder/data/constants/workflow-data-seeds.constants';
import {
WORKSPACE_MEMBER_DATA_SEED_COLUMNS,
WORKSPACE_MEMBER_DATA_SEEDS,
} from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
import { TimelineActivitySeederService } from 'src/engine/workspace-manager/dev-seeder/data/services/timeline-activity-seeder.service';
import { prefillViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-views';
+import { prefillWorkflows } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows';
import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
const RECORD_SEEDS_CONFIGS = [
@@ -176,16 +171,6 @@ const RECORD_SEEDS_CONFIGS = [
pgColumns: MESSAGE_PARTICIPANT_DATA_SEED_COLUMNS,
recordSeeds: MESSAGE_PARTICIPANT_DATA_SEEDS,
},
- {
- tableName: 'workflow',
- pgColumns: WORKFLOW_DATA_SEED_COLUMNS,
- recordSeeds: WORKFLOW_DATA_SEEDS,
- },
- {
- tableName: 'workflowVersion',
- pgColumns: WORKFLOW_VERSION_DATA_SEED_COLUMNS,
- recordSeeds: WORKFLOW_VERSION_DATA_SEEDS,
- },
{
tableName: '_pet',
pgColumns: PET_DATA_SEED_COLUMNS,
@@ -261,16 +246,14 @@ export class DevSeederDataService {
workspaceId,
});
- // For now views/favorites are auto-created for custom
- // objects but not for standard objects.
- // This is probably something we want to fix in the future.
-
const viewDefinitionsWithId = await prefillViews(
entityManager,
schemaName,
objectMetadataItems.filter((item) => !item.isCustom),
);
+ await prefillWorkflows(entityManager, schemaName, objectMetadataItems);
+
await prefillWorkspaceFavorites(
viewDefinitionsWithId
.filter(
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows.ts
index 5da79643fd..6101b9fcf7 100644
--- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows.ts
@@ -1,5 +1,10 @@
+import { isDefined } from 'twenty-shared/utils';
+
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
+import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
+import { generateObjectMetadataMaps } from 'src/engine/metadata-modules/utils/generate-object-metadata-maps.util';
import { type WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
+import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields';
const QUICK_LEAD_WORKFLOW_ID = '8b213cac-a68b-4ffe-817a-3ec994e9932d';
const QUICK_LEAD_WORKFLOW_VERSION_ID = 'ac67974f-c524-4288-9d88-af8515400b68';
@@ -7,7 +12,30 @@ const QUICK_LEAD_WORKFLOW_VERSION_ID = 'ac67974f-c524-4288-9d88-af8515400b68';
export const prefillWorkflows = async (
entityManager: WorkspaceEntityManager,
schemaName: string,
+ objectMetadataItems: ObjectMetadataEntity[],
) => {
+ const objectMetadataMaps = generateObjectMetadataMaps(objectMetadataItems);
+ const companyObjectMetadataId =
+ objectMetadataMaps.idByNameSingular['company'];
+
+ const personObjectMetadataId = objectMetadataMaps.idByNameSingular['person'];
+
+ if (
+ !isDefined(companyObjectMetadataId) ||
+ !isDefined(personObjectMetadataId)
+ ) {
+ throw new Error('Company or person object metadata not found');
+ }
+
+ const companyObjectMetadata =
+ objectMetadataMaps.byId[companyObjectMetadataId];
+
+ const personObjectMetadata = objectMetadataMaps.byId[personObjectMetadataId];
+
+ if (!isDefined(companyObjectMetadata) || !isDefined(personObjectMetadata)) {
+ throw new Error('Company or person object metadata not found');
+ }
+
await entityManager
.createQueryBuilder(undefined, undefined, undefined, {
shouldBypassPermissionChecks: true,
@@ -181,298 +209,6 @@ export const prefillWorkflows = async (
},
},
outputSchema: {
- fields: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconBuildingSkyscraper',
- type: 'TEXT',
- label: 'Name',
- value: 'My text',
- isLeaf: true,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- address: {
- icon: 'IconMap',
- label: 'Address',
- value: {
- addressLat: {
- type: 'NUMERIC',
- label: ' Address Lat',
- value: null,
- isLeaf: true,
- },
- addressLng: {
- type: 'NUMERIC',
- label: ' Address Lng',
- value: null,
- isLeaf: true,
- },
- addressCity: {
- type: 'TEXT',
- label: ' Address City',
- value: 'My text',
- isLeaf: true,
- },
- addressState: {
- type: 'TEXT',
- label: ' Address State',
- value: 'My text',
- isLeaf: true,
- },
- addressCountry: {
- type: 'TEXT',
- label: ' Address Country',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet1: {
- type: 'TEXT',
- label: ' Address Street1',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet2: {
- type: 'TEXT',
- label: ' Address Street2',
- value: 'My text',
- isLeaf: true,
- },
- addressPostcode: {
- type: 'TEXT',
- label: ' Address Postcode',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- employees: {
- icon: 'IconUsers',
- type: 'NUMBER',
- label: 'Employees',
- value: 20,
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- domainName: {
- icon: 'IconLink',
- label: 'Domain Name',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- accountOwner: {
- icon: 'IconUserCircle',
- label: 'Account Owner',
- value: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconCircleUser',
- label: 'Name',
- value: {
- lastName: {
- type: 'TEXT',
- label: ' Last Name',
- value: 'My text',
- isLeaf: true,
- },
- firstName: {
- type: 'TEXT',
- label: ' First Name',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- userEmail: {
- icon: 'IconMail',
- type: 'TEXT',
- label: 'User Email',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- idealCustomerProfile: {
- icon: 'IconTarget',
- type: 'BOOLEAN',
- label: 'ICP',
- value: true,
- isLeaf: true,
- },
- annualRecurringRevenue: {
- icon: 'IconMoneybag',
- label: 'ARR',
- value: {
- amountMicros: {
- type: 'NUMERIC',
- label: ' Amount Micros',
- value: null,
- isLeaf: true,
- },
- currencyCode: {
- type: 'TEXT',
- label: ' Currency Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
object: {
icon: 'IconBuildingSkyscraper',
label: 'Company',
@@ -482,6 +218,13 @@ export const prefillWorkflows = async (
nameSingular: 'company',
},
_outputSchemaType: 'RECORD',
+ fields: generateObjectRecordFields({
+ objectMetadataInfo: {
+ objectMetadataItemWithFieldsMaps: companyObjectMetadata,
+ objectMetadataMaps,
+ },
+ depth: 0,
+ }),
},
errorHandlingOptions: {
retryOnFailure: { value: false },
@@ -517,445 +260,13 @@ export const prefillWorkflows = async (
},
},
outputSchema: {
- fields: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
+ fields: generateObjectRecordFields({
+ objectMetadataInfo: {
+ objectMetadataItemWithFieldsMaps: personObjectMetadata,
+ objectMetadataMaps,
},
- city: {
- icon: 'IconMap',
- type: 'TEXT',
- label: 'City',
- value: 'My text',
- isLeaf: true,
- },
- name: {
- icon: 'IconUser',
- label: 'Name',
- value: {
- lastName: {
- type: 'TEXT',
- label: ' Last Name',
- value: 'My text',
- isLeaf: true,
- },
- firstName: {
- type: 'TEXT',
- label: ' First Name',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- emails: {
- icon: 'IconMail',
- label: 'Emails',
- value: {
- primaryEmail: {
- type: 'TEXT',
- label: ' Primary Email',
- value: 'My text',
- isLeaf: true,
- },
- additionalEmails: {
- type: 'RAW_JSON',
- label: ' Additional Emails',
- value: null,
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- phones: {
- icon: 'IconPhone',
- label: 'Phones',
- value: {
- additionalPhones: {
- type: 'RAW_JSON',
- label: ' Additional Phones',
- value: null,
- isLeaf: true,
- },
- primaryPhoneNumber: {
- type: 'TEXT',
- label: ' Primary Phone Number',
- value: 'My text',
- isLeaf: true,
- },
- primaryPhoneCallingCode: {
- type: 'TEXT',
- label: ' Primary Phone Calling Code',
- value: 'My text',
- isLeaf: true,
- },
- primaryPhoneCountryCode: {
- type: 'TEXT',
- label: ' Primary Phone Country Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- company: {
- icon: 'IconBuildingSkyscraper',
- label: 'Company',
- value: {
- id: {
- icon: 'Icon123',
- type: 'UUID',
- label: 'Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- name: {
- icon: 'IconBuildingSkyscraper',
- type: 'TEXT',
- label: 'Name',
- value: 'My text',
- isLeaf: true,
- },
- xLink: {
- icon: 'IconBrandX',
- label: 'X',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- address: {
- icon: 'IconMap',
- label: 'Address',
- value: {
- addressLat: {
- type: 'NUMERIC',
- label: ' Address Lat',
- value: null,
- isLeaf: true,
- },
- addressLng: {
- type: 'NUMERIC',
- label: ' Address Lng',
- value: null,
- isLeaf: true,
- },
- addressCity: {
- type: 'TEXT',
- label: ' Address City',
- value: 'My text',
- isLeaf: true,
- },
- addressState: {
- type: 'TEXT',
- label: ' Address State',
- value: 'My text',
- isLeaf: true,
- },
- addressCountry: {
- type: 'TEXT',
- label: ' Address Country',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet1: {
- type: 'TEXT',
- label: ' Address Street1',
- value: 'My text',
- isLeaf: true,
- },
- addressStreet2: {
- type: 'TEXT',
- label: ' Address Street2',
- value: 'My text',
- isLeaf: true,
- },
- addressPostcode: {
- type: 'TEXT',
- label: ' Address Postcode',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- employees: {
- icon: 'IconUsers',
- type: 'NUMBER',
- label: 'Employees',
- value: 20,
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- domainName: {
- icon: 'IconLink',
- label: 'Domain Name',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- idealCustomerProfile: {
- icon: 'IconTarget',
- type: 'BOOLEAN',
- label: 'ICP',
- value: true,
- isLeaf: true,
- },
- annualRecurringRevenue: {
- icon: 'IconMoneybag',
- label: 'ARR',
- value: {
- amountMicros: {
- type: 'NUMERIC',
- label: ' Amount Micros',
- value: null,
- isLeaf: true,
- },
- currencyCode: {
- type: 'TEXT',
- label: ' Currency Code',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
- isLeaf: false,
- },
- jobTitle: {
- icon: 'IconBriefcase',
- type: 'TEXT',
- label: 'Job Title',
- value: 'My text',
- isLeaf: true,
- },
- createdAt: {
- icon: 'IconCalendar',
- type: 'DATE_TIME',
- label: 'Creation date',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- createdBy: {
- icon: 'IconCreativeCommonsSa',
- label: 'Created by',
- value: {
- name: {
- type: 'TEXT',
- label: ' Name',
- value: 'My text',
- isLeaf: true,
- },
- source: {
- type: 'SELECT',
- label: ' Source',
- value: null,
- isLeaf: true,
- },
- context: {
- type: 'RAW_JSON',
- label: ' Context',
- value: null,
- isLeaf: true,
- },
- workspaceMemberId: {
- type: 'UUID',
- label: ' Workspace Member Id',
- value: '123e4567-e89b-12d3-a456-426614174000',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- deletedAt: {
- icon: 'IconCalendarMinus',
- type: 'DATE_TIME',
- label: 'Deleted at',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- updatedAt: {
- icon: 'IconCalendarClock',
- type: 'DATE_TIME',
- label: 'Last update',
- value: '01/23/2025 15:16',
- isLeaf: true,
- },
- linkedinLink: {
- icon: 'IconBrandLinkedin',
- label: 'Linkedin',
- value: {
- primaryLinkUrl: {
- type: 'TEXT',
- label: ' Primary Link Url',
- value: 'My text',
- isLeaf: true,
- },
- secondaryLinks: {
- type: 'RAW_JSON',
- label: ' Secondary Links',
- value: null,
- isLeaf: true,
- },
- primaryLinkLabel: {
- type: 'TEXT',
- label: ' Primary Link Label',
- value: 'My text',
- isLeaf: true,
- },
- },
- isLeaf: false,
- },
- },
- object: {
- icon: 'IconUser',
- label: 'Person',
- value: 'A person',
- isLeaf: true,
- fieldIdName: 'id',
- nameSingular: 'person',
- },
- _outputSchemaType: 'RECORD',
+ depth: 0,
+ }),
},
errorHandlingOptions: {
retryOnFailure: { value: false },
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts
index 43e8573fed..312f595931 100644
--- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts
@@ -6,8 +6,8 @@ import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-worksp
import { prefillCompanies } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-companies';
import { prefillPeople } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-people';
import { prefillViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-views';
-import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
import { prefillWorkflows } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workflows';
+import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
export const standardObjectsPrefillData = async (
mainDataSource: DataSource,
@@ -19,7 +19,7 @@ export const standardObjectsPrefillData = async (
await prefillPeople(entityManager, schemaName);
- await prefillWorkflows(entityManager, schemaName);
+ await prefillWorkflows(entityManager, schemaName, objectMetadataItems);
const viewDefinitionsWithId = await prefillViews(
entityManager,
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts
index 0f1f728179..e614b4c5a9 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type.ts
@@ -31,7 +31,7 @@ export type BaseOutputSchema = Record;
export type FieldOutputSchema =
| ((Leaf | Node) & {
- fieldMetadataId?: string;
+ fieldMetadataId: string;
})
| RecordOutputSchema;
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts
index f8505604fc..3785f60fab 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-form-response.spec.ts
@@ -10,7 +10,7 @@ const companyMockObjectMetadataItem = mockObjectMetadataItemsWithFieldMaps.find(
describe('generateFakeFormResponse', () => {
it('should generate fake responses for a form schema', async () => {
- const schema: FormFieldMetadata[] = [
+ const formFieldMetadataItems: FormFieldMetadata[] = [
{
id: '96939213-49ac-4dee-949d-56e6c7be98e6',
name: 'name',
@@ -51,8 +51,8 @@ describe('generateFakeFormResponse', () => {
},
};
- const result = await generateFakeFormResponse({
- formMetadata: schema,
+ const result = generateFakeFormResponse({
+ formFieldMetadataItems,
objectMetadataMaps: mockObjectMetadataMaps,
});
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-field.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-record-field.spec.ts
similarity index 93%
rename from packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-field.spec.ts
rename to packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-record-field.spec.ts
index c153b21f0d..4f4b247257 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-field.spec.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-fake-record-field.spec.ts
@@ -1,7 +1,7 @@
import { FieldMetadataType } from 'twenty-shared/types';
import * as generateFakeValueModule from 'src/engine/utils/generate-fake-value';
-import { generateFakeField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field';
+import { generateFakeRecordField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field';
import * as camelToTitleCaseModule from 'src/utils/camel-to-title-case';
jest.mock('src/engine/utils/generate-fake-value');
@@ -52,7 +52,7 @@ describe('generateFakeField', () => {
it('should generate a leaf node for TEXT type', () => {
generateFakeValueSpy.mockReturnValueOnce('Fake Text');
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.TEXT,
label: 'Text Field',
fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
@@ -74,7 +74,7 @@ describe('generateFakeField', () => {
});
it('should handle custom value', () => {
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.TEXT,
label: 'Text Field',
value: 'Test value',
@@ -96,7 +96,7 @@ describe('generateFakeField', () => {
it('should generate a leaf node for NUMBER type with icon', () => {
generateFakeValueSpy.mockReturnValueOnce(42);
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.NUMBER,
label: 'Number Field',
icon: 'IconNumber',
@@ -118,7 +118,7 @@ describe('generateFakeField', () => {
generateFakeValueSpy.mockReturnValueOnce(fakeDate);
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.DATE,
label: 'Date Field',
fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
@@ -145,7 +145,7 @@ describe('generateFakeField', () => {
.mockReturnValueOnce('Label')
.mockReturnValueOnce('Url');
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.LINKS,
label: 'Links Field',
fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
@@ -189,7 +189,7 @@ describe('generateFakeField', () => {
.mockReturnValueOnce('Amount')
.mockReturnValueOnce('Currency Code');
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.CURRENCY,
label: 'Currency Field',
icon: 'IconCurrency',
@@ -230,7 +230,7 @@ describe('generateFakeField', () => {
generateFakeValueSpy.mockReturnValueOnce('Unknown Value');
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: unknownType,
label: 'Unknown Field',
fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
@@ -249,7 +249,7 @@ describe('generateFakeField', () => {
it('should handle empty label', () => {
generateFakeValueSpy.mockReturnValueOnce('Fake Boolean');
- const result = generateFakeField({
+ const result = generateFakeRecordField({
type: FieldMetadataType.BOOLEAN,
label: '',
fieldMetadataId: '123e4567-e89b-12d3-a456-426614174000',
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-object-record-fields.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-object-record-fields.spec.ts
index 1449d871ad..7c4261bfba 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-object-record-fields.spec.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/__tests__/generate-object-record-fields.spec.ts
@@ -1,12 +1,12 @@
import { FieldMetadataType } from 'twenty-shared/types';
-import { generateFakeField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field';
+import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps';
+import { generateFakeRecordField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field';
import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields';
import { shouldGenerateFieldFakeValue } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/should-generate-field-fake-value';
-import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps';
jest.mock(
- 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field',
+ 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field',
);
jest.mock(
'src/modules/workflow/workflow-builder/workflow-schema/utils/should-generate-field-fake-value',
@@ -42,7 +42,7 @@ describe('generateObjectRecordFields', () => {
(field) => field.type !== FieldMetadataType.RELATION,
);
- (generateFakeField as jest.Mock).mockImplementation(
+ (generateFakeRecordField as jest.Mock).mockImplementation(
({ type, label, icon }) => ({
type,
label,
@@ -69,7 +69,7 @@ describe('generateObjectRecordFields', () => {
});
expect(shouldGenerateFieldFakeValue).toHaveBeenCalledTimes(2);
- expect(generateFakeField).toHaveBeenCalledTimes(2);
+ expect(generateFakeRecordField).toHaveBeenCalledTimes(2);
});
it('should return empty object when no valid fields', () => {
@@ -79,6 +79,6 @@ describe('generateObjectRecordFields', () => {
expect(result).toEqual({});
expect(shouldGenerateFieldFakeValue).toHaveBeenCalledTimes(2);
- expect(generateFakeField).not.toHaveBeenCalled();
+ expect(generateFakeRecordField).not.toHaveBeenCalled();
});
});
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-field.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-field.ts
new file mode 100644
index 0000000000..a6dad16650
--- /dev/null
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-field.ts
@@ -0,0 +1,26 @@
+import { type FieldMetadataType } from 'twenty-shared/types';
+
+import { generateFakeValue } from 'src/engine/utils/generate-fake-value';
+import {
+ type Leaf,
+ type Node,
+} from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
+
+type GenerateFakeFormFieldArgs = {
+ type: FieldMetadataType;
+ label: string;
+ value?: string;
+};
+
+export const generateFakeFormField = ({
+ type,
+ label,
+ value,
+}: GenerateFakeFormFieldArgs): Leaf | Node => {
+ return {
+ isLeaf: true,
+ type: type,
+ label: label,
+ value: value ?? generateFakeValue(type, 'FieldMetadataType'),
+ };
+};
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-response.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-response.ts
index f9a70ef8c0..c5657ebd9c 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-response.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-response.ts
@@ -6,59 +6,59 @@ import {
type Leaf,
type Node,
} from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
-import { generateFakeField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field';
+import { generateFakeFormField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-field';
import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record';
import { type FormFieldMetadata } from 'src/modules/workflow/workflow-executor/workflow-actions/form/types/workflow-form-action-settings.type';
-export const generateFakeFormResponse = async ({
- formMetadata,
- objectMetadataMaps,
-}: {
- formMetadata: FormFieldMetadata[];
+type GenerateFakeFormResponseArgs = {
+ formFieldMetadataItems: FormFieldMetadata[];
objectMetadataMaps: ObjectMetadataMaps;
-}): Promise> => {
- const result = await Promise.all(
- formMetadata.map(async (formFieldMetadata) => {
- if (formFieldMetadata.type === 'RECORD') {
- if (!formFieldMetadata?.settings?.objectName) {
- return undefined;
- }
+};
- const objectMetadataItemWithFieldsMaps =
- getObjectMetadataMapItemByNameSingular(
- objectMetadataMaps,
- formFieldMetadata?.settings?.objectName,
- );
-
- if (!isDefined(objectMetadataItemWithFieldsMaps)) {
- throw new Error(
- `Object metadata not found for object name ${formFieldMetadata?.settings?.objectName}`,
- );
- }
-
- return {
- [formFieldMetadata.name]: {
- isLeaf: false,
- label: formFieldMetadata.label,
- value: generateFakeObjectRecord({
- objectMetadataInfo: {
- objectMetadataItemWithFieldsMaps,
- objectMetadataMaps,
- },
- }),
- },
- };
- } else {
- return {
- [formFieldMetadata.name]: generateFakeField({
- type: formFieldMetadata.type,
- label: formFieldMetadata.label,
- value: formFieldMetadata.placeholder,
- }),
- };
+export const generateFakeFormResponse = ({
+ formFieldMetadataItems,
+ objectMetadataMaps,
+}: GenerateFakeFormResponseArgs): Record => {
+ const result = formFieldMetadataItems.map((formFieldMetadata) => {
+ if (formFieldMetadata.type === 'RECORD') {
+ if (!formFieldMetadata?.settings?.objectName) {
+ return undefined;
}
- }),
- );
+
+ const objectMetadataItemWithFieldsMaps =
+ getObjectMetadataMapItemByNameSingular(
+ objectMetadataMaps,
+ formFieldMetadata?.settings?.objectName,
+ );
+
+ if (!isDefined(objectMetadataItemWithFieldsMaps)) {
+ throw new Error(
+ `Object metadata not found for object name ${formFieldMetadata?.settings?.objectName}`,
+ );
+ }
+
+ return {
+ [formFieldMetadata.name]: {
+ isLeaf: false,
+ label: formFieldMetadata.label,
+ value: generateFakeObjectRecord({
+ objectMetadataInfo: {
+ objectMetadataItemWithFieldsMaps,
+ objectMetadataMaps,
+ },
+ }),
+ },
+ };
+ } else {
+ return {
+ [formFieldMetadata.name]: generateFakeFormField({
+ type: formFieldMetadata.type,
+ label: formFieldMetadata.label,
+ value: formFieldMetadata.placeholder,
+ }),
+ };
+ }
+ });
return result.filter(isDefined).reduce(
(acc, curr) => {
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field.ts
similarity index 87%
rename from packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field.ts
rename to packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field.ts
index 51c3b77062..f61caa63dd 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field.ts
@@ -8,19 +8,23 @@ import {
} from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
-export const generateFakeField = ({
+type GenerateFakeRecordFieldArgs = {
+ type: FieldMetadataType;
+ label: string;
+ fieldMetadataId: string;
+ icon?: string;
+ value?: string;
+};
+
+export const generateFakeRecordField = ({
type,
label,
icon,
value,
fieldMetadataId,
-}: {
- type: FieldMetadataType;
- label: string;
- fieldMetadataId?: string;
- icon?: string;
- value?: string;
-}): (Leaf | Node) & { fieldMetadataId?: string } => {
+}: GenerateFakeRecordFieldArgs): (Leaf | Node) & {
+ fieldMetadataId: string;
+} => {
const compositeType = compositeTypeDefinitions.get(type);
if (compositeType) {
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts
index 7034b4ab20..69c9959d43 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields.ts
@@ -3,8 +3,8 @@ import { isDefined } from 'twenty-shared/utils';
import { type ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { type FieldOutputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
-import { generateFakeField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-field';
import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record';
+import { generateFakeRecordField } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-record-field';
import { shouldGenerateFieldFakeValue } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/should-generate-field-fake-value';
const MAXIMUM_DEPTH = 1;
@@ -25,7 +25,7 @@ export const generateObjectRecordFields = ({
}
if (field.type !== FieldMetadataType.RELATION) {
- acc[field.name] = generateFakeField({
+ acc[field.name] = generateFakeRecordField({
type: field.type,
label: field.label,
icon: field.icon ?? undefined,
diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service.ts
index ab6f9a9561..74103d9455 100644
--- a/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service.ts
+++ b/packages/twenty-server/src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service.ts
@@ -73,7 +73,7 @@ export class WorkflowSchemaWorkspaceService {
});
case WorkflowActionType.FORM:
return this.computeFormActionOutputSchema({
- formMetadata: step.settings.input,
+ formFieldMetadataItems: step.settings.input,
workspaceId,
});
case WorkflowActionType.CODE: // StepOutput schema is computed on serverlessFunction draft execution
@@ -156,10 +156,10 @@ export class WorkflowSchemaWorkspaceService {
}
private async computeFormActionOutputSchema({
- formMetadata,
+ formFieldMetadataItems,
workspaceId,
}: {
- formMetadata: FormFieldMetadata[];
+ formFieldMetadataItems: FormFieldMetadata[];
workspaceId: string;
}): Promise {
const objectMetadataMaps =
@@ -168,7 +168,7 @@ export class WorkflowSchemaWorkspaceService {
);
return generateFakeFormResponse({
- formMetadata,
+ formFieldMetadataItems,
objectMetadataMaps,
});
}