Filter dropdown by types (#13703)
Allow to filter types in variable dropdown. This will avoid unsupported types for filters (RICH_TEXT, ACTOR) <img width="579" height="505" alt="Capture d’écran 2025-08-07 à 09 58 42" src="https://github.com/user-attachments/assets/c3fbeb3f-61ab-4c2c-bb2c-6f2c6292ef9e" />
This commit is contained in:
+7
@@ -15,11 +15,17 @@ import { useContext } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { StepFilter } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
type WorkflowStepFilterFieldSelectProps = {
|
||||
stepFilter: StepFilter;
|
||||
};
|
||||
|
||||
const NON_SELECTABLE_FIELD_TYPES = [
|
||||
FieldMetadataType.ACTOR,
|
||||
FieldMetadataType.RICH_TEXT_V2,
|
||||
];
|
||||
|
||||
export const WorkflowStepFilterFieldSelect = ({
|
||||
stepFilter,
|
||||
}: WorkflowStepFilterFieldSelectProps) => {
|
||||
@@ -163,6 +169,7 @@ export const WorkflowStepFilterFieldSelect = ({
|
||||
shouldDisplayRecordFields={shouldDisplayRecordFields}
|
||||
shouldDisplayRecordObjects={shouldDisplayRecordObjects}
|
||||
shouldEnableSelectRelationObject={true}
|
||||
fieldTypesToExclude={NON_SELECTABLE_FIELD_TYPES}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+4
@@ -3,6 +3,7 @@ import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/S
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { InputSchemaPropertyType } from '@/workflow/types/InputSchema';
|
||||
import { WorkflowVariablesDropdownAllItems } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownAllItems';
|
||||
import { WorkflowVariablesDropdownFieldItems } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems';
|
||||
import { WorkflowVariablesDropdownWorkflowStepItems } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownWorkflowStepItems';
|
||||
@@ -37,6 +38,7 @@ export const WorkflowVariablesDropdown = ({
|
||||
disabled,
|
||||
shouldDisplayRecordFields,
|
||||
shouldDisplayRecordObjects,
|
||||
fieldTypesToExclude,
|
||||
shouldEnableSelectRelationObject,
|
||||
multiline,
|
||||
clickableComponent,
|
||||
@@ -45,6 +47,7 @@ export const WorkflowVariablesDropdown = ({
|
||||
onVariableSelect: (variableName: string) => void;
|
||||
shouldDisplayRecordFields: boolean;
|
||||
shouldDisplayRecordObjects: boolean;
|
||||
fieldTypesToExclude?: InputSchemaPropertyType[];
|
||||
shouldEnableSelectRelationObject?: boolean;
|
||||
disabled?: boolean;
|
||||
multiline?: boolean;
|
||||
@@ -61,6 +64,7 @@ export const WorkflowVariablesDropdown = ({
|
||||
const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({
|
||||
shouldDisplayRecordFields,
|
||||
shouldDisplayRecordObjects,
|
||||
fieldTypesToExclude,
|
||||
});
|
||||
|
||||
const noAvailableVariables = availableVariablesInWorkflowStep.length === 0;
|
||||
|
||||
+4
@@ -1,5 +1,6 @@
|
||||
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
|
||||
import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector';
|
||||
import { InputSchemaPropertyType } from '@/workflow/types/InputSchema';
|
||||
import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow';
|
||||
import { getPreviousSteps } from '@/workflow/workflow-steps/utils/getWorkflowPreviousSteps';
|
||||
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
|
||||
@@ -15,9 +16,11 @@ import { isEmptyObject } from '~/utils/isEmptyObject';
|
||||
export const useAvailableVariablesInWorkflowStep = ({
|
||||
shouldDisplayRecordFields,
|
||||
shouldDisplayRecordObjects,
|
||||
fieldTypesToExclude,
|
||||
}: {
|
||||
shouldDisplayRecordFields: boolean;
|
||||
shouldDisplayRecordObjects: boolean;
|
||||
fieldTypesToExclude?: InputSchemaPropertyType[];
|
||||
}): StepOutputSchema[] => {
|
||||
const workflowSelectedNode = useWorkflowSelectedNodeOrThrow();
|
||||
const flow = useFlowOrThrow();
|
||||
@@ -41,6 +44,7 @@ export const useAvailableVariablesInWorkflowStep = ({
|
||||
shouldDisplayRecordFields,
|
||||
shouldDisplayRecordObjects,
|
||||
outputSchema: stepOutputSchema.outputSchema,
|
||||
fieldTypesToExclude,
|
||||
}) as OutputSchema;
|
||||
|
||||
if (!isDefined(outputSchema) || isEmptyObject(outputSchema)) {
|
||||
|
||||
+40
@@ -225,4 +225,44 @@ describe('filterOutputSchema', () => {
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fieldTypesToExclude', () => {
|
||||
it('should filter out the types', () => {
|
||||
const inputSchema = createRecordSchema('person', {
|
||||
name: { isLeaf: true, type: undefined, value: 'toto' },
|
||||
age: { isLeaf: true, type: FieldMetadataType.NUMBER },
|
||||
id: { isLeaf: true, type: FieldMetadataType.UUID },
|
||||
});
|
||||
|
||||
const expectedSchema = createRecordSchema('person', {
|
||||
name: { isLeaf: true, type: undefined, value: 'toto' },
|
||||
age: { isLeaf: true, type: FieldMetadataType.NUMBER },
|
||||
});
|
||||
|
||||
expect(
|
||||
filterOutputSchema({
|
||||
shouldDisplayRecordFields: true,
|
||||
shouldDisplayRecordObjects: false,
|
||||
outputSchema: inputSchema,
|
||||
fieldTypesToExclude: [FieldMetadataType.UUID],
|
||||
}),
|
||||
).toEqual(expectedSchema);
|
||||
});
|
||||
|
||||
it('should return the same schema if no types to filter', () => {
|
||||
const inputSchema = createRecordSchema('person', {
|
||||
name: { isLeaf: true, value: 'string' },
|
||||
id: { isLeaf: true, type: FieldMetadataType.UUID },
|
||||
});
|
||||
|
||||
expect(
|
||||
filterOutputSchema({
|
||||
shouldDisplayRecordFields: true,
|
||||
shouldDisplayRecordObjects: false,
|
||||
outputSchema: inputSchema,
|
||||
fieldTypesToExclude: [],
|
||||
}),
|
||||
).toEqual(inputSchema);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+41
-5
@@ -1,3 +1,4 @@
|
||||
import { InputSchemaPropertyType } from '@/workflow/types/InputSchema';
|
||||
import {
|
||||
BaseOutputSchema,
|
||||
OutputSchema,
|
||||
@@ -128,20 +129,55 @@ const filterBaseOutputSchema = ({
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const filterRecordOutputSchemaFieldsByType = ({
|
||||
outputSchema,
|
||||
fieldTypesToExclude,
|
||||
}: {
|
||||
outputSchema: RecordOutputSchema;
|
||||
fieldTypesToExclude: InputSchemaPropertyType[];
|
||||
}) => {
|
||||
const filteredFields: BaseOutputSchema = {};
|
||||
|
||||
for (const key in outputSchema.fields) {
|
||||
const field = outputSchema.fields[key];
|
||||
|
||||
if (isDefined(field.type) && fieldTypesToExclude.includes(field.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredFields[key] = field;
|
||||
}
|
||||
|
||||
return {
|
||||
...outputSchema,
|
||||
// Relations could be filtered recursively but this util requires a global simplification first
|
||||
fields: filteredFields,
|
||||
};
|
||||
};
|
||||
|
||||
export const filterOutputSchema = ({
|
||||
shouldDisplayRecordFields,
|
||||
shouldDisplayRecordObjects,
|
||||
outputSchema,
|
||||
fieldTypesToExclude,
|
||||
}: {
|
||||
shouldDisplayRecordFields: boolean;
|
||||
shouldDisplayRecordObjects: boolean;
|
||||
outputSchema?: OutputSchema;
|
||||
fieldTypesToExclude?: InputSchemaPropertyType[];
|
||||
}): OutputSchema | undefined => {
|
||||
if (
|
||||
!shouldDisplayRecordObjects ||
|
||||
shouldDisplayRecordFields ||
|
||||
!outputSchema
|
||||
) {
|
||||
if (!isDefined(outputSchema)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!shouldDisplayRecordObjects || shouldDisplayRecordFields) {
|
||||
if (isRecordOutputSchema(outputSchema) && isDefined(fieldTypesToExclude)) {
|
||||
return filterRecordOutputSchemaFieldsByType({
|
||||
outputSchema,
|
||||
fieldTypesToExclude,
|
||||
});
|
||||
}
|
||||
|
||||
return outputSchema;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user