Add empty operands to UUID filter type in workflow filter action (#20821)
## Summary - Adds `IS_EMPTY` and `IS_NOT_EMPTY` operands to the UUID entry in `getStepFilterOperands`, aligning the workflow filter action with the find records (search) action which already includes these operands for ID-type fields. ## Test plan - [ ] Open a workflow with a filter action, select an ID-type field, and verify the operand dropdown now includes "Is empty" and "Is not empty" - [ ] Open a workflow with a find records action, select an ID-type field, and verify the operand dropdown is consistent with the filter action --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+30
@@ -484,6 +484,18 @@ describe('turnRecordFilterIntoRecordGqlOperationFilter', () => {
|
||||
|
||||
expect(result).toHaveProperty('rating.in');
|
||||
});
|
||||
|
||||
it('should handle IS_NOT operand as wrapped eq', () => {
|
||||
const result = turnRecordFilterIntoRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
recordFilter: makeFilter('f-rating', RecordFilterOperand.IS_NOT, '3'),
|
||||
fieldMetadataItemById,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
not: { rating: { eq: 'RATING_3' } },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('BOOLEAN filter', () => {
|
||||
@@ -920,6 +932,24 @@ describe('turnRecordFilterIntoRecordGqlOperationFilter', () => {
|
||||
|
||||
expect(result).toHaveProperty('recordId.in');
|
||||
});
|
||||
|
||||
it('should handle IS_NOT operand as wrapped in', () => {
|
||||
const result = turnRecordFilterIntoRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
recordFilter: makeFilter(
|
||||
'f-uuid',
|
||||
RecordFilterOperand.IS_NOT,
|
||||
'["550e8400-e29b-41d4-a716-446655440000"]',
|
||||
),
|
||||
fieldMetadataItemById,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
not: {
|
||||
recordId: { in: ['550e8400-e29b-41d4-a716-446655440000'] },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('relation traversal', () => {
|
||||
|
||||
@@ -507,6 +507,14 @@ const buildDirectFieldGqlOperationFilter = ({
|
||||
eq: convertRatingToRatingValue(parseFloat(recordFilter.value)),
|
||||
} as RatingFilter,
|
||||
};
|
||||
case RecordFilterOperand.IS_NOT:
|
||||
return {
|
||||
not: {
|
||||
[fieldMetadataItem.name]: {
|
||||
eq: convertRatingToRatingValue(parseFloat(recordFilter.value)),
|
||||
} as RatingFilter,
|
||||
},
|
||||
};
|
||||
case RecordFilterOperand.GREATER_THAN_OR_EQUAL:
|
||||
return {
|
||||
[fieldMetadataItem.name]: {
|
||||
@@ -1525,9 +1533,16 @@ const buildDirectFieldGqlOperationFilter = ({
|
||||
};
|
||||
}
|
||||
case 'UUID': {
|
||||
const recordIds = arrayOfUuidOrVariableSchema.parse(recordFilter.value);
|
||||
const parsedRecordIds = arrayOfUuidOrVariableSchema.parse(
|
||||
recordFilter.value,
|
||||
);
|
||||
|
||||
if (!isDefined(recordIds) || recordIds.length === 0) return;
|
||||
// Fall back to a sentinel v4 UUID when the input isn't a valid UUID so the
|
||||
// filter compiles to a guaranteed no-match instead of being silently dropped.
|
||||
const recordIds =
|
||||
isDefined(parsedRecordIds) && parsedRecordIds.length > 0
|
||||
? parsedRecordIds
|
||||
: ['00000000-0000-4000-8000-000000000000'];
|
||||
|
||||
switch (recordFilter.operand) {
|
||||
case RecordFilterOperand.IS:
|
||||
@@ -1536,6 +1551,14 @@ const buildDirectFieldGqlOperationFilter = ({
|
||||
in: recordIds,
|
||||
} as UUIDFilter,
|
||||
};
|
||||
case RecordFilterOperand.IS_NOT:
|
||||
return {
|
||||
not: {
|
||||
[fieldMetadataItem.name]: {
|
||||
in: recordIds,
|
||||
} as UUIDFilter,
|
||||
},
|
||||
};
|
||||
default:
|
||||
throw new Error(
|
||||
`Unknown operand ${recordFilter.operand} for ${filterType} filter`,
|
||||
|
||||
+10
@@ -97,6 +97,16 @@ describe('getEmptyRecordGqlOperationFilter', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle UUID type', () => {
|
||||
const result = getEmptyRecordGqlOperationFilter(
|
||||
makeParams(FieldMetadataType.UUID),
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
testField: { is: 'NULL' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle CURRENCY type', () => {
|
||||
const result = getEmptyRecordGqlOperationFilter(
|
||||
makeParams(FieldMetadataType.CURRENCY),
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
type RelationFilter,
|
||||
type SelectFilter,
|
||||
type StringFilter,
|
||||
type UUIDFilter,
|
||||
} from '@/types';
|
||||
import { CustomError } from '@/utils/errors';
|
||||
import { computeEmptyGqlOperationFilterForEmails } from '@/utils/filter/computeEmptyGqlOperationFilterForEmails';
|
||||
@@ -308,6 +309,11 @@ export const getEmptyRecordGqlOperationFilter = ({
|
||||
[correspondingField.name]: { is: 'NULL' } as SelectFilter,
|
||||
};
|
||||
break;
|
||||
case 'UUID':
|
||||
emptyRecordFilter = {
|
||||
[correspondingField.name]: { is: 'NULL' } as UUIDFilter,
|
||||
};
|
||||
break;
|
||||
case 'MULTI_SELECT':
|
||||
emptyRecordFilter = {
|
||||
or: [
|
||||
|
||||
Reference in New Issue
Block a user