diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx index fccd79aac..164f88aa7 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx @@ -94,7 +94,7 @@ export const AdvancedFilterRecordFilterOperandSelect = ({ /> } dropdownComponents={ - + ); diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx index 3df320b64..7f5a52cc4 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx @@ -83,17 +83,31 @@ export const AdvancedFilterValueInput = ({ ? ({ y: -33, x: 0 } satisfies DropdownOffset) : DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET; - const showFilterTextInput = - (isDefined(filterType) && - (TEXT_FILTER_TYPES.includes(filterType) || - NUMBER_FILTER_TYPES.includes(filterType))) || - isExpectedSubFieldName( - FieldMetadataType.CURRENCY, - 'amountMicros', - recordFilter.subFieldName, - ) || - (filterType === 'ADDRESS' && - subFieldNameUsedInDropdown !== 'addressCountry'); + const isFilterableByTextValue = + isDefined(filterType) && + (TEXT_FILTER_TYPES.includes(filterType) || + NUMBER_FILTER_TYPES.includes(filterType)); + + const isCurrencyAmountMicrosFilter = isExpectedSubFieldName( + FieldMetadataType.CURRENCY, + 'amountMicros', + recordFilter.subFieldName, + ); + + const isAddressFilterOnSubFieldOtherThanCountry = + filterType === 'ADDRESS' && subFieldNameUsedInDropdown !== 'addressCountry'; + + const isActorNameFilter = isExpectedSubFieldName( + FieldMetadataType.ACTOR, + 'name', + recordFilter.subFieldName, + ); + + const showFilterTextInputInsteadOfDropdown = + isFilterableByTextValue || + isCurrencyAmountMicrosFilter || + isAddressFilterOnSubFieldOtherThanCountry || + isActorNameFilter; return ( @@ -103,7 +117,7 @@ export const AdvancedFilterValueInput = ({ - ) : showFilterTextInput ? ( + ) : showFilterTextInputInsteadOfDropdown ? ( ) : ( )} - {filterType === 'ACTOR' && - (isActorSourceCompositeFilter || isNotASubFieldFilter ? ( - <> - - - ) : ( - <> - - - ))} + {filterType === 'ACTOR' && ( + <> + + + )} {filterType === 'ADDRESS' && (isNotASubFieldFilter ? ( <> diff --git a/packages/twenty-front/src/modules/object-record/record-filter/constants/IconNameBySubField.ts b/packages/twenty-front/src/modules/object-record/record-filter/constants/IconNameBySubField.ts index dca90d8c4..1fdebd24e 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/constants/IconNameBySubField.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/constants/IconNameBySubField.ts @@ -5,4 +5,6 @@ export const ICON_NAME_BY_SUB_FIELD: Partial< > = { currencyCode: 'IconCurrencyDollar', amountMicros: 'IconNumber95Small', + name: 'IconAlignJustified', + source: 'IconFileArrowLeft', }; diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/computeViewRecordGqlOperationFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/computeViewRecordGqlOperationFilter.ts index 9d1e9758f..a529780c3 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/computeViewRecordGqlOperationFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/computeViewRecordGqlOperationFilter.ts @@ -927,73 +927,139 @@ export const computeFilterRecordGqlOperationFilter = ({ ); } } - // TODO: fix this with a new composite field in ViewFilter entity case 'ACTOR': { - switch (filter.operand) { - case RecordFilterOperand.Is: { - if (filter.value === '[]') { - return; - } + if (isSubFieldFilter) { + switch (subFieldName) { + case 'source': { + switch (filter.operand) { + case RecordFilterOperand.Is: { + if (filter.value === '[]') { + return; + } - const parsedRecordIds = JSON.parse(filter.value) as string[]; + const parsedSources = JSON.parse(filter.value) as string[]; - return { - [correspondingField.name]: { - source: { - in: parsedRecordIds, - } as RelationFilter, - }, - }; - } - case RecordFilterOperand.IsNot: { - if (filter.value === '[]') { - return; - } - - const parsedRecordIds = JSON.parse(filter.value) as string[]; - - if (parsedRecordIds.length === 0) return; - - return { - not: { - [correspondingField.name]: { - source: { - in: parsedRecordIds, - } as RelationFilter, - }, - }, - }; - } - case RecordFilterOperand.Contains: - return { - or: [ - { - [correspondingField.name]: { - name: { - ilike: `%${filter.value}%`, - }, - } as ActorFilter, - }, - ], - }; - case RecordFilterOperand.DoesNotContain: - return { - and: [ - { - not: { + return { [correspondingField.name]: { - name: { - ilike: `%${filter.value}%`, + source: { + in: parsedSources, + } satisfies RelationFilter, + }, + }; + } + case RecordFilterOperand.IsNot: { + if (filter.value === '[]') { + return; + } + + const parsedSources = JSON.parse(filter.value) as string[]; + + if (parsedSources.length === 0) return; + + return { + not: { + [correspondingField.name]: { + source: { + in: parsedSources, + } satisfies RelationFilter, }, - } as ActorFilter, + }, + }; + } + default: + throw new Error( + `Unknown operand ${filter.operand} for ${filter.label} filter`, + ); + } + } + case 'name': { + switch (filter.operand) { + case RecordFilterOperand.Contains: + return { + or: [ + { + [correspondingField.name]: { + name: { + ilike: `%${filter.value}%`, + }, + } satisfies ActorFilter, + }, + ], + }; + case RecordFilterOperand.DoesNotContain: + return { + and: [ + { + not: { + [correspondingField.name]: { + name: { + ilike: `%${filter.value}%`, + }, + } satisfies ActorFilter, + }, + }, + ], + }; + default: + throw new Error( + `Unknown operand ${filter.operand} for ${filter.label} filter`, + ); + } + } + } + break; + } else { + if (filter.value === '[]') { + return; + } + + const parsedSources = JSON.parse(filter.value) as string[]; + + if (parsedSources.length === 0) return; + + switch (filter.operand) { + case RecordFilterOperand.Contains: + return { + or: [ + { + [correspondingField.name]: { + source: { + in: parsedSources, + }, + } satisfies ActorFilter, }, - }, - ], - }; - default: - throw new Error( - `Unknown operand ${filter.operand} for ${filter.label} filter`, - ); + ], + }; + case RecordFilterOperand.DoesNotContain: + return { + and: [ + { + or: [ + { + not: { + [correspondingField.name]: { + source: { + in: parsedSources, + }, + } satisfies ActorFilter, + }, + }, + { + [correspondingField.name]: { + source: { + is: 'NULL', + }, + } satisfies ActorFilter, + }, + ], + }, + ], + }; + default: + throw new Error( + `Unknown operand ${filter.operand} for ${filter.label} filter`, + ); + } } } case 'EMAILS': diff --git a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsCompositeFieldTypeConfigs.ts b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsCompositeFieldTypeConfigs.ts index 0f700d998..ef8bd887d 100644 --- a/packages/twenty-front/src/modules/settings/data-model/constants/SettingsCompositeFieldTypeConfigs.ts +++ b/packages/twenty-front/src/modules/settings/data-model/constants/SettingsCompositeFieldTypeConfigs.ts @@ -177,8 +177,8 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = { label: 'Actor', Icon: IllustrationIconSetting, category: 'Basic', - subFields: ['source'], - filterableSubFields: ['source'], + subFields: ['source', 'name'], + filterableSubFields: ['source', 'name'], labelBySubField: { source: 'Source', name: 'Name', diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx index b7225195e..89d4e0f6d 100644 --- a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx @@ -65,6 +65,7 @@ export const EditableFilterDropdownButton = ({ dropdownOffset={{ y: 8, x: 0 }} dropdownPlacement="bottom-start" onClickOutside={handleDropdownClickOutside} + dropdownWidth={200} /> );