diff --git a/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts b/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts
index 72573ea21..6c1615b17 100644
--- a/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts
+++ b/packages/twenty-front/src/modules/object-record/graphql/types/RecordGqlOperationFilter.ts
@@ -92,6 +92,7 @@ export type LinksFilter = {
export type ActorFilter = {
name?: StringFilter;
+ source?: IsFilter;
};
export type EmailsFilter = {
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
index da02a28a6..28f82a4e7 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
@@ -2,6 +2,11 @@ import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-d
import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
+
+import { ObjectFilterDropdownRecordSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect';
+import { ObjectFilterDropdownSourceSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect';
+import { ObjectFilterDropdownTextSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput';
+import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect';
@@ -11,8 +16,6 @@ import { ObjectFilterDropdownNumberInput } from './ObjectFilterDropdownNumberInp
import { ObjectFilterDropdownOperandButton } from './ObjectFilterDropdownOperandButton';
import { ObjectFilterDropdownOperandSelect } from './ObjectFilterDropdownOperandSelect';
import { ObjectFilterDropdownOptionSelect } from './ObjectFilterDropdownOptionSelect';
-import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect';
-import { ObjectFilterDropdownTextSearchInput } from './ObjectFilterDropdownTextSearchInput';
const StyledContainer = styled.div`
position: relative;
@@ -113,6 +116,12 @@ export const MultipleFiltersDropdownContent = ({
>
)}
+ {filterDefinitionUsedInDropdown.type === 'SOURCE' && (
+ <>
+
+
+ >
+ )}
{filterDefinitionUsedInDropdown.type === 'SELECT' && (
<>
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
index f0c2d66cd..15465b67d 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
@@ -1,17 +1,15 @@
import styled from '@emotion/styled';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
-import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
-
-import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
+import { ObjectFilterSelectMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterSelectMenu';
+import { ObjectFilterSelectSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterSelectSubMenu';
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter';
-import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
-import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
-import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
+import { currentSubMenuState } from '@/object-record/object-filter-dropdown/states/subMenuStates';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
+import { useRecoilState } from 'recoil';
import { isDefined } from 'twenty-ui';
export const StyledInput = styled.input`
@@ -47,6 +45,9 @@ export const ObjectFilterDropdownFilterSelect = () => {
availableFilterDefinitionsComponentState,
);
+ const [currentSubMenu, setCurrentSubMenu] =
+ useRecoilState(currentSubMenuState);
+
const sortedAvailableFilterDefinitions = [...availableFilterDefinitions]
.sort((a, b) => a.label.localeCompare(b.label))
.filter((item) =>
@@ -75,37 +76,21 @@ export const ObjectFilterDropdownFilterSelect = () => {
selectFilter({ filterDefinition: selectedFilterDefinition });
};
- return (
- <>
- ) =>
- setSearchText(event.target.value)
- }
- />
-
-
- {sortedAvailableFilterDefinitions.map(
- (availableFilterDefinition, index) => (
-
-
-
- ),
- )}
-
-
- >
+ useEffect(() => {
+ return () => {
+ setCurrentSubMenu(null);
+ };
+ }, [setCurrentSubMenu]);
+
+ return !currentSubMenu ? (
+
+ ) : (
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx
index eb04750c9..da2127ee0 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx
@@ -1,9 +1,14 @@
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter';
+import {
+ currentParentFilterDefinitionState,
+ currentSubMenuState,
+} from '@/object-record/object-filter-dropdown/states/subMenuStates';
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
+import { hasSubMenuFilter } from '@/object-record/object-filter-dropdown/utils/hasSubMenuFilter';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect';
-import { useRecoilValue } from 'recoil';
+import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useIcons } from 'twenty-ui';
export type ObjectFilterDropdownFilterSelectMenuItemProps = {
@@ -23,12 +28,24 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
isSelectedItemIdSelector(filterDefinition.fieldMetadataId),
);
+ const hasSubMenu = hasSubMenuFilter(filterDefinition.type);
+
const { getIcon } = useIcons();
+ const setCurrentSubMenu = useSetRecoilState(currentSubMenuState);
+ const setCurrentParentFilterDefinition = useSetRecoilState(
+ currentParentFilterDefinitionState,
+ );
+
const handleClick = () => {
resetSelectedItem();
- selectFilter({ filterDefinition });
+ if (hasSubMenu) {
+ setCurrentSubMenu(filterDefinition.type);
+ setCurrentParentFilterDefinition(filterDefinition);
+ } else {
+ selectFilter({ filterDefinition });
+ }
};
return (
@@ -38,6 +55,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
onClick={handleClick}
LeftIcon={getIcon(filterDefinition.iconName)}
text={filterDefinition.label}
+ hasSubMenu={hasSubMenu}
/>
);
};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx
index ddaaf2e6a..c55496ee6 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx
@@ -4,9 +4,9 @@ import { v4 } from 'uuid';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
-import { MultipleRecordSelectDropdown } from '@/object-record/select/components/MultipleRecordSelectDropdown';
+import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
-import { SelectableRecord } from '@/object-record/select/types/SelectableRecord';
+import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { isDefined } from '~/utils/isDefined';
@@ -66,7 +66,7 @@ export const ObjectFilterDropdownRecordSelect = ({
});
const handleMultipleRecordSelectChange = (
- recordToSelect: SelectableRecord,
+ recordToSelect: SelectableItem,
newSelectedValue: boolean,
) => {
if (loading) {
@@ -134,15 +134,15 @@ export const ObjectFilterDropdownRecordSelect = ({
};
return (
-
);
};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx
new file mode 100644
index 000000000..b0acad0bf
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx
@@ -0,0 +1,137 @@
+import { useState } from 'react';
+import { useRecoilValue } from 'recoil';
+import { v4 } from 'uuid';
+
+import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
+import { getSourceEnumOptions } from '@/object-record/object-filter-dropdown/utils/getSourceEnumOptions';
+import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
+import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
+import { SelectableItem } from '@/object-record/select/types/SelectableItem';
+import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
+import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
+import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
+import { isDefined } from '~/utils/isDefined';
+
+export const EMPTY_FILTER_VALUE = '[]';
+export const MAX_ITEMS_TO_DISPLAY = 3;
+
+type ObjectFilterDropdownSourceSelectProps = {
+ viewComponentId?: string;
+};
+
+export const ObjectFilterDropdownSourceSelect = ({
+ viewComponentId,
+}: ObjectFilterDropdownSourceSelectProps) => {
+ const {
+ filterDefinitionUsedInDropdownState,
+ objectFilterDropdownSearchInputState,
+ selectedOperandInDropdownState,
+ selectedFilterState,
+ setObjectFilterDropdownSelectedRecordIds,
+ objectFilterDropdownSelectedRecordIdsState,
+ selectFilter,
+ emptyFilterButKeepDefinition,
+ } = useFilterDropdown();
+
+ const { deleteCombinedViewFilter } =
+ useDeleteCombinedViewFilters(viewComponentId);
+
+ const { currentViewWithCombinedFiltersAndSorts } =
+ useGetCurrentView(viewComponentId);
+
+ const filterDefinitionUsedInDropdown = useRecoilValue(
+ filterDefinitionUsedInDropdownState,
+ );
+ const objectFilterDropdownSearchInput = useRecoilValue(
+ objectFilterDropdownSearchInputState,
+ );
+ const selectedOperandInDropdown = useRecoilValue(
+ selectedOperandInDropdownState,
+ );
+ const objectFilterDropdownSelectedRecordIds = useRecoilValue(
+ objectFilterDropdownSelectedRecordIdsState,
+ );
+ const [fieldId] = useState(v4());
+
+ const selectedFilter = useRecoilValue(selectedFilterState);
+
+ const sourceTypes = getSourceEnumOptions(
+ objectFilterDropdownSelectedRecordIds,
+ );
+
+ const filteredSelectedItems = sourceTypes.filter((option) =>
+ objectFilterDropdownSelectedRecordIds.includes(option.id),
+ );
+
+ const handleMultipleItemSelectChange = (
+ itemToSelect: SelectableItem,
+ newSelectedValue: boolean,
+ ) => {
+ const newSelectedItemIds = newSelectedValue
+ ? [...objectFilterDropdownSelectedRecordIds, itemToSelect.id]
+ : objectFilterDropdownSelectedRecordIds.filter(
+ (id) => id !== itemToSelect.id,
+ );
+
+ if (newSelectedItemIds.length === 0) {
+ emptyFilterButKeepDefinition();
+ deleteCombinedViewFilter(fieldId);
+ return;
+ }
+
+ setObjectFilterDropdownSelectedRecordIds(newSelectedItemIds);
+
+ const selectedItemNames = sourceTypes
+ .filter((option) => newSelectedItemIds.includes(option.id))
+ .map((option) => option.name);
+
+ const filterDisplayValue =
+ selectedItemNames.length > MAX_ITEMS_TO_DISPLAY
+ ? `${selectedItemNames.length} source types`
+ : selectedItemNames.join(', ');
+
+ if (
+ isDefined(filterDefinitionUsedInDropdown) &&
+ isDefined(selectedOperandInDropdown)
+ ) {
+ const newFilterValue =
+ newSelectedItemIds.length > 0
+ ? JSON.stringify(newSelectedItemIds)
+ : EMPTY_FILTER_VALUE;
+
+ const viewFilter =
+ currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
+ (viewFilter) =>
+ viewFilter.fieldMetadataId ===
+ filterDefinitionUsedInDropdown.fieldMetadataId,
+ );
+
+ const filterId = viewFilter?.id ?? fieldId;
+
+ selectFilter({
+ id: selectedFilter?.id ? selectedFilter.id : filterId,
+ definition: filterDefinitionUsedInDropdown,
+ operand: selectedOperandInDropdown || ViewFilterOperand.Is,
+ displayValue: filterDisplayValue,
+ fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
+ value: newFilterValue,
+ });
+ }
+ };
+
+ return (
+
+ !filteredSelectedItems.some((selected) => selected.id === item.id),
+ )}
+ filteredSelectedItems={filteredSelectedItems}
+ selectedItems={filteredSelectedItems}
+ onChange={handleMultipleItemSelectChange}
+ searchFilter={objectFilterDropdownSearchInput}
+ loadingItems={false}
+ />
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectMenu.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectMenu.tsx
new file mode 100644
index 000000000..ad5d8bc6a
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectMenu.tsx
@@ -0,0 +1,87 @@
+import styled from '@emotion/styled';
+
+import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
+
+import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
+import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
+import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
+import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
+import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
+import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
+
+export const StyledInput = styled.input`
+ background: transparent;
+ border: none;
+ border-top: none;
+ border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
+ border-radius: 0;
+ border-top-left-radius: ${({ theme }) => theme.border.radius.md};
+ border-top-right-radius: ${({ theme }) => theme.border.radius.md};
+ color: ${({ theme }) => theme.font.color.primary};
+ margin: 0;
+ outline: none;
+ padding: ${({ theme }) => theme.spacing(2)};
+ height: 19px;
+ font-family: inherit;
+ font-size: ${({ theme }) => theme.font.size.sm};
+
+ font-weight: inherit;
+ max-width: 100%;
+ overflow: hidden;
+ text-decoration: none;
+
+ &::placeholder {
+ color: ${({ theme }) => theme.font.color.light};
+ }
+`;
+
+type ObjectFilterSelectMenuProps = {
+ searchText: string;
+ setSearchText: (searchText: string) => void;
+ sortedAvailableFilterDefinitions: FilterDefinition[];
+ selectableListItemIds: string[];
+ handleEnter: (itemId: string) => void;
+};
+
+export const ObjectFilterSelectMenu = ({
+ searchText,
+ setSearchText,
+ sortedAvailableFilterDefinitions,
+ selectableListItemIds,
+ handleEnter,
+}: ObjectFilterSelectMenuProps) => {
+ return (
+ <>
+ ) =>
+ setSearchText(event.target.value)
+ }
+ />
+
+
+ {sortedAvailableFilterDefinitions.map(
+ (availableFilterDefinition: FilterDefinition, index: number) => (
+
+
+
+ ),
+ )}
+
+
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectSubMenu.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectSubMenu.tsx
new file mode 100644
index 000000000..205ca425e
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterSelectSubMenu.tsx
@@ -0,0 +1,102 @@
+import { StyledInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
+import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
+import {
+ currentParentFilterDefinitionState,
+ currentSubMenuState,
+} from '@/object-record/object-filter-dropdown/states/subMenuStates';
+import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
+import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType';
+import { getHeaderTitle } from '@/object-record/object-filter-dropdown/utils/getHeaderTitle';
+import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType';
+import { getSubMenuOptions } from '@/object-record/object-filter-dropdown/utils/getSubMenuOptions';
+import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
+import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
+import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
+import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
+import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
+import { useState } from 'react';
+import { useRecoilState, useRecoilValue } from 'recoil';
+import { IconChevronLeft, useIcons } from 'twenty-ui';
+
+export const ObjectFilterSelectSubMenu = () => {
+ const [searchText, setSearchText] = useState('');
+ const { getIcon } = useIcons();
+
+ const [currentSubMenu, setCurrentSubMenu] =
+ useRecoilState(currentSubMenuState);
+
+ const currentParentFilterDefinition = useRecoilValue(
+ currentParentFilterDefinitionState,
+ );
+
+ const {
+ setFilterDefinitionUsedInDropdown,
+ setSelectedOperandInDropdown,
+ setObjectFilterDropdownSearchInput,
+ } = useFilterDropdown();
+
+ const setHotkeyScope = useSetHotkeyScope();
+
+ const handleSelectFilter = (definition: FilterDefinition | null) => {
+ if (definition !== null) {
+ setFilterDefinitionUsedInDropdown(definition);
+ if (definition.type === 'SOURCE') {
+ setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
+ }
+
+ setSelectedOperandInDropdown(
+ getOperandsForFilterType(definition.type)?.[0],
+ );
+
+ setObjectFilterDropdownSearchInput('');
+ }
+ };
+
+ return (
+ <>
+ {
+ setCurrentSubMenu(null);
+ }}
+ >
+ {getHeaderTitle(currentSubMenu)}
+
+ ) =>
+ setSearchText(event.target.value)
+ }
+ />
+
+ {getSubMenuOptions(currentSubMenu)
+ .sort((a, b) => a.name.localeCompare(b.name))
+ .filter((item) =>
+ item.name
+ .toLocaleLowerCase()
+ .includes(searchText.toLocaleLowerCase()),
+ )
+ .map((menuOption, index) => (
+
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/subMenuStates.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/subMenuStates.ts
new file mode 100644
index 000000000..5f0469a2a
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/subMenuStates.ts
@@ -0,0 +1,15 @@
+import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
+import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType';
+import { atom } from 'recoil';
+
+export const currentSubMenuState = atom({
+ key: 'currentSubMenuState',
+ default: null,
+});
+
+export const currentParentFilterDefinitionState = atom(
+ {
+ key: 'currentParentFilterDefinitionState',
+ default: null,
+ },
+);
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterDefinition.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterDefinition.ts
index 954562f4f..7f7cb678a 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterDefinition.ts
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterDefinition.ts
@@ -11,4 +11,5 @@ export type FilterDefinition = {
relationObjectMetadataNameSingular?: string;
selectAllLabel?: string;
SelectAllIcon?: IconComponent;
+ subFieldType?: FilterType;
};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts
index 1803a88a5..cec0407c5 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/types/FilterType.ts
@@ -17,4 +17,5 @@ export type FilterType =
| 'RATING'
| 'MULTI_SELECT'
| 'ACTOR'
- | 'ARRAY';
+ | 'ARRAY'
+ | 'SOURCE';
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getHeaderTitle.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getHeaderTitle.ts
new file mode 100644
index 000000000..dcffda683
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getHeaderTitle.ts
@@ -0,0 +1,14 @@
+import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType';
+
+export const getHeaderTitle = (
+ subMenu: FilterType | null,
+): string | undefined => {
+ switch (subMenu) {
+ case 'ACTOR':
+ return 'Actor';
+ case 'SOURCE':
+ return 'Creation Source';
+ default:
+ return undefined;
+ }
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts
index d1066e2a5..80ac33bc6 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getOperandsForFilterType.ts
@@ -57,6 +57,8 @@ export const getOperandsForFilterType = (
];
case 'RELATION':
return [...relationOperands, ...emptyOperands];
+ case 'SOURCE':
+ return [...relationOperands];
case 'SELECT':
return [...relationOperands];
default:
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSourceEnumOptions.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSourceEnumOptions.ts
new file mode 100644
index 000000000..ee886da63
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSourceEnumOptions.ts
@@ -0,0 +1,56 @@
+import { SelectableItem } from '@/object-record/select/types/SelectableItem';
+import {
+ IconApi,
+ IconCsv,
+ IconGmail,
+ IconGoogleCalendar,
+ IconSettingsAutomation,
+ IconUserCircle,
+} from 'twenty-ui';
+
+export const getSourceEnumOptions = (
+ selectedItemIds: string[],
+): SelectableItem[] => {
+ return [
+ {
+ id: 'MANUAL',
+ name: 'User',
+ isSelected: selectedItemIds.includes('MANUAL'),
+ AvatarIcon: IconUserCircle,
+ isIconInverted: true,
+ },
+ {
+ id: 'IMPORT',
+ name: 'Import',
+ isSelected: selectedItemIds.includes('IMPORT'),
+ AvatarIcon: IconCsv,
+ isIconInverted: true,
+ },
+ {
+ id: 'API',
+ name: 'Api',
+ isSelected: selectedItemIds.includes('API'),
+ AvatarIcon: IconApi,
+ isIconInverted: true,
+ },
+ {
+ id: 'EMAIL',
+ name: 'Email',
+ isSelected: selectedItemIds.includes('EMAIL'),
+ AvatarIcon: IconGmail,
+ },
+ {
+ id: 'CALENDAR',
+ name: 'Calendar',
+ isSelected: selectedItemIds.includes('CALENDAR'),
+ AvatarIcon: IconGoogleCalendar,
+ },
+ {
+ id: 'WORKFLOW',
+ name: 'Workflow',
+ isSelected: selectedItemIds.includes('WORKFLOW'),
+ AvatarIcon: IconSettingsAutomation,
+ isIconInverted: true,
+ },
+ ];
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSubMenuOptions.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSubMenuOptions.ts
new file mode 100644
index 000000000..dde8aedbd
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/getSubMenuOptions.ts
@@ -0,0 +1,21 @@
+import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType';
+
+export const getSubMenuOptions = (subMenu: FilterType | null) => {
+ switch (subMenu) {
+ case 'ACTOR':
+ return [
+ {
+ name: 'Creation Source',
+ icon: 'IconPlug',
+ type: 'SOURCE',
+ },
+ {
+ name: 'Creator Name',
+ icon: 'IconId',
+ type: 'ACTOR',
+ },
+ ];
+ default:
+ return [];
+ }
+};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/hasSubMenuFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/hasSubMenuFilter.ts
new file mode 100644
index 000000000..897670457
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/hasSubMenuFilter.ts
@@ -0,0 +1,3 @@
+import { FilterType } from '@/object-record/object-filter-dropdown/types/FilterType';
+
+export const hasSubMenuFilter = (type: FilterType) => ['ACTOR'].includes(type);
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts
index 58cbaca25..145844853 100644
--- a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts
+++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts
@@ -30,12 +30,6 @@ import { endOfDay, roundToNearestMinutes, startOfDay } from 'date-fns';
import { z } from 'zod';
import { Filter } from '../../object-filter-dropdown/types/Filter';
-export type ObjectDropdownFilter = Omit & {
- definition: {
- type: Filter['definition']['type'];
- };
-};
-
const applyEmptyFilters = (
operand: ViewFilterOperand,
correspondingField: Pick,
@@ -282,7 +276,7 @@ const applyEmptyFilters = (
};
export const turnObjectDropdownFilterIntoQueryFilter = (
- rawUIFilters: ObjectDropdownFilter[],
+ rawUIFilters: Filter[],
fields: Pick[],
): RecordGqlOperationFilter | undefined => {
const objectRecordFilters: RecordGqlOperationFilter[] = [];
@@ -894,48 +888,87 @@ export const turnObjectDropdownFilterIntoQueryFilter = (
break;
}
case 'ACTOR':
- switch (rawUIFilter.operand) {
- case ViewFilterOperand.Contains:
- objectRecordFilters.push({
- or: [
- {
- [correspondingField.name]: {
- name: {
- ilike: `%${rawUIFilter.value}%`,
+ if (rawUIFilter.definition.subFieldType !== undefined) {
+ const parsedRecordIds = JSON.parse(rawUIFilter.value) as string[];
+ switch (rawUIFilter.definition.subFieldType) {
+ case 'SOURCE':
+ switch (rawUIFilter.operand) {
+ case ViewFilterOperand.Is:
+ objectRecordFilters.push({
+ [correspondingField.name]: {
+ source: {
+ in: parsedRecordIds,
+ } as RelationFilter,
},
- } as ActorFilter,
- },
- ],
- });
- break;
- case ViewFilterOperand.DoesNotContain:
- objectRecordFilters.push({
- and: [
- {
- not: {
+ });
+
+ break;
+ case ViewFilterOperand.IsNot:
+ if (parsedRecordIds.length > 0) {
+ objectRecordFilters.push({
+ not: {
+ [correspondingField.name]: {
+ [rawUIFilter.definition.subFieldType.toLowerCase()]: {
+ in: parsedRecordIds,
+ } as RelationFilter,
+ },
+ },
+ });
+ }
+
+ break;
+
+ default:
+ throw new Error(
+ `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.subFieldType} filter`,
+ );
+ }
+ }
+ } else {
+ switch (rawUIFilter.operand) {
+ case ViewFilterOperand.Contains:
+ objectRecordFilters.push({
+ or: [
+ {
[correspondingField.name]: {
name: {
ilike: `%${rawUIFilter.value}%`,
},
} as ActorFilter,
},
- },
- ],
- });
- break;
- case ViewFilterOperand.IsEmpty:
- case ViewFilterOperand.IsNotEmpty:
- applyEmptyFilters(
- rawUIFilter.operand,
- correspondingField,
- objectRecordFilters,
- rawUIFilter.definition.type,
- );
- break;
- default:
- throw new Error(
- `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`,
- );
+ ],
+ });
+ break;
+ case ViewFilterOperand.DoesNotContain:
+ objectRecordFilters.push({
+ and: [
+ {
+ not: {
+ [correspondingField.name]: {
+ name: {
+ ilike: `%${rawUIFilter.value}%`,
+ },
+ } as ActorFilter,
+ },
+ },
+ ],
+ });
+ break;
+ case ViewFilterOperand.IsEmpty:
+ case ViewFilterOperand.IsNotEmpty:
+ applyEmptyFilters(
+ rawUIFilter.operand,
+ correspondingField,
+ objectRecordFilters,
+ rawUIFilter.definition.type,
+ );
+ break;
+ default:
+ throw new Error(
+ `Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`,
+ );
+ }
+ break;
}
break;
case 'EMAILS':
diff --git a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx b/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx
similarity index 55%
rename from packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx
rename to packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx
index 3914a4163..fba130110 100644
--- a/packages/twenty-front/src/modules/object-record/select/components/MultipleRecordSelectDropdown.tsx
+++ b/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx
@@ -1,9 +1,10 @@
+import styled from '@emotion/styled';
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
-import { Avatar } from 'twenty-ui';
+import { AvatarChip } from 'twenty-ui';
-import { SelectableRecord } from '@/object-record/select/types/SelectableRecord';
+import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
@@ -14,26 +15,36 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
-export const MultipleRecordSelectDropdown = ({
+const StyledAvatarChip = styled(AvatarChip)`
+ &.avatar-icon-container {
+ color: ${({ theme }) => theme.font.color.secondary};
+ gap: ${({ theme }) => theme.spacing(2)};
+ padding-left: 0px;
+ padding-right: 0px;
+ font-size: ${({ theme }) => theme.font.size.md};
+ }
+`;
+
+export const MultipleSelectDropdown = ({
selectableListId,
hotkeyScope,
- recordsToSelect,
- loadingRecords,
- filteredSelectedRecords,
+ itemsToSelect,
+ loadingItems,
+ filteredSelectedItems,
onChange,
searchFilter,
}: {
selectableListId: string;
hotkeyScope: string;
- recordsToSelect: SelectableRecord[];
- filteredSelectedRecords: SelectableRecord[];
- selectedRecords: SelectableRecord[];
+ itemsToSelect: SelectableItem[];
+ filteredSelectedItems: SelectableItem[];
+ selectedItems: SelectableItem[];
searchFilter: string;
onChange: (
- changedRecordToSelect: SelectableRecord,
+ changedItemToSelect: SelectableItem,
newSelectedValue: boolean,
) => void;
- loadingRecords: boolean;
+ loadingItems: boolean;
}) => {
const { closeDropdown } = useDropdown();
const { selectedItemIdState } = useSelectableListStates({
@@ -44,32 +55,32 @@ export const MultipleRecordSelectDropdown = ({
const selectedItemId = useRecoilValue(selectedItemIdState);
- const handleRecordSelectChange = (
- recordToSelect: SelectableRecord,
+ const handleItemSelectChange = (
+ itemToSelect: SelectableItem,
newSelectedValue: boolean,
) => {
onChange(
{
- ...recordToSelect,
+ ...itemToSelect,
isSelected: newSelectedValue,
},
newSelectedValue,
);
};
- const [recordsInDropdown, setRecordInDropdown] = useState([
- ...(filteredSelectedRecords ?? []),
- ...(recordsToSelect ?? []),
+ const [itemsInDropdown, setItemInDropdown] = useState([
+ ...(filteredSelectedItems ?? []),
+ ...(itemsToSelect ?? []),
]);
useEffect(() => {
- if (!loadingRecords) {
- setRecordInDropdown([
- ...(filteredSelectedRecords ?? []),
- ...(recordsToSelect ?? []),
+ if (!loadingItems) {
+ setItemInDropdown([
+ ...(filteredSelectedItems ?? []),
+ ...(itemsToSelect ?? []),
]);
}
- }, [recordsToSelect, filteredSelectedRecords, loadingRecords]);
+ }, [itemsToSelect, filteredSelectedItems, loadingItems]);
useScopedHotkeys(
[Key.Escape],
@@ -82,12 +93,12 @@ export const MultipleRecordSelectDropdown = ({
);
const showNoResult =
- recordsToSelect?.length === 0 &&
+ itemsToSelect?.length === 0 &&
searchFilter !== '' &&
- filteredSelectedRecords?.length === 0 &&
- !loadingRecords;
+ filteredSelectedItems?.length === 0 &&
+ !loadingItems;
- const selectableItemIds = recordsInDropdown.map((record) => record.id);
+ const selectableItemIds = itemsInDropdown.map((item) => item.id);
return (
{
- const record = recordsInDropdown.findIndex(
+ const item = itemsInDropdown.findIndex(
(entity) => entity.id === itemId,
);
- const recordIsSelectedInDropwdown = filteredSelectedRecords.find(
+ const itemIsSelectedInDropwdown = filteredSelectedItems.find(
(entity) => entity.id === itemId,
);
- handleRecordSelectChange(
- recordsInDropdown[record],
- !recordIsSelectedInDropwdown,
+ handleItemSelectChange(
+ itemsInDropdown[item],
+ !itemIsSelectedInDropwdown,
);
resetSelectedItem();
}}
>
- {recordsInDropdown?.map((record) => {
+ {itemsInDropdown?.map((item) => {
return (
{
resetSelectedItem();
- handleRecordSelectChange(record, newCheckedValue);
+ handleItemSelectChange(item, newCheckedValue);
}}
avatar={
-
}
- text={record.name}
/>
);
})}
{showNoResult && }
- {loadingRecords && }
+ {loadingItems && }
);
diff --git a/packages/twenty-front/src/modules/object-record/select/hooks/useRecordsForSelect.ts b/packages/twenty-front/src/modules/object-record/select/hooks/useRecordsForSelect.ts
index 905d4fd8f..73bacf2e7 100644
--- a/packages/twenty-front/src/modules/object-record/select/hooks/useRecordsForSelect.ts
+++ b/packages/twenty-front/src/modules/object-record/select/hooks/useRecordsForSelect.ts
@@ -5,7 +5,7 @@ import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapTo
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
-import { SelectableRecord } from '@/object-record/select/types/SelectableRecord';
+import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { getObjectFilterFields } from '@/object-record/select/utils/getObjectFilterFields';
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
@@ -109,19 +109,19 @@ export const useRecordsForSelect = ({
.map((record) => ({
...record,
isSelected: true,
- })) as SelectableRecord[],
+ })) as SelectableItem[],
filteredSelectedRecords: filteredSelectedRecordsData
.map(mapToObjectRecordIdentifier)
.map((record) => ({
...record,
isSelected: true,
- })) as SelectableRecord[],
+ })) as SelectableItem[],
recordsToSelect: recordsToSelectData
.map(mapToObjectRecordIdentifier)
.map((record) => ({
...record,
isSelected: false,
- })) as SelectableRecord[],
+ })) as SelectableItem[],
loading:
recordsToSelectLoading ||
filteredSelectedRecordsLoading ||
diff --git a/packages/twenty-front/src/modules/object-record/select/types/SelectableItem.ts b/packages/twenty-front/src/modules/object-record/select/types/SelectableItem.ts
new file mode 100644
index 000000000..57122ebe7
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/select/types/SelectableItem.ts
@@ -0,0 +1,11 @@
+import { AvatarType, IconComponent } from 'twenty-ui';
+
+export type SelectableItem = T & {
+ id: string;
+ name: string;
+ avatarUrl?: string;
+ avatarType?: AvatarType;
+ AvatarIcon?: IconComponent;
+ isSelected: boolean;
+ isIconInverted?: boolean;
+};
diff --git a/packages/twenty-front/src/modules/object-record/select/types/SelectableRecord.ts b/packages/twenty-front/src/modules/object-record/select/types/SelectableRecord.ts
deleted file mode 100644
index ff08ac70b..000000000
--- a/packages/twenty-front/src/modules/object-record/select/types/SelectableRecord.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { AvatarType } from 'twenty-ui';
-
-export type SelectableRecord = {
- id: string;
- name: string;
- avatarUrl?: string;
- avatarType?: AvatarType;
- record: any;
- isSelected: boolean;
-};
diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar.tsx
index 7e8dff27e..8086e4ad0 100644
--- a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar.tsx
@@ -22,7 +22,7 @@ type MenuItemMultiSelectAvatarProps = {
avatar?: ReactNode;
selected: boolean;
isKeySelected?: boolean;
- text: string;
+ text?: string;
className?: string;
onSelectChange?: (selected: boolean) => void;
};
diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemSelect.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemSelect.tsx
index 5f6dee4cd..7a5a97670 100644
--- a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemSelect.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItemSelect.tsx
@@ -1,6 +1,6 @@
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
-import { IconCheck, IconComponent } from 'twenty-ui';
+import { IconCheck, IconChevronRight, IconComponent } from 'twenty-ui';
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
import { StyledMenuItemBase } from '../internals/components/StyledMenuItemBase';
@@ -45,6 +45,7 @@ type MenuItemSelectProps = {
onClick?: () => void;
disabled?: boolean;
hovered?: boolean;
+ hasSubMenu?: boolean;
};
export const MenuItemSelect = ({
@@ -55,6 +56,7 @@ export const MenuItemSelect = ({
onClick,
disabled,
hovered,
+ hasSubMenu = false,
}: MenuItemSelectProps) => {
const theme = useTheme();
@@ -68,6 +70,12 @@ export const MenuItemSelect = ({
>
{selected && }
+ {hasSubMenu && (
+
+ )}
);
};
diff --git a/packages/twenty-front/src/modules/views/types/ViewFilter.ts b/packages/twenty-front/src/modules/views/types/ViewFilter.ts
index 608e13918..f5175cf41 100644
--- a/packages/twenty-front/src/modules/views/types/ViewFilter.ts
+++ b/packages/twenty-front/src/modules/views/types/ViewFilter.ts
@@ -1,3 +1,4 @@
+import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
import { ViewFilterOperand } from './ViewFilterOperand';
export type ViewFilter = {
@@ -11,4 +12,5 @@ export type ViewFilter = {
createdAt?: string;
updatedAt?: string;
viewId?: string;
+ definition?: FilterDefinition;
};
diff --git a/packages/twenty-front/src/modules/views/utils/getFilterDefinitionForViewFilter.ts b/packages/twenty-front/src/modules/views/utils/getFilterDefinitionForViewFilter.ts
new file mode 100644
index 000000000..d66b6f26b
--- /dev/null
+++ b/packages/twenty-front/src/modules/views/utils/getFilterDefinitionForViewFilter.ts
@@ -0,0 +1,17 @@
+import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
+import { hasSubMenuFilter } from '@/object-record/object-filter-dropdown/utils/hasSubMenuFilter';
+import { ViewFilter } from '../types/ViewFilter';
+
+export const getFilterDefinitionForViewFilter = (
+ viewFilter: ViewFilter,
+ availableFilterDefinition: FilterDefinition,
+): FilterDefinition => {
+ return {
+ ...availableFilterDefinition,
+ subFieldType:
+ hasSubMenuFilter(availableFilterDefinition.type) &&
+ viewFilter.definition?.type !== availableFilterDefinition.type
+ ? viewFilter.definition?.type
+ : undefined,
+ };
+};
diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
index 104ba6afd..f3a4fcd22 100644
--- a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
+++ b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
@@ -2,6 +2,7 @@ import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
import { isDefined } from '~/utils/isDefined';
+import { getFilterDefinitionForViewFilter } from '@/views/utils/getFilterDefinitionForViewFilter';
import { ViewFilter } from '../types/ViewFilter';
export const mapViewFiltersToFilters = (
@@ -23,7 +24,10 @@ export const mapViewFiltersToFilters = (
value: viewFilter.value,
displayValue: viewFilter.displayValue,
operand: viewFilter.operand,
- definition: availableFilterDefinition,
+ definition: getFilterDefinitionForViewFilter(
+ viewFilter,
+ availableFilterDefinition,
+ ),
};
})
.filter(isDefined);
diff --git a/packages/twenty-ui/src/display/chip/components/Chip.tsx b/packages/twenty-ui/src/display/chip/components/Chip.tsx
index 8ff16e9a9..48795fd42 100644
--- a/packages/twenty-ui/src/display/chip/components/Chip.tsx
+++ b/packages/twenty-ui/src/display/chip/components/Chip.tsx
@@ -127,6 +127,7 @@ export const Chip = ({
rightComponent,
accent = ChipAccent.TextPrimary,
onClick,
+ className,
}: ChipProps) => {
return (
{leftComponent}