Variables not coming from a Record step should be available in Record Picker (#12708)

We want code and webhook variables available in Record Picker since
those can contains uuid.

This PR:
- update `WorkflowVariablesDropdownObjectItems.tsx` so it manages fields
properly
- factorise both dropdown into a commun hook
- update filterOutputSchema.ts so it does not filter fields that are not
FieldMetadata types
- set relation fields as record object in variable schema so those can
be selected as full record

Before


https://github.com/user-attachments/assets/f4f85402-c056-4fd8-8474-d86bef9d4bc3

After


https://github.com/user-attachments/assets/c6589e18-7dfa-4fc8-a525-3a580e265896
This commit is contained in:
Thomas Trompette
2025-06-19 11:33:21 +02:00
committed by GitHub
parent c16b625752
commit 07cf1ed71d
16 changed files with 229 additions and 159 deletions

View File

@ -11,6 +11,7 @@ export type Leaf = {
export type Node = {
isLeaf: false;
type?: InputSchemaPropertyType;
icon?: string;
label?: string;
value: OutputSchema;

View File

@ -128,6 +128,7 @@ describe('generateFakeField', () => {
isLeaf: false,
icon: undefined,
label: 'Links Field',
type: FieldMetadataType.LINKS,
value: {
label: {
isLeaf: true,
@ -166,6 +167,7 @@ describe('generateFakeField', () => {
isLeaf: false,
icon: 'IconCurrency',
label: 'Currency Field',
type: FieldMetadataType.CURRENCY,
value: {
amount: {
isLeaf: true,

View File

@ -1,6 +1,6 @@
import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps';
import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record';
import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields';
import { mockObjectMetadataItemsWithFieldMaps } from 'src/engine/core-modules/__mocks__/mockObjectMetadataItemsWithFieldMaps';
jest.mock(
'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields',
@ -33,7 +33,7 @@ const objectMetadataInfo = {
describe('generateFakeObjectRecord', () => {
it('should generate a record with correct object metadata', () => {
const result = generateFakeObjectRecord(objectMetadataInfo);
const result = generateFakeObjectRecord({ objectMetadataInfo });
expect(result).toEqual({
object: {
@ -53,10 +53,11 @@ describe('generateFakeObjectRecord', () => {
});
it('should call generateObjectRecordFields with the object metadata', () => {
generateFakeObjectRecord(objectMetadataInfo);
generateFakeObjectRecord({ objectMetadataInfo });
expect(generateObjectRecordFields).toHaveBeenCalledWith({
objectMetadataInfo,
depth: 0,
});
});
});

View File

@ -22,6 +22,7 @@ export const generateFakeField = ({
if (compositeType) {
return {
isLeaf: false,
type: type,
icon: icon,
label: label,
value: compositeType.properties.reduce((acc, property) => {

View File

@ -1,5 +1,7 @@
import { isDefined } from 'twenty-shared/utils';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
import {
Leaf,
Node,
@ -7,8 +9,6 @@ import {
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 { FormFieldMetadata } from 'src/modules/workflow/workflow-executor/workflow-actions/form/types/workflow-form-action-settings.type';
import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
export const generateFakeFormResponse = async ({
formMetadata,
@ -40,8 +40,10 @@ export const generateFakeFormResponse = async ({
isLeaf: false,
label: formFieldMetadata.label,
value: generateFakeObjectRecord({
objectMetadataMaps,
objectMetadataItemWithFieldsMaps,
objectMetadataInfo: {
objectMetadataItemWithFieldsMaps,
objectMetadataMaps,
},
}),
},
};

View File

@ -1,10 +1,14 @@
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { RecordOutputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
import { generateObjectRecordFields } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-object-record-fields';
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
export const generateFakeObjectRecord = (
objectMetadataInfo: ObjectMetadataInfo,
): RecordOutputSchema => {
export const generateFakeObjectRecord = ({
objectMetadataInfo,
depth = 0,
}: {
objectMetadataInfo: ObjectMetadataInfo;
depth?: number;
}): RecordOutputSchema => {
return {
object: {
isLeaf: true,
@ -15,7 +19,10 @@ export const generateFakeObjectRecord = (
objectMetadataInfo.objectMetadataItemWithFieldsMaps.nameSingular,
fieldIdName: 'id',
},
fields: generateObjectRecordFields({ objectMetadataInfo }),
fields: generateObjectRecordFields({
objectMetadataInfo,
depth,
}),
_outputSchemaType: 'RECORD',
};
};

View File

@ -1,10 +1,11 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { BaseOutputSchema } 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 { shouldGenerateFieldFakeValue } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/should-generate-field-fake-value';
import { ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
const MAXIMUM_DEPTH = 1;
@ -45,7 +46,7 @@ export const generateObjectRecordFields = ({
isLeaf: false,
icon: field.icon,
label: field.label,
value: generateObjectRecordFields({
value: generateFakeObjectRecord({
objectMetadataInfo: {
objectMetadataItemWithFieldsMaps: relationTargetObjectMetadata,
objectMetadataMaps: objectMetadataInfo.objectMetadataMaps,

View File

@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common';
import { DatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/enums/database-event-action';
import { checkStringIsDatabaseEventAction } from 'src/engine/api/graphql/graphql-query-runner/utils/check-string-is-database-event-action';
import { generateFakeValue } from 'src/engine/utils/generate-fake-value';
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { OutputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/output-schema.type';
import { generateFakeFormResponse } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-form-response';
import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/workflow-schema/utils/generate-fake-object-record';
@ -16,7 +17,6 @@ import {
WorkflowTrigger,
WorkflowTriggerType,
} from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
@Injectable()
export class WorkflowSchemaWorkspaceService {
@ -148,7 +148,7 @@ export class WorkflowSchemaWorkspaceService {
workspaceId,
);
return generateFakeObjectRecord(objectMetadataInfo);
return generateFakeObjectRecord({ objectMetadataInfo });
}
private computeSendEmailActionOutputSchema(): OutputSchema {