[View migration] Clean ViewFilterOperand (#14785)

In the BE we have stored filter operand as IS_EMPTY, IS_NOT_EMPTY, etc. 
For some reason in the FE we were manipulating IsEmpty, IsNotEmpty, etc.
(maybe because they were used before in Views before they were moved to
core)

So we were converting the operands in the FE from IS to Is
(convertViewFilterOperandFromCore) to read and manipulate viewFilters,
and then back to BE version to send mutations etc., from Is to IS
(convertViewFilterOperandToCore).
The migration is now over, so we can remove and simplify that code. 
(In the 1-5:migrate-views-to-core command we still do the migration from
Is format to IS format.)
This commit is contained in:
Marie
2025-09-30 17:12:03 +02:00
committed by GitHub
parent 15975a2cfc
commit 3927b36406
88 changed files with 730 additions and 853 deletions
@@ -15,7 +15,7 @@ export const SeeRunsWorkflowSingleRecordAction = () => {
queryParams={{
filter: {
workflow: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [workflowWithCurrentVersion?.id],
},
},
@@ -15,7 +15,7 @@ export const SeeVersionsWorkflowSingleRecordAction = () => {
queryParams={{
filter: {
workflow: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [workflowWithCurrentVersion?.id],
},
},
@@ -20,12 +20,12 @@ export const SeeRunsWorkflowVersionSingleRecordAction = () => {
queryParams={{
filter: {
workflow: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [workflowWithCurrentVersion?.id],
},
},
workflowVersion: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [recordId],
},
},
@@ -20,7 +20,7 @@ export const SeeVersionsWorkflowVersionSingleRecordAction = () => {
queryParams={{
filter: {
workflow: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [workflowWithCurrentVersion?.id],
},
},
@@ -63,7 +63,7 @@ export const useFindManyRecordsSelectedInContextStore = ({
return (
foundFieldMetadataItem?.name === 'deletedAt' &&
filter.operand === RecordFilterOperand.IsNotEmpty
filter.operand === RecordFilterOperand.IS_NOT_EMPTY
);
});
@@ -60,7 +60,7 @@ describe('computeContextStoreFilters', () => {
value: 'John',
displayValue: 'John',
displayAvatarUrl: undefined,
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
type: 'TEXT',
label: 'Name',
},
@@ -78,7 +78,7 @@ export const ObjectFilterDropdownDateInput = () => {
};
const isRelativeOperand =
selectedOperandInDropdown === ViewFilterOperand.IsRelative;
selectedOperandInDropdown === ViewFilterOperand.IS_RELATIVE;
const handleClear = () => {
isRelativeOperand
@@ -42,20 +42,20 @@ export const ObjectFilterDropdownFilterInput = ({
const isOperandWithFilterValue =
selectedOperandInDropdown &&
[
ViewFilterOperand.Is,
ViewFilterOperand.IsNotNull,
ViewFilterOperand.IsNot,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.IsBefore,
ViewFilterOperand.IsAfter,
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.IsRelative,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT_NULL,
ViewFilterOperand.IS_NOT,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.IS_BEFORE,
ViewFilterOperand.IS_AFTER,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
ViewFilterOperand.IS_RELATIVE,
].includes(selectedOperandInDropdown);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VectorSearch;
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
if (isVectorSearchFilter && isDefined(filterDropdownId)) {
return <ObjectFilterDropdownVectorSearchInput />;
@@ -33,7 +33,7 @@ export const ObjectFilterDropdownFilterInputHeader = () => {
dropdownInstanceId === VIEW_BAR_FILTER_DROPDOWN_ID;
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VectorSearch;
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
if (isInViewBarFilterDropdown) {
return <ViewBarFilterDropdownFilterInputMenuHeader />;
@@ -2,8 +2,8 @@ import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordF
export const DATE_OPERANDS_THAT_SHOULD_BE_INITIALIZED_WITH_NOW: RecordFilterOperand[] =
[
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IsAfter,
RecordFilterOperand.IsBefore,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
RecordFilterOperand.IS_AFTER,
RecordFilterOperand.IS_BEFORE,
];
@@ -44,11 +44,11 @@ export const useApplyObjectFilterDropdownOperand = () => {
newOperand: RecordFilterOperand,
) => {
const isValuelessOperand = [
RecordFilterOperand.IsEmpty,
RecordFilterOperand.IsNotEmpty,
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IS_EMPTY,
RecordFilterOperand.IS_NOT_EMPTY,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
].includes(newOperand);
let recordFilterToUpsert: RecordFilter | null | undefined = null;
@@ -93,7 +93,7 @@ export const useApplyObjectFilterDropdownOperand = () => {
);
recordFilterToUpsert.displayValue = displayValue;
} else if (newOperand === RecordFilterOperand.IsRelative) {
} else if (newOperand === RecordFilterOperand.IS_RELATIVE) {
const defaultRelativeDate = {
direction: 'THIS' as VariableDateViewFilterValueDirection,
amount: 1,
@@ -5,13 +5,13 @@ import { getOperandLabel, getOperandLabelShort } from '../getOperandLabel';
describe('getOperandLabel', () => {
const testCases = [
[ViewFilterOperand.Contains, 'Contains'],
[ViewFilterOperand.DoesNotContain, "Doesn't contain"],
[ViewFilterOperand.GreaterThanOrEqual, 'Greater than or equal'],
[ViewFilterOperand.LessThanOrEqual, 'Less than or equal'],
[ViewFilterOperand.Is, 'Is'],
[ViewFilterOperand.IsNot, 'Is not'],
[ViewFilterOperand.IsNotNull, 'Is not null'],
[ViewFilterOperand.CONTAINS, 'Contains'],
[ViewFilterOperand.DOES_NOT_CONTAIN, "Doesn't contain"],
[ViewFilterOperand.GREATER_THAN_OR_EQUAL, 'Greater than or equal'],
[ViewFilterOperand.LESS_THAN_OR_EQUAL, 'Less than or equal'],
[ViewFilterOperand.IS, 'Is'],
[ViewFilterOperand.IS_NOT, 'Is not'],
[ViewFilterOperand.IS_NOT_NULL, 'Is not null'],
[undefined, ''], // undefined operand
];
@@ -27,13 +27,13 @@ describe('getOperandLabel', () => {
describe('getOperandLabelShort', () => {
const testCases = [
[ViewFilterOperand.Is, ': '],
[ViewFilterOperand.Contains, ': '],
[ViewFilterOperand.IsNot, ': Not'],
[ViewFilterOperand.DoesNotContain, ': Not'],
[ViewFilterOperand.IsNotNull, ': NotNull'],
[ViewFilterOperand.GreaterThanOrEqual, '\u00A0≥ '],
[ViewFilterOperand.LessThanOrEqual, '\u00A0≤ '],
[ViewFilterOperand.IS, ': '],
[ViewFilterOperand.CONTAINS, ': '],
[ViewFilterOperand.IS_NOT, ': Not'],
[ViewFilterOperand.DOES_NOT_CONTAIN, ': Not'],
[ViewFilterOperand.IS_NOT_NULL, ': NotNull'],
[ViewFilterOperand.GREATER_THAN_OR_EQUAL, '\u00A0≥ '],
[ViewFilterOperand.LESS_THAN_OR_EQUAL, '\u00A0≤ '],
[undefined, ': '], // undefined operand
];
@@ -6,48 +6,48 @@ import { type FilterableFieldType } from 'twenty-shared/types';
describe('getOperandsForFilterType', () => {
const emptyOperands = [
RecordFilterOperand.IsEmpty,
RecordFilterOperand.IsNotEmpty,
RecordFilterOperand.IS_EMPTY,
RecordFilterOperand.IS_NOT_EMPTY,
];
const containsOperands = [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
];
const numberOperands = [
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
];
const currencyAmountMicrosOperands = [
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
];
const currencyCurrencyCodeOperands = [
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
];
const actorSourceOperands = [
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
];
const dateOperands = [
RecordFilterOperand.Is,
RecordFilterOperand.IsRelative,
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IsBefore,
RecordFilterOperand.IsAfter,
RecordFilterOperand.IS,
RecordFilterOperand.IS_RELATIVE,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
RecordFilterOperand.IS_BEFORE,
RecordFilterOperand.IS_AFTER,
];
const relationOperand = [RecordFilterOperand.Is, RecordFilterOperand.IsNot];
const relationOperand = [RecordFilterOperand.IS, RecordFilterOperand.IS_NOT];
const testCases = [
['TEXT', [...containsOperands, ...emptyOperands]],
@@ -4,22 +4,22 @@ import { isFilterOperandExpectingValue } from '../isFilterOperandExpectingValue'
describe('isFilterOperandExpectingValue', () => {
const testCases = [
{ operand: ViewFilterOperand.Contains, expectedResult: true },
{ operand: ViewFilterOperand.DoesNotContain, expectedResult: true },
{ operand: ViewFilterOperand.GreaterThanOrEqual, expectedResult: true },
{ operand: ViewFilterOperand.LessThanOrEqual, expectedResult: true },
{ operand: ViewFilterOperand.Is, expectedResult: true },
{ operand: ViewFilterOperand.IsNot, expectedResult: true },
{ operand: ViewFilterOperand.IsRelative, expectedResult: true },
{ operand: ViewFilterOperand.IsBefore, expectedResult: true },
{ operand: ViewFilterOperand.IsAfter, expectedResult: true },
{ operand: ViewFilterOperand.CONTAINS, expectedResult: true },
{ operand: ViewFilterOperand.DOES_NOT_CONTAIN, expectedResult: true },
{ operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, expectedResult: true },
{ operand: ViewFilterOperand.LESS_THAN_OR_EQUAL, expectedResult: true },
{ operand: ViewFilterOperand.IS, expectedResult: true },
{ operand: ViewFilterOperand.IS_NOT, expectedResult: true },
{ operand: ViewFilterOperand.IS_RELATIVE, expectedResult: true },
{ operand: ViewFilterOperand.IS_BEFORE, expectedResult: true },
{ operand: ViewFilterOperand.IS_AFTER, expectedResult: true },
{ operand: ViewFilterOperand.IsNotNull, expectedResult: false },
{ operand: ViewFilterOperand.IsEmpty, expectedResult: false },
{ operand: ViewFilterOperand.IsNotEmpty, expectedResult: false },
{ operand: ViewFilterOperand.IsInPast, expectedResult: false },
{ operand: ViewFilterOperand.IsInFuture, expectedResult: false },
{ operand: ViewFilterOperand.IsToday, expectedResult: false },
{ operand: ViewFilterOperand.IS_NOT_NULL, expectedResult: false },
{ operand: ViewFilterOperand.IS_EMPTY, expectedResult: false },
{ operand: ViewFilterOperand.IS_NOT_EMPTY, expectedResult: false },
{ operand: ViewFilterOperand.IS_IN_PAST, expectedResult: false },
{ operand: ViewFilterOperand.IS_IN_FUTURE, expectedResult: false },
{ operand: ViewFilterOperand.IS_TODAY, expectedResult: false },
];
testCases.forEach(({ operand, expectedResult }) => {
@@ -1,14 +1,14 @@
import { ViewFilterOperand } from 'twenty-shared/types';
export const configurableViewFilterOperands = new Set<ViewFilterOperand>([
ViewFilterOperand.Is,
ViewFilterOperand.IsNotNull,
ViewFilterOperand.IsNot,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.IsBefore,
ViewFilterOperand.IsAfter,
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.IsRelative,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT_NULL,
ViewFilterOperand.IS_NOT,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.IS_BEFORE,
ViewFilterOperand.IS_AFTER,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
ViewFilterOperand.IS_RELATIVE,
]);
@@ -11,9 +11,9 @@ export const getInitialFilterValue = (
case 'DATE':
case 'DATE_TIME': {
const activeDatePickerOperands = [
RecordFilterOperand.IsBefore,
RecordFilterOperand.Is,
RecordFilterOperand.IsAfter,
RecordFilterOperand.IS_BEFORE,
RecordFilterOperand.IS,
RecordFilterOperand.IS_AFTER,
];
if (activeDatePickerOperands.includes(newOperand)) {
@@ -25,7 +25,7 @@ export const getInitialFilterValue = (
return { value, displayValue };
}
if (newOperand === RecordFilterOperand.IsRelative) {
if (newOperand === RecordFilterOperand.IS_RELATIVE) {
return { value: '', displayValue: '' };
}
@@ -5,35 +5,35 @@ export const getOperandLabel = (
operand: ViewFilterOperand | null | undefined,
) => {
switch (operand) {
case ViewFilterOperand.Contains:
case ViewFilterOperand.CONTAINS:
return t`Contains`;
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.DOES_NOT_CONTAIN:
return t`Doesn't contain`;
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return t`Greater than or equal`;
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return t`Less than or equal`;
case ViewFilterOperand.IsBefore:
case ViewFilterOperand.IS_BEFORE:
return t`Is before`;
case ViewFilterOperand.IsAfter:
case ViewFilterOperand.IS_AFTER:
return t`Is after`;
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return t`Is`;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return t`Is not`;
case ViewFilterOperand.IsNotNull:
case ViewFilterOperand.IS_NOT_NULL:
return t`Is not null`;
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return t`Is empty`;
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return t`Is not empty`;
case ViewFilterOperand.IsRelative:
case ViewFilterOperand.IS_RELATIVE:
return t`Is relative`;
case ViewFilterOperand.IsInPast:
case ViewFilterOperand.IS_IN_PAST:
return t`Is in past`;
case ViewFilterOperand.IsInFuture:
case ViewFilterOperand.IS_IN_FUTURE:
return t`Is in future`;
case ViewFilterOperand.IsToday:
case ViewFilterOperand.IS_TODAY:
return t`Is today`;
default:
return '';
@@ -44,31 +44,31 @@ export const getOperandLabelShort = (
operand: ViewFilterOperand | null | undefined,
) => {
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.Contains:
case ViewFilterOperand.IS:
case ViewFilterOperand.CONTAINS:
return ': ';
case ViewFilterOperand.IsNot:
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.IS_NOT:
case ViewFilterOperand.DOES_NOT_CONTAIN:
return t`: Not`;
case ViewFilterOperand.IsNotNull:
case ViewFilterOperand.IS_NOT_NULL:
return t`: NotNull`;
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return t`: NotEmpty`;
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return t`: Empty`;
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return '\u00A0≥ ';
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return '\u00A0≤ ';
case ViewFilterOperand.IsBefore:
case ViewFilterOperand.IS_BEFORE:
return '\u00A0< ';
case ViewFilterOperand.IsAfter:
case ViewFilterOperand.IS_AFTER:
return '\u00A0> ';
case ViewFilterOperand.IsInPast:
case ViewFilterOperand.IS_IN_PAST:
return t`: Past`;
case ViewFilterOperand.IsInFuture:
case ViewFilterOperand.IS_IN_FUTURE:
return t`: Future`;
case ViewFilterOperand.IsToday:
case ViewFilterOperand.IS_TODAY:
return t`: Today`;
default:
return ': ';
@@ -2,22 +2,22 @@ import { ViewFilterOperand } from 'twenty-shared/types';
export const isFilterOperandExpectingValue = (operand: ViewFilterOperand) => {
switch (operand) {
case ViewFilterOperand.IsNotNull:
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IsInPast:
case ViewFilterOperand.IsInFuture:
case ViewFilterOperand.IsToday:
case ViewFilterOperand.IS_NOT_NULL:
case ViewFilterOperand.IS_EMPTY:
case ViewFilterOperand.IS_NOT_EMPTY:
case ViewFilterOperand.IS_IN_PAST:
case ViewFilterOperand.IS_IN_FUTURE:
case ViewFilterOperand.IS_TODAY:
return false;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.Contains:
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.IsBefore:
case ViewFilterOperand.IsAfter:
case ViewFilterOperand.Is:
case ViewFilterOperand.IsRelative:
case ViewFilterOperand.IS_NOT:
case ViewFilterOperand.CONTAINS:
case ViewFilterOperand.DOES_NOT_CONTAIN:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
case ViewFilterOperand.IS_BEFORE:
case ViewFilterOperand.IS_AFTER:
case ViewFilterOperand.IS:
case ViewFilterOperand.IS_RELATIVE:
default:
return true;
}
@@ -33,7 +33,7 @@ export const useRecordCalendarQueryDateRangeFilter = (selectedDate: Date) => {
id: DATE_RANGE_FILTER_AFTER_ID,
fieldMetadataId: dateRangeFilterFieldMetadataId,
value: `${firstDayOfFirstWeek.toISOString()}`,
operand: RecordFilterOperand.IsAfter,
operand: RecordFilterOperand.IS_AFTER,
type: 'DATE',
label: 'After',
displayValue: `${firstDayOfFirstWeek.toISOString()}`,
@@ -43,7 +43,7 @@ export const useRecordCalendarQueryDateRangeFilter = (selectedDate: Date) => {
id: DATE_RANGE_FILTER_BEFORE_ID,
fieldMetadataId: dateRangeFilterFieldMetadataId,
value: `${lastDayOfLastWeek.toISOString()}`,
operand: RecordFilterOperand.IsBefore,
operand: RecordFilterOperand.IS_BEFORE,
type: 'DATE',
label: 'Before',
displayValue: `${lastDayOfLastWeek.toISOString()}`,
@@ -92,7 +92,7 @@ export const RecordDetailRelationSection = ({
const filterQueryParams = {
filter: {
[relationFieldMetadataItem?.name || '']: {
[ViewFilterOperand.Is]: {
[ViewFilterOperand.IS]: {
selectedRecordIds: [recordId],
},
},
@@ -40,7 +40,7 @@ describe('useRemoveRecordFilter', () => {
id: 'filter-1',
fieldMetadataId: 'field-1',
value: 'test-value',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
displayValue: 'test-value',
label: 'Test Field',
type: FieldMetadataType.TEXT,
@@ -85,7 +85,7 @@ describe('useRemoveRecordFilter', () => {
id: 'filter-1',
fieldMetadataId: 'field-1',
value: 'test-value',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
displayValue: 'test-value',
label: 'Test Field',
type: FieldMetadataType.TEXT,
@@ -34,7 +34,7 @@ describe('useUpsertRecordFilter', () => {
id: 'filter-1',
fieldMetadataId: 'field-1',
value: 'test-value',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
displayValue: 'test-value',
label: 'Test Field',
type: FieldMetadataType.TEXT,
@@ -68,7 +68,7 @@ describe('useUpsertRecordFilter', () => {
id: 'filter-1',
fieldMetadataId: 'field-1',
value: 'initial-value',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
displayValue: 'initial-value',
label: 'Test Field',
type: FieldMetadataType.TEXT,
@@ -78,7 +78,7 @@ describe('useUpsertRecordFilter', () => {
id: 'filter-1',
fieldMetadataId: 'field-1',
value: 'updated-value',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
displayValue: 'updated-value',
label: 'Test Field',
type: FieldMetadataType.TEXT,
@@ -22,7 +22,7 @@ export const useCheckIsSoftDeleteFilter = () => {
});
const isNotEmptyFilter =
recordFilter.operand === RecordFilterOperand.IsNotEmpty;
recordFilter.operand === RecordFilterOperand.IS_NOT_EMPTY;
return (
foundFieldMetadataItem.name === SOFT_DELETE_FILTER_FIELD_NAME &&
@@ -46,7 +46,7 @@ describe('computeViewRecordGqlOperationFilter', () => {
value: companiesMock[0].name,
fieldMetadataId: companyMockNameFieldMetadataId.id,
displayValue: companiesMock[0].name,
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'TEXT',
label: 'Name',
};
@@ -89,7 +89,7 @@ describe('computeViewRecordGqlOperationFilter', () => {
value: companiesMock[0].name,
fieldMetadataId: companyMockNameFieldMetadataId.id,
displayValue: companiesMock[0].name,
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
type: FieldMetadataType.TEXT,
label: 'Name',
};
@@ -99,7 +99,7 @@ describe('computeViewRecordGqlOperationFilter', () => {
value: '1000',
fieldMetadataId: companyMockEmployeesFieldMetadataId.id,
displayValue: '1000',
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
type: FieldMetadataType.NUMBER,
label: 'Employees',
};
@@ -144,7 +144,7 @@ describe('should work as expected for the different field types', () => {
value: '123 Main St',
fieldMetadataId: companyMockAddressFieldMetadataId.id,
displayValue: '123 Main St',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
type: FieldMetadataType.ADDRESS,
label: 'Address',
};
@@ -154,7 +154,7 @@ describe('should work as expected for the different field types', () => {
value: '123 Main St',
fieldMetadataId: companyMockAddressFieldMetadataId?.id,
displayValue: '123 Main St',
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
type: FieldMetadataType.ADDRESS,
label: 'Address',
};
@@ -164,7 +164,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockAddressFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
type: FieldMetadataType.ADDRESS,
label: 'Address',
};
@@ -174,7 +174,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockAddressFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
label: 'Address',
type: FieldMetadataType.ADDRESS,
};
@@ -608,7 +608,7 @@ describe('should work as expected for the different field types', () => {
value: '1234567890',
fieldMetadataId: personMockPhonesFieldMetadataId.id,
displayValue: '1234567890',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
label: 'Phones',
type: FieldMetadataType.PHONES,
};
@@ -618,7 +618,7 @@ describe('should work as expected for the different field types', () => {
value: '1234567890',
fieldMetadataId: personMockPhonesFieldMetadataId.id,
displayValue: '1234567890',
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
label: 'Phones',
type: FieldMetadataType.PHONES,
};
@@ -628,7 +628,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: personMockPhonesFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
label: 'Phones',
type: FieldMetadataType.PHONES,
};
@@ -638,7 +638,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: personMockPhonesFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
label: 'Phones',
type: FieldMetadataType.PHONES,
};
@@ -833,7 +833,7 @@ describe('should work as expected for the different field types', () => {
value: 'test@test.com',
fieldMetadataId: personMockEmailFieldMetadataId.id,
displayValue: 'test@test.com',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
label: 'Emails',
type: FieldMetadataType.EMAILS,
};
@@ -843,7 +843,7 @@ describe('should work as expected for the different field types', () => {
value: 'test@test.com',
fieldMetadataId: personMockEmailFieldMetadataId.id,
displayValue: 'test@test.com',
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
label: 'Emails',
type: FieldMetadataType.EMAILS,
};
@@ -853,7 +853,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: personMockEmailFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
label: 'Emails',
type: FieldMetadataType.EMAILS,
};
@@ -863,7 +863,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: personMockEmailFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
label: 'Emails',
type: FieldMetadataType.EMAILS,
};
@@ -1034,7 +1034,7 @@ describe('should work as expected for the different field types', () => {
value: '2024-09-17T20:46:58.922Z',
fieldMetadataId: companyMockDateFieldMetadataId?.id,
displayValue: '2024-09-17T20:46:58.922Z',
operand: ViewFilterOperand.IsAfter,
operand: ViewFilterOperand.IS_AFTER,
label: 'Created At',
type: FieldMetadataType.DATE_TIME,
};
@@ -1044,7 +1044,7 @@ describe('should work as expected for the different field types', () => {
value: '2024-09-17T20:46:58.922Z',
fieldMetadataId: companyMockDateFieldMetadataId?.id,
displayValue: '2024-09-17T20:46:58.922Z',
operand: ViewFilterOperand.IsBefore,
operand: ViewFilterOperand.IS_BEFORE,
label: 'Created At',
type: FieldMetadataType.DATE_TIME,
};
@@ -1054,7 +1054,7 @@ describe('should work as expected for the different field types', () => {
value: '2024-09-17T20:46:58.922Z',
fieldMetadataId: companyMockDateFieldMetadataId?.id,
displayValue: '2024-09-17T20:46:58.922Z',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
label: 'Created At',
type: FieldMetadataType.DATE_TIME,
};
@@ -1064,7 +1064,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockDateFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
label: 'Created At',
type: FieldMetadataType.DATE_TIME,
};
@@ -1074,7 +1074,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockDateFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
label: 'Created At',
type: FieldMetadataType.DATE_TIME,
};
@@ -1147,7 +1147,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockEmployeesFieldMetadataId?.id,
displayValue: '1000',
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
label: 'Employees',
type: FieldMetadataType.NUMBER,
};
@@ -1157,7 +1157,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockEmployeesFieldMetadataId?.id,
displayValue: '1000',
operand: ViewFilterOperand.LessThanOrEqual,
operand: ViewFilterOperand.LESS_THAN_OR_EQUAL,
label: 'Employees',
type: FieldMetadataType.NUMBER,
};
@@ -1167,7 +1167,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockEmployeesFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
label: 'Employees',
type: FieldMetadataType.NUMBER,
};
@@ -1177,7 +1177,7 @@ describe('should work as expected for the different field types', () => {
value: '',
fieldMetadataId: companyMockEmployeesFieldMetadataId?.id,
displayValue: '',
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
label: 'Employees',
type: FieldMetadataType.NUMBER,
};
@@ -1233,7 +1233,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockARRFieldMetadataId?.id,
displayValue: '1000',
operand: RecordFilterOperand.GreaterThanOrEqual,
operand: RecordFilterOperand.GREATER_THAN_OR_EQUAL,
subFieldName: 'amountMicros' satisfies Extract<
keyof FieldCurrencyValue,
'amountMicros'
@@ -1247,7 +1247,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockARRFieldMetadataId.id,
displayValue: '1000',
operand: RecordFilterOperand.LessThanOrEqual,
operand: RecordFilterOperand.LESS_THAN_OR_EQUAL,
subFieldName: 'amountMicros' satisfies Extract<
keyof FieldCurrencyValue,
'amountMicros'
@@ -1261,7 +1261,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockARRFieldMetadataId.id,
displayValue: '1000',
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
subFieldName: 'amountMicros' satisfies Extract<
keyof FieldCurrencyValue,
'amountMicros'
@@ -1275,7 +1275,7 @@ describe('should work as expected for the different field types', () => {
value: '1000',
fieldMetadataId: companyMockARRFieldMetadataId.id,
displayValue: '1000',
operand: RecordFilterOperand.IsNot,
operand: RecordFilterOperand.IS_NOT,
subFieldName: 'amountMicros' satisfies Extract<
keyof FieldCurrencyValue,
'amountMicros'
@@ -1343,7 +1343,7 @@ describe('should work as expected for the different field types', () => {
value: '["USD"]',
fieldMetadataId: companyMockARRFieldMetadataId.id,
displayValue: 'USD',
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
subFieldName: 'currencyCode' satisfies Extract<
keyof FieldCurrencyValue,
'currencyCode'
@@ -1357,7 +1357,7 @@ describe('should work as expected for the different field types', () => {
value: '["USD"]',
fieldMetadataId: companyMockARRFieldMetadataId.id,
displayValue: 'Not USD',
operand: RecordFilterOperand.IsNot,
operand: RecordFilterOperand.IS_NOT,
subFieldName: 'currencyCode' satisfies Extract<
keyof FieldCurrencyValue,
'currencyCode'
@@ -1411,7 +1411,7 @@ describe('should work as expected for the different field types', () => {
value: '["DOG",""]',
fieldMetadataId: selectFieldMetadata?.id,
displayValue: '["Dog",""]',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
label: 'Select',
type: FieldMetadataType.SELECT,
};
@@ -1421,7 +1421,7 @@ describe('should work as expected for the different field types', () => {
value: '["DOG",""]',
fieldMetadataId: selectFieldMetadata.id,
displayValue: '["Dog",""]',
operand: ViewFilterOperand.IsNot,
operand: ViewFilterOperand.IS_NOT,
label: 'Select',
type: FieldMetadataType.SELECT,
};
@@ -1481,7 +1481,7 @@ describe('should work as expected for the different field types', () => {
value: '["option1",""]',
fieldMetadataId: multiSelectFieldMetadata.id,
displayValue: '["option1",""]',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
label: 'MultiSelect',
type: FieldMetadataType.MULTI_SELECT,
};
@@ -1491,7 +1491,7 @@ describe('should work as expected for the different field types', () => {
value: '["option1",""]',
fieldMetadataId: multiSelectFieldMetadata.id,
displayValue: '["option1",""]',
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
label: 'MultiSelect',
type: FieldMetadataType.MULTI_SELECT,
};
@@ -9,7 +9,7 @@ const MOCK_RECORD_FILTER_FIELDS: RecordFilter = {
id: 'filter-1',
recordFilterGroupId: 'root-group',
fieldMetadataId: 'field-1',
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
value: 'value-1',
displayValue: 'Display Value 1',
label: 'Label 1',
@@ -14,13 +14,13 @@ export type GetRecordFilterOperandsParams = {
};
const emptyOperands = [
RecordFilterOperand.IsEmpty,
RecordFilterOperand.IsNotEmpty,
RecordFilterOperand.IS_EMPTY,
RecordFilterOperand.IS_NOT_EMPTY,
] as const;
const relationOperands = [
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
] as const;
type FilterOperandMap = {
@@ -38,110 +38,114 @@ type CompositeFieldFilterOperandMap = {
export const FILTER_OPERANDS_MAP = {
TEXT: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
EMAILS: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
FULL_NAME: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
ADDRESS: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
LINKS: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
PHONES: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
CURRENCY: [
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
],
NUMBER: [
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
],
RAW_JSON: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
DATE_TIME: [
RecordFilterOperand.Is,
RecordFilterOperand.IsRelative,
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IsBefore,
RecordFilterOperand.IsAfter,
RecordFilterOperand.IS,
RecordFilterOperand.IS_RELATIVE,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
RecordFilterOperand.IS_BEFORE,
RecordFilterOperand.IS_AFTER,
...emptyOperands,
],
DATE: [
RecordFilterOperand.Is,
RecordFilterOperand.IsRelative,
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IsBefore,
RecordFilterOperand.IsAfter,
RecordFilterOperand.IS,
RecordFilterOperand.IS_RELATIVE,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
RecordFilterOperand.IS_BEFORE,
RecordFilterOperand.IS_AFTER,
...emptyOperands,
],
RATING: [
RecordFilterOperand.Is,
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.IS,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
],
RELATION: [...relationOperands, ...emptyOperands],
MULTI_SELECT: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
SELECT: [
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
...emptyOperands,
],
SELECT: [RecordFilterOperand.Is, RecordFilterOperand.IsNot, ...emptyOperands],
ACTOR: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
ARRAY: [
RecordFilterOperand.Contains,
RecordFilterOperand.DoesNotContain,
RecordFilterOperand.CONTAINS,
RecordFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
BOOLEAN: [RecordFilterOperand.Is],
TS_VECTOR: [RecordFilterOperand.VectorSearch],
UUID: [RecordFilterOperand.Is],
BOOLEAN: [RecordFilterOperand.IS],
TS_VECTOR: [RecordFilterOperand.VECTOR_SEARCH],
UUID: [RecordFilterOperand.IS],
} as const satisfies FilterOperandMap;
export const COMPOSITE_FIELD_FILTER_OPERANDS_MAP = {
CURRENCY: {
currencyCode: [
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
...emptyOperands,
],
amountMicros: [
RecordFilterOperand.GreaterThanOrEqual,
RecordFilterOperand.LessThanOrEqual,
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.GREATER_THAN_OR_EQUAL,
RecordFilterOperand.LESS_THAN_OR_EQUAL,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
...emptyOperands,
],
},
@@ -190,8 +194,8 @@ export const getRecordFilterOperands = ({
case 'ACTOR': {
if (isFilterOnActorSourceSubField(subFieldName)) {
return [
RecordFilterOperand.Is,
RecordFilterOperand.IsNot,
RecordFilterOperand.IS,
RecordFilterOperand.IS_NOT,
...emptyOperands,
];
}
@@ -18,9 +18,9 @@ export const isRecordFilterAboutSoftDelete = ({
});
const valueIsNotEmptyFilter =
(recordFilter.operand === RecordFilterOperand.Is &&
(recordFilter.operand === RecordFilterOperand.IS &&
!isEmpty(recordFilter.value)) ||
recordFilter.operand === RecordFilterOperand.IsNotEmpty;
recordFilter.operand === RecordFilterOperand.IS_NOT_EMPTY;
return (
foundFieldMetadataItem.name === SOFT_DELETE_FILTER_FIELD_NAME &&
@@ -10,11 +10,11 @@ export const isRecordFilterConsideredEmpty = (
if (
(!isDefined(value) || value === '' || value === '[]') &&
![
RecordFilterOperand.IsEmpty,
RecordFilterOperand.IsNotEmpty,
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IS_EMPTY,
RecordFilterOperand.IS_NOT_EMPTY,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
].includes(operand)
) {
return true;
@@ -35,7 +35,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'TEXT',
} satisfies RecordFilter);
break;
@@ -46,7 +46,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'ADDRESS',
} satisfies RecordFilter);
break;
@@ -57,7 +57,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'LINKS',
} satisfies RecordFilter);
break;
@@ -68,7 +68,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'FULL_NAME',
} satisfies RecordFilter);
break;
@@ -79,7 +79,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'ARRAY',
} satisfies RecordFilter);
break;
@@ -90,7 +90,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'EMAILS',
} satisfies RecordFilter);
break;
@@ -101,7 +101,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'PHONES',
} satisfies RecordFilter);
break;
@@ -113,7 +113,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
type: 'NUMBER',
} satisfies RecordFilter);
}
@@ -126,7 +126,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
type: 'CURRENCY',
subFieldName: 'amountMicros',
} satisfies RecordFilter);
@@ -149,7 +149,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
filterValue: arrayOfCurrenciesStringified,
fieldMetadataItem,
}),
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
type: 'CURRENCY',
subFieldName: 'currencyCode',
} satisfies RecordFilter);
@@ -177,7 +177,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
fieldMetadataItem,
filterValue: arrayOfSelectValues,
}),
operand: RecordFilterOperand.Is,
operand: RecordFilterOperand.IS,
type: 'SELECT',
} satisfies RecordFilter);
}
@@ -204,7 +204,7 @@ export const turnAnyFieldFilterIntoRecordGqlFilter = ({
fieldMetadataItem,
filterValue: arrayOfSelectValues,
}),
operand: RecordFilterOperand.Contains,
operand: RecordFilterOperand.CONTAINS,
type: 'MULTI_SELECT',
} satisfies RecordFilter);
}
@@ -57,7 +57,7 @@ export const useHandleToggleTrashColumnFilter = ({
const newFilter: RecordFilter = {
id: v4(),
fieldMetadataId: trashFieldMetadata.id,
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
displayValue: '',
type: filterType,
label: `Deleted`,
@@ -38,22 +38,22 @@ describe('buildValueFromFilter', () => {
describe('TEXT field type', () => {
const testCases = [
{
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
expected: 'test',
},
{
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
value: 'test',
expected: undefined,
},
{
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
value: 'test',
expected: 'test',
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: 'test',
expected: undefined,
},
@@ -71,47 +71,47 @@ describe('buildValueFromFilter', () => {
describe('DATE_TIME field type', () => {
const testCases = [
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsAfter,
operand: ViewFilterOperand.IS_AFTER,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsBefore,
operand: ViewFilterOperand.IS_BEFORE,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsInPast,
operand: ViewFilterOperand.IS_IN_PAST,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsInFuture,
operand: ViewFilterOperand.IS_IN_FUTURE,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsToday,
operand: ViewFilterOperand.IS_TODAY,
value: '',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsRelative,
operand: ViewFilterOperand.IS_RELATIVE,
value: '',
expected: mockDate,
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: '',
expected: undefined,
},
{
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
value: '2024-03-20T12:00:00Z',
expected: mockDate,
},
@@ -135,22 +135,22 @@ describe('buildValueFromFilter', () => {
describe('NUMBER field type', () => {
const testCases = [
{
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
value: '5',
expected: 6,
},
{
operand: ViewFilterOperand.LessThanOrEqual,
operand: ViewFilterOperand.LESS_THAN_OR_EQUAL,
value: '5',
expected: 4,
},
{
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
value: '5',
expected: 5,
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: '5',
expected: undefined,
},
@@ -168,12 +168,12 @@ describe('buildValueFromFilter', () => {
describe('BOOLEAN field type', () => {
const testCases = [
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: 'true',
expected: true,
},
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: 'false',
expected: false,
},
@@ -191,22 +191,22 @@ describe('buildValueFromFilter', () => {
describe('ARRAY field type', () => {
const testCases = [
{
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
expected: 'test',
},
{
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
value: 'test',
expected: undefined,
},
{
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
value: 'test',
expected: 'test',
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: 'test',
expected: undefined,
},
@@ -236,7 +236,7 @@ describe('buildValueFromFilter', () => {
const testCases = [
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: false,
selectedRecordIds: ['record-1'],
@@ -246,7 +246,7 @@ describe('buildValueFromFilter', () => {
expected: 'record-1',
},
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: true,
selectedRecordIds: ['record-1'],
@@ -256,7 +256,7 @@ describe('buildValueFromFilter', () => {
expected: 'current-workspace-member-id',
},
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: false,
selectedRecordIds: ['record-1', 'record-2'],
@@ -266,7 +266,7 @@ describe('buildValueFromFilter', () => {
expected: undefined,
},
{
operand: ViewFilterOperand.IsNot,
operand: ViewFilterOperand.IS_NOT,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: false,
selectedRecordIds: ['record-1'],
@@ -276,7 +276,7 @@ describe('buildValueFromFilter', () => {
expected: undefined,
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: false,
selectedRecordIds: ['record-1'],
@@ -309,7 +309,7 @@ describe('buildValueFromFilter', () => {
it.each(compositeTypes)(
'should return undefined for composite type %s',
(type) => {
const filter = createTestFilter(ViewFilterOperand.Is, 'test', type);
const filter = createTestFilter(ViewFilterOperand.IS, 'test', type);
expect(buildValueFromFilter({ filter })).toBeUndefined();
},
);
@@ -317,7 +317,7 @@ describe('buildValueFromFilter', () => {
describe('RAW_JSON field type', () => {
it('should return undefined', () => {
const filter = createTestFilter(ViewFilterOperand.Is, 'test', 'RAW_JSON');
const filter = createTestFilter(ViewFilterOperand.IS, 'test', 'RAW_JSON');
expect(buildValueFromFilter({ filter })).toBeUndefined();
});
});
@@ -346,27 +346,27 @@ describe('buildValueFromFilter', () => {
const testCases = [
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: 'Rating 1',
expected: 'RATING_1',
},
{
operand: ViewFilterOperand.IsNotEmpty,
operand: ViewFilterOperand.IS_NOT_EMPTY,
value: 'Rating 2',
expected: 'RATING_2',
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: 'Rating 1',
expected: undefined,
},
{
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
value: 'Rating 1',
expected: 'RATING_2',
},
{
operand: ViewFilterOperand.LessThanOrEqual,
operand: ViewFilterOperand.LESS_THAN_OR_EQUAL,
value: 'Rating 2',
expected: 'RATING_1',
},
@@ -387,7 +387,7 @@ describe('buildValueFromFilter', () => {
it('should return undefined when option is not found', () => {
const filter = createTestFilter(
ViewFilterOperand.Is,
ViewFilterOperand.IS,
'Rating 4',
'RATING',
);
@@ -420,17 +420,17 @@ describe('buildValueFromFilter', () => {
const testCases = [
{
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: JSON.stringify(['OPTION_1']),
expected: 'OPTION_1',
},
{
operand: ViewFilterOperand.IsNot,
operand: ViewFilterOperand.IS_NOT,
value: JSON.stringify(['OPTION_1']),
expected: undefined,
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: JSON.stringify(['OPTION_1']),
expected: undefined,
},
@@ -451,7 +451,7 @@ describe('buildValueFromFilter', () => {
it('should handle invalid JSON', () => {
const filter = createTestFilter(
ViewFilterOperand.Is,
ViewFilterOperand.IS,
'invalid-json',
'SELECT',
);
@@ -467,17 +467,17 @@ describe('buildValueFromFilter', () => {
describe('MULTI_SELECT field type', () => {
const testCases = [
{
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: JSON.stringify(['OPTION_1', 'OPTION_2']),
expected: ['OPTION_1', 'OPTION_2'],
},
{
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
value: JSON.stringify(['OPTION_1']),
expected: undefined,
},
{
operand: ViewFilterOperand.IsEmpty,
operand: ViewFilterOperand.IS_EMPTY,
value: JSON.stringify(['OPTION_1']),
expected: undefined,
},
@@ -493,7 +493,7 @@ describe('buildValueFromFilter', () => {
it('should handle invalid JSON', () => {
const filter = createTestFilter(
ViewFilterOperand.Contains,
ViewFilterOperand.CONTAINS,
'invalid-json',
'MULTI_SELECT',
);
@@ -504,7 +504,7 @@ describe('buildValueFromFilter', () => {
describe('UUID field type', () => {
it('should return the value', () => {
const filter = createTestFilter(
ViewFilterOperand.Is,
ViewFilterOperand.IS,
'test-uuid',
'UUID',
);
@@ -111,12 +111,12 @@ const computeValueFromFilterText = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Contains:
case ViewFilterOperand.CONTAINS:
return value;
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return value;
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.IS_EMPTY:
case ViewFilterOperand.DOES_NOT_CONTAIN:
return undefined;
default:
assertUnreachable(operand);
@@ -128,17 +128,17 @@ const computeValueFromFilterDate = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IsAfter:
case ViewFilterOperand.IsBefore:
case ViewFilterOperand.IS:
case ViewFilterOperand.IS_AFTER:
case ViewFilterOperand.IS_BEFORE:
return new Date(value);
case ViewFilterOperand.IsToday:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IsInPast:
case ViewFilterOperand.IsInFuture:
case ViewFilterOperand.IsRelative:
case ViewFilterOperand.IS_TODAY:
case ViewFilterOperand.IS_NOT_EMPTY:
case ViewFilterOperand.IS_IN_PAST:
case ViewFilterOperand.IS_IN_FUTURE:
case ViewFilterOperand.IS_RELATIVE:
return new Date();
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -151,13 +151,13 @@ const computeValueFromFilterNumber = (
) => {
switch (operand) {
//TODO: we shouln't create values from those filters as it makes no sense for the user
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return Number(value) + 1;
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return Number(value) - 1;
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return Number(value);
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -169,7 +169,7 @@ const computeValueFromFilterBoolean = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return value === 'true';
default:
assertUnreachable(operand);
@@ -181,11 +181,11 @@ const computeValueFromFilterArray = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Contains:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.CONTAINS:
case ViewFilterOperand.IS_NOT_EMPTY:
return value;
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.DOES_NOT_CONTAIN:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -203,22 +203,22 @@ const computeValueFromFilterRating = (
}
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS:
case ViewFilterOperand.IS_NOT_EMPTY:
return option.value;
case ViewFilterOperand.GreaterThanOrEqual: {
case ViewFilterOperand.GREATER_THAN_OR_EQUAL: {
const plusOne = options?.find(
(opt) => opt.position === option.position + 1,
)?.value;
return plusOne ? plusOne : option.value;
}
case ViewFilterOperand.LessThanOrEqual: {
case ViewFilterOperand.LESS_THAN_OR_EQUAL: {
const minusOne = options?.find(
(opt) => opt.position === option.position - 1,
)?.value;
return minusOne ? minusOne : option.value;
}
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -231,8 +231,8 @@ const computeValueFromFilterSelect = (
options?: FieldMetadataItemOption[],
) => {
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS:
case ViewFilterOperand.IS_NOT_EMPTY:
try {
const valueParsed = parseJson<string[]>(value)?.[0];
const option = options?.find((option) => option.value === valueParsed);
@@ -243,8 +243,8 @@ const computeValueFromFilterSelect = (
} catch {
return undefined;
}
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_NOT:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -256,16 +256,16 @@ const computeValueFromFilterMultiSelect = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Contains:
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.CONTAINS:
case ViewFilterOperand.IS_NOT_EMPTY:
try {
const parsedValue = parseJson<string[]>(value);
return parsedValue ? parsedValue : undefined;
} catch {
return undefined;
}
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.DOES_NOT_CONTAIN:
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -280,7 +280,7 @@ const computeValueFromFilterRelation = (
label?: string,
) => {
switch (operand) {
case ViewFilterOperand.Is: {
case ViewFilterOperand.IS: {
const parsedValue = parseJson<{
isCurrentWorkspaceMemberSelected: boolean;
selectedRecordIds: string[];
@@ -296,9 +296,9 @@ const computeValueFromFilterRelation = (
}
return undefined; //todo
}
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IsNotEmpty: // todo
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_NOT:
case ViewFilterOperand.IS_NOT_EMPTY: // todo
case ViewFilterOperand.IS_EMPTY:
return undefined;
default:
assertUnreachable(operand);
@@ -310,7 +310,7 @@ const computeValueFromFilterTSVector = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.VectorSearch:
case ViewFilterOperand.VECTOR_SEARCH:
return value;
default:
assertUnreachable(operand);
@@ -322,7 +322,7 @@ const computeValueFromFilterUUID = (
value: string,
) => {
switch (operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return value;
default:
assertUnreachable(operand);
@@ -20,7 +20,7 @@ export const EditableFilterChipDropdownMenuHeader = () => {
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VectorSearch;
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const { closeDropdown } = useCloseDropdown();
@@ -25,7 +25,7 @@ export const ViewBarFilterDropdownContent = () => {
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VectorSearch;
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const isAnyFieldSearchFilter = objectFilterDropdownAnyFieldSearchIsSelected;
@@ -21,7 +21,7 @@ export const ViewBarFilterDropdownFilterInputMenuHeader = () => {
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VectorSearch;
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const { clearVectorSearchInput } = useClearVectorSearchInput();
@@ -45,7 +45,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: mockFieldMetadataItem.id,
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: 'test',
viewFilterGroupId: 'group-1',
@@ -29,7 +29,7 @@ describe('useApplyViewFiltersToCurrentRecordFilters', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: mockFieldMetadataItem.id,
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: mockFieldMetadataItem.label,
viewFilterGroupId: 'group-1',
@@ -13,7 +13,6 @@ import { DESTROY_CORE_VIEW_FILTER } from '@/views/graphql/mutations/destroyCoreV
import { UPDATE_CORE_VIEW_FILTER } from '@/views/graphql/mutations/updateCoreViewFilter';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { type ViewFilter } from '@/views/types/ViewFilter';
import { convertViewFilterOperandToCore } from '@/views/utils/convertViewFilterOperandToCore';
import { useApolloClient } from '@apollo/client';
import { isNull } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
@@ -46,7 +45,7 @@ export const usePersistViewFilterRecords = () => {
fieldMetadataId: viewFilter.fieldMetadataId,
viewId: view.id,
value: viewFilter.value,
operand: convertViewFilterOperandToCore(viewFilter.operand),
operand: viewFilter.operand,
viewFilterGroupId: viewFilter.viewFilterGroupId,
positionInViewFilterGroup: viewFilter.positionInViewFilterGroup,
subFieldName: viewFilter.subFieldName ?? null,
@@ -87,7 +86,7 @@ export const usePersistViewFilterRecords = () => {
id: viewFilter.id,
input: {
value: viewFilter.value,
operand: convertViewFilterOperandToCore(viewFilter.operand),
operand: viewFilter.operand,
positionInViewFilterGroup: viewFilter.positionInViewFilterGroup,
viewFilterGroupId: viewFilter.viewFilterGroupId,
subFieldName: viewFilter.subFieldName ?? null,
@@ -14,7 +14,7 @@ export const useGetViewGroupsFilters = (): RecordFilter[] => {
id: recordGroup.id,
fieldMetadataId: recordGroup.fieldMetadataId,
value: JSON.stringify([recordGroup.fieldValue]),
operand: ViewFilterOperand.IsNot,
operand: ViewFilterOperand.IS_NOT,
displayValue: '',
type: getFilterTypeFromFieldType(FieldMetadataType.SELECT),
label: '',
@@ -16,7 +16,7 @@ export const useOpenVectorSearchFilter = (filterDropdownId?: string) => {
const openVectorSearchFilter = () => {
setObjectFilterDropdownFilterIsSelected(true);
setSelectedOperandInDropdown(ViewFilterOperand.VectorSearch);
setSelectedOperandInDropdown(ViewFilterOperand.VECTOR_SEARCH);
};
return {
@@ -26,7 +26,7 @@ export const useVectorSearchFilterActions = () => {
fieldMetadataId: vectorSearchField.id,
value: value,
displayValue: value,
operand: ViewFilterOperand.VectorSearch,
operand: ViewFilterOperand.VECTOR_SEARCH,
type: getFilterTypeFromFieldType(vectorSearchField.type),
label: 'Search',
};
@@ -7,7 +7,7 @@ describe('areViewFiltersEqual', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: 'field-1',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: 'test',
viewFilterGroupId: 'group-1',
@@ -46,7 +46,7 @@ describe('areViewFiltersEqual', () => {
const filterA = { ...baseFilter };
const filterB = {
...baseFilter,
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
};
expect(areViewFiltersEqual(filterA, filterB)).toBe(false);
@@ -7,7 +7,7 @@ describe('getViewFiltersToCreate', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: 'field-1',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: 'test',
viewFilterGroupId: 'group-1',
@@ -7,7 +7,7 @@ describe('getViewFiltersToDelete', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: 'field-1',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: 'test',
viewFilterGroupId: 'group-1',
@@ -7,7 +7,7 @@ describe('getViewFiltersToUpdate', () => {
__typename: 'ViewFilter',
id: 'filter-1',
fieldMetadataId: 'field-1',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'test',
displayValue: 'test',
viewFilterGroupId: 'group-1',
@@ -73,7 +73,7 @@ describe('getViewFiltersToUpdate', () => {
const existingFilter = { ...baseFilter } satisfies ViewFilter;
const filterWithNewOperand = {
...baseFilter,
operand: ViewFilterOperand.DoesNotContain,
operand: ViewFilterOperand.DOES_NOT_CONTAIN,
} satisfies ViewFilter;
const currentViewFilters: ViewFilter[] = [existingFilter];
@@ -28,7 +28,7 @@ describe('mapViewFiltersToFilters', () => {
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
},
];
@@ -38,7 +38,7 @@ describe('mapViewFiltersToFilters', () => {
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
label: baseFieldMetadataItem.label,
type: FieldMetadataType.FULL_NAME,
positionInRecordFilterGroup: undefined,
@@ -2,7 +2,6 @@ import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/Com
import { type ViewFilter } from '@/views/types/ViewFilter';
import { convertViewFilterValueToString } from 'twenty-shared/utils';
import { type CoreViewFilter } from '~/generated/graphql';
import { convertViewFilterOperandFromCore } from '../utils/convertViewFilterOperandFromCore';
export const convertCoreViewFilterToViewFilter = (
coreViewFilter: Pick<
@@ -20,7 +19,7 @@ export const convertCoreViewFilterToViewFilter = (
__typename: 'ViewFilter',
id: coreViewFilter.id,
fieldMetadataId: coreViewFilter.fieldMetadataId,
operand: convertViewFilterOperandFromCore(coreViewFilter.operand),
operand: coreViewFilter.operand,
value: convertViewFilterValueToString(coreViewFilter.value),
displayValue: convertViewFilterValueToString(coreViewFilter.value),
viewFilterGroupId: coreViewFilter.viewFilterGroupId,
@@ -1,26 +0,0 @@
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand as CoreViewFilterOperand } from '~/generated/graphql';
const mappingFromCore: Record<CoreViewFilterOperand, ViewFilterOperand> = {
[CoreViewFilterOperand.IS]: ViewFilterOperand.Is,
[CoreViewFilterOperand.IS_NOT_NULL]: ViewFilterOperand.IsNotNull,
[CoreViewFilterOperand.IS_NOT]: ViewFilterOperand.IsNot,
[CoreViewFilterOperand.LESS_THAN_OR_EQUAL]: ViewFilterOperand.LessThanOrEqual,
[CoreViewFilterOperand.GREATER_THAN_OR_EQUAL]:
ViewFilterOperand.GreaterThanOrEqual,
[CoreViewFilterOperand.IS_BEFORE]: ViewFilterOperand.IsBefore,
[CoreViewFilterOperand.IS_AFTER]: ViewFilterOperand.IsAfter,
[CoreViewFilterOperand.CONTAINS]: ViewFilterOperand.Contains,
[CoreViewFilterOperand.DOES_NOT_CONTAIN]: ViewFilterOperand.DoesNotContain,
[CoreViewFilterOperand.IS_EMPTY]: ViewFilterOperand.IsEmpty,
[CoreViewFilterOperand.IS_NOT_EMPTY]: ViewFilterOperand.IsNotEmpty,
[CoreViewFilterOperand.IS_RELATIVE]: ViewFilterOperand.IsRelative,
[CoreViewFilterOperand.IS_IN_PAST]: ViewFilterOperand.IsInPast,
[CoreViewFilterOperand.IS_IN_FUTURE]: ViewFilterOperand.IsInFuture,
[CoreViewFilterOperand.IS_TODAY]: ViewFilterOperand.IsToday,
[CoreViewFilterOperand.VECTOR_SEARCH]: ViewFilterOperand.VectorSearch,
};
export const convertViewFilterOperandFromCore = (
coreOperand: CoreViewFilterOperand,
): ViewFilterOperand => mappingFromCore[coreOperand];
@@ -1,28 +0,0 @@
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand as CoreViewFilterOperand } from '~/generated-metadata/graphql';
const operandMapping: Record<ViewFilterOperand, CoreViewFilterOperand> = {
[ViewFilterOperand.Is]: CoreViewFilterOperand.IS,
[ViewFilterOperand.IsNotNull]: CoreViewFilterOperand.IS_NOT_NULL,
[ViewFilterOperand.IsNot]: CoreViewFilterOperand.IS_NOT,
[ViewFilterOperand.LessThanOrEqual]: CoreViewFilterOperand.LESS_THAN_OR_EQUAL,
[ViewFilterOperand.GreaterThanOrEqual]:
CoreViewFilterOperand.GREATER_THAN_OR_EQUAL,
[ViewFilterOperand.IsBefore]: CoreViewFilterOperand.IS_BEFORE,
[ViewFilterOperand.IsAfter]: CoreViewFilterOperand.IS_AFTER,
[ViewFilterOperand.Contains]: CoreViewFilterOperand.CONTAINS,
[ViewFilterOperand.DoesNotContain]: CoreViewFilterOperand.DOES_NOT_CONTAIN,
[ViewFilterOperand.IsEmpty]: CoreViewFilterOperand.IS_EMPTY,
[ViewFilterOperand.IsNotEmpty]: CoreViewFilterOperand.IS_NOT_EMPTY,
[ViewFilterOperand.IsRelative]: CoreViewFilterOperand.IS_RELATIVE,
[ViewFilterOperand.IsInPast]: CoreViewFilterOperand.IS_IN_PAST,
[ViewFilterOperand.IsInFuture]: CoreViewFilterOperand.IS_IN_FUTURE,
[ViewFilterOperand.IsToday]: CoreViewFilterOperand.IS_TODAY,
[ViewFilterOperand.VectorSearch]: CoreViewFilterOperand.VECTOR_SEARCH,
};
export const convertViewFilterOperandToCore = (
sharedOperand: ViewFilterOperand,
): CoreViewFilterOperand => {
return operandMapping[sharedOperand];
};
@@ -21,9 +21,9 @@ export const getRecordFilterLabelValue = ({
if (isDateOrDateTimeFilter) {
switch (recordFilter.operand) {
case RecordFilterOperand.IsToday:
case RecordFilterOperand.IsInFuture:
case RecordFilterOperand.IsInPast:
case RecordFilterOperand.IS_TODAY:
case RecordFilterOperand.IS_IN_FUTURE:
case RecordFilterOperand.IS_IN_PAST:
return operandLabelShort;
default:
return `${operandLabelShort} ${recordFilter.displayValue}`;
@@ -2,5 +2,5 @@ import { type RecordFilter } from '@/object-record/record-filter/types/RecordFil
import { ViewFilterOperand } from 'twenty-shared/types';
export const isVectorSearchFilter = (filter: RecordFilter) => {
return filter.operand === ViewFilterOperand.VectorSearch;
return filter.operand === ViewFilterOperand.VECTOR_SEARCH;
};
@@ -4,8 +4,6 @@ import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataIte
import { isSystemSearchVectorField } from '@/object-record/utils/isSystemSearchVectorField';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { convertViewFilterOperandFromCore } from '@/views/utils/convertViewFilterOperandFromCore';
import { type ViewFilterOperand } from 'twenty-shared/types';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { type CoreViewFilter } from '~/generated/graphql';
import { type ViewFilter } from '../types/ViewFilter';
@@ -34,10 +32,7 @@ export const mapViewFiltersToFilters = (
? 'Search'
: availableFieldMetadataItem.label;
const operand =
viewFilter.__typename === 'CoreViewFilter'
? convertViewFilterOperandFromCore(viewFilter.operand)
: (viewFilter.operand as ViewFilterOperand);
const operand = viewFilter.operand;
return {
id: viewFilter.id,
@@ -25,7 +25,7 @@ const BASE_NEW_STEP_FILTER = {
type: 'unknown',
label: '',
value: '',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
displayValue: '',
stepFilterGroupId: '',
stepOutputKey: '',
@@ -163,7 +163,7 @@ export const WorkflowStepFilterValueInput = ({
);
}
if (isDateField && stepFilter.operand === ViewFilterOperand.IsRelative) {
if (isDateField && stepFilter.operand === ViewFilterOperand.IS_RELATIVE) {
return (
<FormRelativeDatePicker
defaultValue={stepFilter.value}
@@ -51,7 +51,7 @@ const CONFIGURED_ACTION: WorkflowFilterAction = {
id: 'filter-1',
stepFilterGroupId: 'filter-group-1',
stepOutputKey: 'company.name',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'Acme',
type: 'string',
},
@@ -26,7 +26,7 @@ const TEXT_STEP_FILTER: StepFilter = {
stepOutputKey: 'company.name',
type: 'text',
value: 'Acme',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
};
const meta: Meta<typeof WorkflowStepFilterColumn> = {
@@ -14,7 +14,7 @@ const DEFAULT_STEP_FILTER: StepFilter = {
stepFilterGroupId: 'filter-group-1',
stepOutputKey: '',
type: 'text',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
value: '',
positionInStepFilterGroup: 0,
};
@@ -15,7 +15,7 @@ const DEFAULT_STEP_FILTER: StepFilter = {
stepFilterGroupId: 'filter-group-1',
stepOutputKey: 'company.name',
type: 'text',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: '',
positionInStepFilterGroup: 0,
};
@@ -25,7 +25,7 @@ const GREATER_THAN_FILTER: StepFilter = {
stepFilterGroupId: 'filter-group-1',
stepOutputKey: 'company.employees',
type: 'number',
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
value: '100',
positionInStepFilterGroup: 0,
};
@@ -15,7 +15,7 @@ const TEXT_FILTER: StepFilter = {
stepFilterGroupId: 'filter-group-1',
stepOutputKey: 'company.name',
type: 'text',
operand: ViewFilterOperand.Contains,
operand: ViewFilterOperand.CONTAINS,
value: 'Acme',
positionInStepFilterGroup: 0,
};
@@ -25,7 +25,7 @@ const NUMBER_FILTER: StepFilter = {
stepFilterGroupId: 'filter-group-1',
stepOutputKey: 'company.employees',
type: 'number',
operand: ViewFilterOperand.GreaterThanOrEqual,
operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
value: '100',
positionInStepFilterGroup: 0,
};
@@ -50,7 +50,7 @@ export const useAddRootStepFilter = () => {
id: v4(),
type: 'unknown',
value: '',
operand: ViewFilterOperand.Is,
operand: ViewFilterOperand.IS,
stepFilterGroupId: newStepFilterGroup.id,
stepOutputKey: '',
positionInStepFilterGroup: 0,
@@ -1,69 +1,69 @@
import { ViewFilterOperand } from 'twenty-shared/types';
const emptyOperands = [
ViewFilterOperand.IsEmpty,
ViewFilterOperand.IsNotEmpty,
ViewFilterOperand.IS_EMPTY,
ViewFilterOperand.IS_NOT_EMPTY,
] as const;
const relationOperands = [
ViewFilterOperand.Is,
ViewFilterOperand.IsNot,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT,
] as const;
const defaultOperands = [
ViewFilterOperand.Is,
ViewFilterOperand.IsNot,
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
] as const;
export const FILTER_OPERANDS_MAP = {
TEXT: [
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
NUMBER: [
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
],
RAW_JSON: [
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
DATE_TIME: [
ViewFilterOperand.Is,
ViewFilterOperand.IsInPast,
ViewFilterOperand.IsInFuture,
ViewFilterOperand.IsToday,
ViewFilterOperand.IsBefore,
ViewFilterOperand.IsAfter,
ViewFilterOperand.IsRelative,
ViewFilterOperand.IS,
ViewFilterOperand.IS_IN_PAST,
ViewFilterOperand.IS_IN_FUTURE,
ViewFilterOperand.IS_TODAY,
ViewFilterOperand.IS_BEFORE,
ViewFilterOperand.IS_AFTER,
ViewFilterOperand.IS_RELATIVE,
...emptyOperands,
],
RATING: [ViewFilterOperand.Is, ViewFilterOperand.IsNot, ...emptyOperands],
RATING: [ViewFilterOperand.IS, ViewFilterOperand.IS_NOT, ...emptyOperands],
RELATION: [...relationOperands, ...emptyOperands],
MULTI_SELECT: [
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
SELECT: [ViewFilterOperand.Is, ViewFilterOperand.IsNot, ...emptyOperands],
SELECT: [ViewFilterOperand.IS, ViewFilterOperand.IS_NOT, ...emptyOperands],
ARRAY: [
ViewFilterOperand.Contains,
ViewFilterOperand.DoesNotContain,
ViewFilterOperand.CONTAINS,
ViewFilterOperand.DOES_NOT_CONTAIN,
...emptyOperands,
],
BOOLEAN: [ViewFilterOperand.Is],
UUID: [ViewFilterOperand.Is],
BOOLEAN: [ViewFilterOperand.IS],
UUID: [ViewFilterOperand.IS],
NUMERIC: [
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
...emptyOperands,
],
};
@@ -71,15 +71,15 @@ export const FILTER_OPERANDS_MAP = {
export const COMPOSITE_FIELD_FILTER_OPERANDS_MAP = {
CURRENCY: {
currencyCode: [
ViewFilterOperand.Is,
ViewFilterOperand.IsNot,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT,
...emptyOperands,
],
amountMicros: [
ViewFilterOperand.GreaterThanOrEqual,
ViewFilterOperand.LessThanOrEqual,
ViewFilterOperand.Is,
ViewFilterOperand.IsNot,
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
ViewFilterOperand.LESS_THAN_OR_EQUAL,
ViewFilterOperand.IS,
ViewFilterOperand.IS_NOT,
...emptyOperands,
],
},
@@ -33,7 +33,7 @@ export const WorkflowAdvancedFilterRecordFilterOperandSelect = ({
? getRecordFilterOperands({
filterType,
subFieldName: filter?.subFieldName,
}).filter((operand) => operand !== RecordFilterOperand.IsRelative)
}).filter((operand) => operand !== RecordFilterOperand.IS_RELATIVE)
: [];
if (isDisabled === true) {
@@ -30,7 +30,6 @@ import {
GraphqlQueryRunnerExceptionCode,
} from 'src/engine/api/graphql/graphql-query-runner/errors/graphql-query-runner.exception';
import { ProcessAggregateHelper } from 'src/engine/api/graphql/graphql-query-runner/helpers/process-aggregate.helper';
import { convertViewFilterOperand } from 'src/engine/api/graphql/graphql-query-runner/utils/convert-view-filter-operands';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ViewFilterGroupService } from 'src/engine/core-modules/view/services/view-filter-group.service';
import { ViewFilterService } from 'src/engine/core-modules/view/services/view-filter.service';
@@ -247,7 +246,7 @@ export class GraphqlQueryGroupByResolverService extends GraphqlQueryBaseResolver
fieldMetadataId: viewFilter.fieldMetadataId,
value: convertViewFilterValueToString(viewFilter.value),
type: getFilterTypeFromFieldType(fieldMetadataItem.type),
operand: convertViewFilterOperand(viewFilter.operand),
operand: viewFilter.operand,
recordFilterGroupId: viewFilter.viewFilterGroupId,
positionInRecordFilterGroup: viewFilter.positionInViewFilterGroup,
subFieldName: viewFilter.subFieldName as CompositeFieldSubFieldName,
@@ -1,44 +0,0 @@
import { ViewFilterOperand as ViewFilterOperandShared } from 'twenty-shared/types';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
export const convertViewFilterOperand = (
operand: ViewFilterOperand,
): ViewFilterOperandShared => {
switch (operand) {
case ViewFilterOperand.IS:
return ViewFilterOperandShared.Is;
case ViewFilterOperand.IS_NOT_NULL:
return ViewFilterOperandShared.IsNotNull;
case ViewFilterOperand.IS_NOT:
return ViewFilterOperandShared.IsNot;
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return ViewFilterOperandShared.LessThanOrEqual;
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return ViewFilterOperandShared.GreaterThanOrEqual;
case ViewFilterOperand.IS_BEFORE:
return ViewFilterOperandShared.IsBefore;
case ViewFilterOperand.IS_AFTER:
return ViewFilterOperandShared.IsAfter;
case ViewFilterOperand.CONTAINS:
return ViewFilterOperandShared.Contains;
case ViewFilterOperand.DOES_NOT_CONTAIN:
return ViewFilterOperandShared.DoesNotContain;
case ViewFilterOperand.IS_EMPTY:
return ViewFilterOperandShared.IsEmpty;
case ViewFilterOperand.IS_NOT_EMPTY:
return ViewFilterOperandShared.IsNotEmpty;
case ViewFilterOperand.IS_RELATIVE:
return ViewFilterOperandShared.IsRelative;
case ViewFilterOperand.IS_IN_PAST:
return ViewFilterOperandShared.IsInPast;
case ViewFilterOperand.IS_IN_FUTURE:
return ViewFilterOperandShared.IsInFuture;
case ViewFilterOperand.IS_TODAY:
return ViewFilterOperandShared.IsToday;
case ViewFilterOperand.VECTOR_SEARCH:
return ViewFilterOperandShared.VectorSearch;
default:
throw new Error(`Invalid view filter operand: ${operand}`);
}
};
@@ -1,9 +1,9 @@
import { Field, InputType } from '@nestjs/graphql';
import GraphQLJSON from 'graphql-type-json';
import { ViewFilterOperand } from 'twenty-shared/types';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type';
@InputType()
@@ -2,9 +2,9 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import { IDField } from '@ptc-org/nestjs-query-graphql';
import GraphQLJSON from 'graphql-type-json';
import { ViewFilterOperand } from 'twenty-shared/types';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type';
registerEnumType(ViewFilterOperand, {
@@ -1,3 +1,4 @@
import { ViewFilterOperand } from 'twenty-shared/types';
import {
Column,
CreateDateColumn,
@@ -15,7 +16,6 @@ import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/inte
import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity';
import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -1,18 +0,0 @@
export enum ViewFilterOperand {
IS = 'IS',
IS_NOT_NULL = 'IS_NOT_NULL',
IS_NOT = 'IS_NOT',
LESS_THAN_OR_EQUAL = 'LESS_THAN_OR_EQUAL',
GREATER_THAN_OR_EQUAL = 'GREATER_THAN_OR_EQUAL',
IS_BEFORE = 'IS_BEFORE',
IS_AFTER = 'IS_AFTER',
CONTAINS = 'CONTAINS',
DOES_NOT_CONTAIN = 'DOES_NOT_CONTAIN',
IS_EMPTY = 'IS_EMPTY',
IS_NOT_EMPTY = 'IS_NOT_EMPTY',
IS_RELATIVE = 'IS_RELATIVE',
IS_IN_PAST = 'IS_IN_PAST',
IS_IN_FUTURE = 'IS_IN_FUTURE',
IS_TODAY = 'IS_TODAY',
VECTOR_SEARCH = 'VECTOR_SEARCH',
}
@@ -1,10 +1,10 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { ViewFilterOperand } from 'twenty-shared/types';
import { type Repository } from 'typeorm';
import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import {
ViewFilterException,
ViewFilterExceptionCode,
@@ -1,5 +1,4 @@
import { isString } from '@sniptt/guards';
import { type ViewFilterOperand as SharedViewFilterOperand } from 'twenty-shared/types';
import { type DataSource, type QueryRunner } from 'typeorm';
import { v4 } from 'uuid';
@@ -29,7 +28,6 @@ import { workflowRunsAllView } from 'src/engine/workspace-manager/standard-objec
import { workflowVersionsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view';
import { workflowsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
import { convertViewFilterOperandToCoreOperand } from 'src/modules/view/utils/convert-view-filter-operand-to-core-operand.util';
type PrefillCoreViewsArgs = {
coreDataSource: DataSource;
@@ -176,9 +174,7 @@ const createCoreViews = async (
viewDefinition.filters.map((filter) => ({
fieldMetadataId: filter.fieldMetadataId,
viewId: viewDefinition.id,
operand: convertViewFilterOperandToCoreOperand(
filter.operand as SharedViewFilterOperand,
),
operand: filter.operand,
value: filter.value,
workspaceId,
}));
@@ -1,4 +1,5 @@
import { type MessageDescriptor } from '@lingui/core';
import { type ViewFilterOperand } from 'twenty-shared/types';
import { type AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { type ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
@@ -26,7 +27,7 @@ export interface ViewDefinition {
filters?: {
fieldMetadataId: string;
displayValue: string;
operand: string;
operand: ViewFilterOperand;
value: string;
}[];
groups?: {
@@ -1,4 +1,5 @@
import { msg } from '@lingui/core/macro';
import { ViewFilterOperand } from 'twenty-shared/types';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import {
@@ -34,7 +35,7 @@ export const tasksAssignedToMeView = (
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.assignee,
)?.id ?? '',
displayValue: 'Me',
operand: 'is',
operand: ViewFilterOperand.IS,
value: JSON.stringify({
isCurrentWorkspaceMemberSelected: true,
selectedRecordIds: [],
@@ -1,30 +1,26 @@
import { ViewFilterOperand as SharedViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
const operandMapping: Record<SharedViewFilterOperand, ViewFilterOperand> = {
[SharedViewFilterOperand.Is]: ViewFilterOperand.IS,
[SharedViewFilterOperand.IsNotNull]: ViewFilterOperand.IS_NOT_NULL,
[SharedViewFilterOperand.IsNot]: ViewFilterOperand.IS_NOT,
[SharedViewFilterOperand.LessThanOrEqual]:
ViewFilterOperand.LESS_THAN_OR_EQUAL,
[SharedViewFilterOperand.GreaterThanOrEqual]:
ViewFilterOperand.GREATER_THAN_OR_EQUAL,
[SharedViewFilterOperand.IsBefore]: ViewFilterOperand.IS_BEFORE,
[SharedViewFilterOperand.IsAfter]: ViewFilterOperand.IS_AFTER,
[SharedViewFilterOperand.Contains]: ViewFilterOperand.CONTAINS,
[SharedViewFilterOperand.DoesNotContain]: ViewFilterOperand.DOES_NOT_CONTAIN,
[SharedViewFilterOperand.IsEmpty]: ViewFilterOperand.IS_EMPTY,
[SharedViewFilterOperand.IsNotEmpty]: ViewFilterOperand.IS_NOT_EMPTY,
[SharedViewFilterOperand.IsRelative]: ViewFilterOperand.IS_RELATIVE,
[SharedViewFilterOperand.IsInPast]: ViewFilterOperand.IS_IN_PAST,
[SharedViewFilterOperand.IsInFuture]: ViewFilterOperand.IS_IN_FUTURE,
[SharedViewFilterOperand.IsToday]: ViewFilterOperand.IS_TODAY,
[SharedViewFilterOperand.VectorSearch]: ViewFilterOperand.VECTOR_SEARCH,
const operandMapping: Record<string, ViewFilterOperand> = {
Is: ViewFilterOperand.IS,
IsNotNull: ViewFilterOperand.IS_NOT_NULL,
IsNot: ViewFilterOperand.IS_NOT,
LessThanOrEqual: ViewFilterOperand.LESS_THAN_OR_EQUAL,
GreaterThanOrEqual: ViewFilterOperand.GREATER_THAN_OR_EQUAL,
IsBefore: ViewFilterOperand.IS_BEFORE,
IsAfter: ViewFilterOperand.IS_AFTER,
Contains: ViewFilterOperand.CONTAINS,
DoesNotContain: ViewFilterOperand.DOES_NOT_CONTAIN,
IsEmpty: ViewFilterOperand.IS_EMPTY,
IsNotEmpty: ViewFilterOperand.IS_NOT_EMPTY,
IsRelative: ViewFilterOperand.IS_RELATIVE,
IsInPast: ViewFilterOperand.IS_IN_PAST,
IsInFuture: ViewFilterOperand.IS_IN_FUTURE,
IsToday: ViewFilterOperand.IS_TODAY,
VectorSearch: ViewFilterOperand.VECTOR_SEARCH,
};
export const convertViewFilterOperandToCoreOperand = (
sharedOperand: SharedViewFilterOperand,
sharedOperand: string,
): ViewFilterOperand => {
return operandMapping[sharedOperand];
};
@@ -122,14 +122,14 @@ function contains(leftValue: unknown, rightValue: unknown): boolean {
function evaluateTextAndArrayFilter(filter: ResolvedFilter): boolean {
switch (filter.operand) {
case ViewFilterOperand.Contains:
case ViewFilterOperand.CONTAINS:
return contains(filter.leftOperand, filter.rightOperand);
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.DOES_NOT_CONTAIN:
return !contains(filter.leftOperand, filter.rightOperand);
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return !isNotEmptyTextOrArray(filter.leftOperand);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNotEmptyTextOrArray(filter.leftOperand);
default:
@@ -145,7 +145,7 @@ function isNotEmptyTextOrArray(value: unknown): boolean {
function evaluateBooleanFilter(filter: ResolvedFilter): boolean {
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return Boolean(filter.leftOperand) === Boolean(filter.rightOperand);
default:
throw new Error(
@@ -158,47 +158,47 @@ function evaluateDateFilter(filter: ResolvedFilter): boolean {
const dateLeftValue = new Date(String(filter.leftOperand));
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return (
dateLeftValue.getDate() ===
new Date(String(filter.rightOperand)).getDate()
);
case ViewFilterOperand.IsInPast:
case ViewFilterOperand.IS_IN_PAST:
return dateLeftValue.getTime() < Date.now();
case ViewFilterOperand.IsInFuture:
case ViewFilterOperand.IS_IN_FUTURE:
return dateLeftValue.getTime() > Date.now();
case ViewFilterOperand.IsToday:
case ViewFilterOperand.IS_TODAY:
return dateLeftValue.toDateString() === new Date().toDateString();
case ViewFilterOperand.IsBefore:
case ViewFilterOperand.IS_BEFORE:
return (
dateLeftValue.getTime() <
new Date(String(filter.rightOperand)).getTime()
);
case ViewFilterOperand.IsAfter:
case ViewFilterOperand.IS_AFTER:
return (
dateLeftValue.getTime() >
new Date(String(filter.rightOperand)).getTime()
);
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return (
filter.leftOperand === null ||
filter.leftOperand === undefined ||
filter.leftOperand === ''
);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return (
filter.leftOperand !== null &&
filter.leftOperand !== undefined &&
filter.leftOperand !== ''
);
case ViewFilterOperand.IsRelative:
case ViewFilterOperand.IS_RELATIVE:
return parseAndEvaluateRelativeDateFilter({
dateToCheck: dateLeftValue,
relativeDateString: String(filter.rightOperand),
@@ -213,9 +213,9 @@ function evaluateDateFilter(filter: ResolvedFilter): boolean {
function evaluateUuidFilter(filter: ResolvedFilter): boolean {
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return filter.leftOperand === filter.rightOperand;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return filter.leftOperand !== filter.rightOperand;
default:
throw new Error(
@@ -237,9 +237,9 @@ function evaluateRelationFilter(filter: ResolvedFilter): boolean {
: filter.rightOperand;
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return leftValue === rightValue;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return leftValue !== rightValue;
default:
throw new Error(
@@ -251,13 +251,13 @@ function evaluateRelationFilter(filter: ResolvedFilter): boolean {
function evaluateCurrencyFilter(filter: ResolvedFilter): boolean {
if (filter.compositeFieldSubFieldName === 'currencyCode') {
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return filter.leftOperand === filter.rightOperand;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return filter.leftOperand !== filter.rightOperand;
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return !isNonEmptyString(filter.leftOperand);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNonEmptyString(filter.leftOperand);
default:
throw new Error(
@@ -274,16 +274,16 @@ function evaluateNumberFilter(filter: ResolvedFilter): boolean {
const rightValue = filter.rightOperand;
switch (filter.operand) {
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return Number(leftValue) >= Number(rightValue);
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return Number(leftValue) <= Number(rightValue);
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return !isNonEmptyString(leftValue);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNonEmptyString(leftValue);
default:
@@ -298,21 +298,21 @@ function evaluateDefaultFilter(filter: ResolvedFilter): boolean {
const rightValue = filter.rightOperand;
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return leftValue == rightValue;
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return leftValue != rightValue;
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return !isNotEmptyTextOrArray(leftValue);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNotEmptyTextOrArray(leftValue);
case ViewFilterOperand.Contains:
case ViewFilterOperand.CONTAINS:
return contains(leftValue, rightValue);
case ViewFilterOperand.DoesNotContain:
case ViewFilterOperand.DOES_NOT_CONTAIN:
return !contains(leftValue, rightValue);
case ViewFilterOperand.GreaterThanOrEqual:
case ViewFilterOperand.GREATER_THAN_OR_EQUAL:
return Number(leftValue) >= Number(rightValue);
case ViewFilterOperand.LessThanOrEqual:
case ViewFilterOperand.LESS_THAN_OR_EQUAL:
return Number(leftValue) <= Number(rightValue);
default:
throw new Error(
@@ -323,14 +323,14 @@ function evaluateDefaultFilter(filter: ResolvedFilter): boolean {
function evaluateSelectFilter(filter: ResolvedFilter): boolean {
switch (filter.operand) {
case ViewFilterOperand.Is:
case ViewFilterOperand.IS:
return contains(filter.leftOperand, filter.rightOperand);
case ViewFilterOperand.IsNot:
case ViewFilterOperand.IS_NOT:
return !contains(filter.leftOperand, filter.rightOperand);
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return !isNotEmptyTextOrArray(filter.leftOperand);
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNotEmptyTextOrArray(filter.leftOperand);
default:
throw new Error(
@@ -9,8 +9,8 @@ import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete
import { groupByOperationFactory } from 'test/integration/graphql/utils/group-by-operation-factory.util';
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
import { findManyObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata.util';
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { ViewFilterGroupLogicalOperator } from 'src/modules/view/standard-objects/view-filter-group.workspace-entity';
@@ -19,10 +19,9 @@ import {
assertViewFilterStructure,
cleanupViewRecords,
} from 'test/integration/utils/view-test.util';
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, ViewFilterOperand } from 'twenty-shared/types';
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import {
ViewFilterExceptionMessageKey,
generateViewFilterExceptionMessage,
@@ -1,3 +1,5 @@
import { ViewFilterOperand } from 'twenty-shared/types';
import { type UpdateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/update-view-field.input';
import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity';
import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity';
@@ -6,7 +8,6 @@ import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view
import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity';
import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
import { ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in';
import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction';
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
@@ -5,6 +5,7 @@ import { createOneObjectMetadata } from 'test/integration/metadata/suites/object
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
import {
createTestViewFilterWithRestApi,
createTestViewWithRestApi,
@@ -14,12 +15,11 @@ import { type EachTestingContext } from 'twenty-shared/testing';
import {
type EnumFieldMetadataType,
FieldMetadataType,
ViewFilterOperand,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
import { type ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type';
import {
@@ -20,9 +20,7 @@ import {
assertViewFilterStructure,
cleanupViewRecords,
} from 'test/integration/utils/view-test.util';
import { FieldMetadataType } from 'twenty-shared/types';
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
import { FieldMetadataType, ViewFilterOperand } from 'twenty-shared/types';
describe('View Filter REST API', () => {
let testObjectMetadataId: string;
@@ -1,18 +1,18 @@
export enum ViewFilterOperand {
Is = 'is',
IsNotNull = 'isNotNull',
IsNot = 'isNot',
LessThanOrEqual = 'lessThan', // TODO: we could change this to 'lessThanOrEqual' for consistency but it would require a migration
GreaterThanOrEqual = 'greaterThan', // TODO: we could change this to 'greaterThanOrEqual' for consistency but it would require a migration
IsBefore = 'isBefore',
IsAfter = 'isAfter',
Contains = 'contains',
DoesNotContain = 'doesNotContain',
IsEmpty = 'isEmpty',
IsNotEmpty = 'isNotEmpty',
IsRelative = 'isRelative',
IsInPast = 'isInPast',
IsInFuture = 'isInFuture',
IsToday = 'isToday',
VectorSearch = 'search',
IS = 'IS',
IS_NOT_NULL = 'IS_NOT_NULL',
IS_NOT = 'IS_NOT',
LESS_THAN_OR_EQUAL = 'LESS_THAN_OR_EQUAL', // TODO: we could change this to 'lessThanOrEqual' for consistency but it would require a migration
GREATER_THAN_OR_EQUAL = 'GREATER_THAN_OR_EQUAL', // TODO: we could change this to 'greaterThanOrEqual' for consistency but it would require a migration
IS_BEFORE = 'IS_BEFORE',
IS_AFTER = 'IS_AFTER',
CONTAINS = 'CONTAINS',
DOES_NOT_CONTAIN = 'DOES_NOT_CONTAIN',
IS_EMPTY = 'IS_EMPTY',
IS_NOT_EMPTY = 'IS_NOT_EMPTY',
IS_RELATIVE = 'IS_RELATIVE',
IS_IN_PAST = 'IS_IN_PAST',
IS_IN_FUTURE = 'IS_IN_FUTURE',
IS_TODAY = 'IS_TODAY',
VECTOR_SEARCH = 'VECTOR_SEARCH',
}
@@ -12,9 +12,9 @@ export const checkIfShouldSkipFiltering = ({
const isAnEmptinessOperand = isEmptinessOperand(recordFilter.operand);
const isDateOperandWithoutValue = [
RecordFilterOperand.IsInPast,
RecordFilterOperand.IsInFuture,
RecordFilterOperand.IsToday,
RecordFilterOperand.IS_IN_PAST,
RecordFilterOperand.IS_IN_FUTURE,
RecordFilterOperand.IS_TODAY,
].includes(recordFilter.operand);
const isFilterValueEmpty =
@@ -25,7 +25,7 @@ export const computeGqlOperationFilterForEmails = ({
switch (subFieldName) {
case 'primaryEmail': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
primaryEmail: {
@@ -33,7 +33,7 @@ export const computeGqlOperationFilterForEmails = ({
},
} satisfies EmailsFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -51,7 +51,7 @@ export const computeGqlOperationFilterForEmails = ({
}
case 'additionalEmails': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
additionalEmails: {
@@ -59,7 +59,7 @@ export const computeGqlOperationFilterForEmails = ({
},
} satisfies EmailsFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
or: [
{
@@ -97,7 +97,7 @@ export const computeGqlOperationFilterForEmails = ({
}
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
or: [
{
@@ -116,7 +116,7 @@ export const computeGqlOperationFilterForEmails = ({
},
],
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
and: [
{
@@ -19,7 +19,7 @@ export const computeGqlOperationFilterForLinks = ({
case 'primaryLinkLabel':
case 'primaryLinkUrl': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
[subFieldName]: {
@@ -27,7 +27,7 @@ export const computeGqlOperationFilterForLinks = ({
},
} satisfies LinksFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -46,7 +46,7 @@ export const computeGqlOperationFilterForLinks = ({
}
case 'secondaryLinks': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
secondaryLinks: {
@@ -54,7 +54,7 @@ export const computeGqlOperationFilterForLinks = ({
},
} satisfies LinksFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
or: [
{
@@ -91,7 +91,7 @@ export const computeGqlOperationFilterForLinks = ({
}
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
or: [
{
@@ -117,7 +117,7 @@ export const computeGqlOperationFilterForLinks = ({
},
],
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
and: [
{
@@ -1,7 +1,7 @@
import { ViewFilterOperand as RecordFilterOperand } from '@/types';
export const isEmptinessOperand = (operand: RecordFilterOperand): boolean => {
return [RecordFilterOperand.IsEmpty, RecordFilterOperand.IsNotEmpty].includes(
return [RecordFilterOperand.IS_EMPTY, RecordFilterOperand.IS_NOT_EMPTY].includes(
operand,
);
};
@@ -105,13 +105,13 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
switch (filterType) {
case 'TEXT':
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
ilike: `%${recordFilter.value}%`,
} as StringFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -127,7 +127,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'TS_VECTOR':
switch (recordFilter.operand) {
case RecordFilterOperand.VectorSearch:
case RecordFilterOperand.VECTOR_SEARCH:
return {
[correspondingFieldMetadataItem.name]: {
search: recordFilter.value,
@@ -140,13 +140,13 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'RAW_JSON':
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
like: `%${recordFilter.value}%`,
} as RawJsonFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -167,28 +167,28 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
resolvedFilterValue instanceof Date ? resolvedFilterValue : now;
switch (recordFilter.operand) {
case RecordFilterOperand.IsAfter: {
case RecordFilterOperand.IS_AFTER: {
return {
[correspondingFieldMetadataItem.name]: {
gt: date.toISOString(),
} as DateFilter,
};
}
case RecordFilterOperand.IsBefore: {
case RecordFilterOperand.IS_BEFORE: {
return {
[correspondingFieldMetadataItem.name]: {
lt: date.toISOString(),
} as DateFilter,
};
}
case RecordFilterOperand.IsRelative: {
case RecordFilterOperand.IS_RELATIVE: {
const dateRange = z
.object({ start: z.date(), end: z.date() })
.safeParse(resolvedFilterValue).data;
const defaultDateRange = resolveDateViewFilterValue({
value: 'PAST_1_DAY',
operand: RecordFilterOperand.IsRelative,
operand: RecordFilterOperand.IS_RELATIVE,
});
if (!defaultDateRange) {
@@ -212,7 +212,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
],
};
}
case RecordFilterOperand.Is: {
case RecordFilterOperand.IS: {
const isValid = resolvedFilterValue instanceof Date;
const date = isValid ? resolvedFilterValue : now;
@@ -231,19 +231,19 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
],
};
}
case RecordFilterOperand.IsInPast:
case RecordFilterOperand.IS_IN_PAST:
return {
[correspondingFieldMetadataItem.name]: {
lte: now.toISOString(),
} as DateFilter,
};
case RecordFilterOperand.IsInFuture:
case RecordFilterOperand.IS_IN_FUTURE:
return {
[correspondingFieldMetadataItem.name]: {
gte: now.toISOString(),
} as DateFilter,
};
case RecordFilterOperand.IsToday: {
case RecordFilterOperand.IS_TODAY: {
return {
and: [
{
@@ -267,13 +267,13 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'RATING':
switch (recordFilter.operand) {
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return {
[correspondingFieldMetadataItem.name]: {
eq: convertRatingToRatingValue(parseFloat(recordFilter.value)),
} as RatingFilter,
};
case RecordFilterOperand.GreaterThanOrEqual:
case RecordFilterOperand.GREATER_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
in: convertGreaterThanOrEqualRatingToArrayOfRatingValues(
@@ -281,7 +281,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
),
} as RatingFilter,
};
case RecordFilterOperand.LessThanOrEqual:
case RecordFilterOperand.LESS_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
in: convertLessThanOrEqualRatingToArrayOfRatingValues(
@@ -296,19 +296,19 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'NUMBER':
switch (recordFilter.operand) {
case RecordFilterOperand.GreaterThanOrEqual:
case RecordFilterOperand.GREATER_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
gte: parseFloat(recordFilter.value),
} as FloatFilter,
};
case RecordFilterOperand.LessThanOrEqual:
case RecordFilterOperand.LESS_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
lte: parseFloat(recordFilter.value),
} as FloatFilter,
};
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return {
[correspondingFieldMetadataItem.name]: {
eq: parseFloat(recordFilter.value),
@@ -340,13 +340,13 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
if (!isDefined (recordIds) || recordIds.length === 0) return;
switch (recordFilter.operand) {
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return {
[correspondingFieldMetadataItem.name + 'Id']: {
in: recordIds,
} as RelationFilter,
};
case RecordFilterOperand.IsNot: {
case RecordFilterOperand.IS_NOT: {
if (!isDefined (recordIds) || recordIds.length === 0) return;
return {
or: [
@@ -392,9 +392,9 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
};
switch (recordFilter.operand) {
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return gqlFilter;
case RecordFilterOperand.IsNot:
case RecordFilterOperand.IS_NOT:
return {
not: gqlFilter,
};
@@ -412,25 +412,25 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
!isSubFieldFilter
) {
switch (recordFilter.operand) {
case RecordFilterOperand.GreaterThanOrEqual:
case RecordFilterOperand.GREATER_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
amountMicros: { gte: parseFloat(recordFilter.value) * 1000000 },
} as CurrencyFilter,
};
case RecordFilterOperand.LessThanOrEqual:
case RecordFilterOperand.LESS_THAN_OR_EQUAL:
return {
[correspondingFieldMetadataItem.name]: {
amountMicros: { lte: parseFloat(recordFilter.value) * 1000000 },
} as CurrencyFilter,
};
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return {
[correspondingFieldMetadataItem.name]: {
amountMicros: { eq: parseFloat(recordFilter.value) * 1000000 },
} as CurrencyFilter,
};
case RecordFilterOperand.IsNot:
case RecordFilterOperand.IS_NOT:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -465,7 +465,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
['firstName', 'lastName'],
);
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
if (!isSubFieldFilter) {
return {
or: fullNameFilters,
@@ -479,7 +479,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
};
}
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
if (!isSubFieldFilter) {
return {
and: fullNameFilters.map((filter) => {
@@ -507,7 +507,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'ADDRESS':
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
if (!isSubFieldFilter) {
return {
or: [
@@ -582,7 +582,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
};
}
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
if (!isSubFieldFilter) {
return {
and: [
@@ -778,7 +778,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
const nonEmptyOptions = options.filter((option: string) => option !== '');
switch (recordFilter.operand) {
case RecordFilterOperand.Contains: {
case RecordFilterOperand.CONTAINS: {
const conditions = [];
if (nonEmptyOptions.length > 0) {
@@ -799,7 +799,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
return conditions.length === 1 ? conditions[0] : { or: conditions };
}
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
or: [
{
@@ -836,7 +836,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
const nonEmptyOptions = options.filter((option: string) => option !== '');
switch (recordFilter.operand) {
case RecordFilterOperand.Is: {
case RecordFilterOperand.IS: {
const conditions = [];
if (nonEmptyOptions.length > 0) {
@@ -857,7 +857,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
return conditions.length === 1 ? conditions[0] : { or: conditions };
}
case RecordFilterOperand.IsNot: {
case RecordFilterOperand.IS_NOT: {
const conditions = [];
if (nonEmptyOptions.length > 0) {
@@ -890,13 +890,13 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'ARRAY': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
containsIlike: `%${recordFilter.value}%`,
} as ArrayFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -913,7 +913,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
case 'ACTOR': {
if (subFieldName === 'source') {
switch (recordFilter.operand) {
case RecordFilterOperand.Is: {
case RecordFilterOperand.IS: {
if (recordFilter.value === '[]') {
return;
}
@@ -928,7 +928,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
};
}
case RecordFilterOperand.IsNot: {
case RecordFilterOperand.IS_NOT: {
if (recordFilter.value === '[]') {
return;
}
@@ -960,7 +960,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
or: [
{
@@ -972,7 +972,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
],
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
and: [
{
@@ -1013,7 +1013,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
or: [
{
@@ -1039,7 +1039,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
],
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
and: [
{
@@ -1094,7 +1094,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
switch (subFieldName) {
case 'additionalPhones': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
or: [
{
@@ -1106,7 +1106,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
],
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
or: [
{
@@ -1135,7 +1135,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'primaryPhoneNumber': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
primaryPhoneNumber: {
@@ -1143,7 +1143,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
} as PhonesFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -1161,7 +1161,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
}
case 'primaryPhoneCallingCode': {
switch (recordFilter.operand) {
case RecordFilterOperand.Contains:
case RecordFilterOperand.CONTAINS:
return {
[correspondingFieldMetadataItem.name]: {
primaryPhoneCallingCode: {
@@ -1169,7 +1169,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
},
} as PhonesFilter,
};
case RecordFilterOperand.DoesNotContain:
case RecordFilterOperand.DOES_NOT_CONTAIN:
return {
not: {
[correspondingFieldMetadataItem.name]: {
@@ -1204,7 +1204,7 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
if (!isDefined (recordIds) || recordIds.length === 0) return;
switch (recordFilter.operand) {
case RecordFilterOperand.Is:
case RecordFilterOperand.IS:
return {
[correspondingFieldMetadataItem.name]: {
in: recordIds,
@@ -392,9 +392,9 @@ export const getEmptyRecordGqlOperationFilter = ({
}
switch (operand) {
case ViewFilterOperand.IsEmpty:
case ViewFilterOperand.IS_EMPTY:
return emptyRecordFilter;
case ViewFilterOperand.IsNotEmpty:
case ViewFilterOperand.IS_NOT_EMPTY:
return {
not: emptyRecordFilter,
};
@@ -165,7 +165,7 @@ const resolveVariableDateViewFilterValue = (value?: string | null) => {
};
export type ResolvedDateViewFilterValue<O extends ViewFilterOperand> =
O extends ViewFilterOperand.IsRelative
O extends ViewFilterOperand.IS_RELATIVE
? ReturnType<typeof resolveVariableDateViewFilterValue>
: Date | null;
@@ -176,7 +176,7 @@ export const resolveDateViewFilterValue = <O extends ViewFilterOperand>(
): ResolvedDateViewFilterValue<O> => {
if (!viewFilter.value) return null;
if (viewFilter.operand === ViewFilterOperand.IsRelative) {
if (viewFilter.operand === ViewFilterOperand.IS_RELATIVE) {
return resolveVariableDateViewFilterValue(
viewFilter.value,
) as ResolvedDateViewFilterValue<O>;