diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts b/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts index c41e2122d..2708774b9 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts @@ -4,6 +4,7 @@ import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShow import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; +import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; @@ -14,14 +15,27 @@ export const getObjectRecordIdentifier = ({ objectMetadataItem: ObjectMetadataItem; record: ObjectRecord; }): ObjectRecordIdentifier => { - if (objectMetadataItem.nameSingular === CoreObjectNameSingular.Opportunity) { - return { - id: record.id, - name: record?.company?.name ?? record.name, - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - linkToShowPage: `/opportunities/${record.id}`, - }; + switch (objectMetadataItem.nameSingular) { + case CoreObjectNameSingular.Opportunity: { + return { + id: record.id, + name: record?.company?.name, + avatarUrl: record.avatarUrl, + avatarType: 'rounded', + linkToShowPage: `/opportunities/${record.id}`, + }; + } + case CoreObjectNameSingular.WorkspaceMember: { + const workspaceMember = record as WorkspaceMember; + + return { + id: workspaceMember.id, + name: + workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName, + avatarUrl: workspaceMember.avatarUrl ?? undefined, + avatarType: 'rounded', + }; + } } const labelIdentifierFieldMetadataItem = diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordRemoveFilterMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordRemoveFilterMenuItem.tsx new file mode 100644 index 000000000..6cf124fd3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordRemoveFilterMenuItem.tsx @@ -0,0 +1,27 @@ +import { MenuItem } from 'tsup.ui.index'; + +import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; +import { IconFilterOff } from '@/ui/display/icon'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; + +export const ObjectFilterDropdownRecordRemoveFilterMenuItem = () => { + const { emptyFilterButKeepDefinition } = useFilterDropdown(); + + const { closeDropdown } = useDropdown(); + + const handleRemoveFilter = () => { + emptyFilterButKeepDefinition(); + closeDropdown(); + }; + + return ( + + + + ); +}; 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 6dd141808..c711e872c 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 @@ -3,7 +3,7 @@ import { MultipleRecordSelectDropdown } from '@/object-record/select/components/ import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; import { SelectableRecord } from '@/object-record/select/types/SelectableRecord'; -export const EMPTY_FILTER_VALUE = ''; +export const EMPTY_FILTER_VALUE = '[]'; export const MAX_RECORDS_TO_DISPLAY = 3; export const ObjectFilterDropdownRecordSelect = () => { @@ -14,6 +14,7 @@ export const ObjectFilterDropdownRecordSelect = () => { setObjectFilterDropdownSelectedRecordIds, objectFilterDropdownSelectedRecordIds, selectFilter, + emptyFilterButKeepDefinition, } = useFilterDropdown(); const objectNameSingular = @@ -41,6 +42,11 @@ export const ObjectFilterDropdownRecordSelect = () => { (id) => id !== recordToSelect.id, ); + if (newSelectedRecordIds.length === 0) { + emptyFilterButKeepDefinition(); + return; + } + setObjectFilterDropdownSelectedRecordIds(newSelectedRecordIds); const selectedRecordNames = [ diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx index f87665839..aa978a47d 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx @@ -1,9 +1,11 @@ import React from 'react'; import { useTheme } from '@emotion/react'; +import { ObjectFilterDropdownRecordRemoveFilterMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordRemoveFilterMenuItem'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { IconChevronDown } from '@/ui/display/icon/index'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; +import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; @@ -65,6 +67,8 @@ export const SingleEntityObjectFilterDropdownButton = ({ dropdownComponents={ <> + + } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx index f8ed8e1de..76316b9dc 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx @@ -59,7 +59,7 @@ describe('useFilterDropdown', () => { act(() => { result.current.setOnFilterSelect( - (_currVal?: Filter) => (_filter: Filter) => {}, + (_currVal?: Filter | null) => (_filter: Filter | null) => {}, ); }); await waitFor(() => { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts index 4dcda8309..2b4932cba 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts @@ -40,13 +40,25 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { } = useFilterDropdownStates(scopeId); const selectFilter = useCallback( - (filter: Filter) => { + (filter: Filter | null) => { setSelectedFilter(filter); onFilterSelect?.(filter); }, [setSelectedFilter, onFilterSelect], ); + const emptyFilterButKeepDefinition = useCallback(() => { + setObjectFilterDropdownSearchInput(''); + setObjectFilterDropdownSelectedEntityId(null); + setObjectFilterDropdownSelectedRecordIds([]); + setSelectedFilter(undefined); + }, [ + setSelectedFilter, + setObjectFilterDropdownSelectedRecordIds, + setObjectFilterDropdownSelectedEntityId, + setObjectFilterDropdownSearchInput, + ]); + const resetFilter = useCallback(() => { setObjectFilterDropdownSearchInput(''); setObjectFilterDropdownSelectedEntityId(null); @@ -87,5 +99,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { resetFilter, onFilterSelect, setOnFilterSelect, + emptyFilterButKeepDefinition, }; }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts index 90e2140da..04c2199ce 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectScopedState.ts @@ -3,7 +3,7 @@ import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createSta import { Filter } from '../types/Filter'; export const onFilterSelectScopedState = createStateScopeMap< - ((filter: Filter) => void) | undefined + ((filter: Filter | null) => void) | undefined >({ key: 'onFilterSelectScopedState', defaultValue: undefined, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts index c2161049b..7e4513447 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterScopedState.ts @@ -3,7 +3,7 @@ import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createSta import { Filter } from '../types/Filter'; export const selectedFilterScopedState = createStateScopeMap< - Filter | undefined + Filter | undefined | null >({ key: 'selectedFilterScopedState', defaultValue: undefined, diff --git a/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts b/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts index 023bc2b8e..3d26836d7 100644 --- a/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts +++ b/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts @@ -3,7 +3,7 @@ import { AvatarType } from '@/users/components/Avatar'; export type ObjectRecordIdentifier = { id: string; name: string; - avatarUrl: string; + avatarUrl?: string; avatarType?: AvatarType | null; linkToShowPage?: string; }; diff --git a/packages/twenty-front/src/modules/ui/display/icon/index.ts b/packages/twenty-front/src/modules/ui/display/icon/index.ts index 75fc8b3a1..47af30bd9 100644 --- a/packages/twenty-front/src/modules/ui/display/icon/index.ts +++ b/packages/twenty-front/src/modules/ui/display/icon/index.ts @@ -57,6 +57,7 @@ export { IconFileText, IconFileUpload, IconFileZip, + IconFilterOff, IconForbid, IconGripVertical, IconHeadphones, diff --git a/packages/twenty-front/src/pages/tasks/TasksEffect.tsx b/packages/twenty-front/src/pages/tasks/TasksEffect.tsx index 859b167f0..7d164ddae 100644 --- a/packages/twenty-front/src/pages/tasks/TasksEffect.tsx +++ b/packages/twenty-front/src/pages/tasks/TasksEffect.tsx @@ -13,10 +13,13 @@ type TasksEffectProps = { export const TasksEffect = ({ filterDropdownId }: TasksEffectProps) => { const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); - const { setSelectedFilter, setAvailableFilterDefinitions } = - useFilterDropdown({ - filterDropdownId: filterDropdownId, - }); + const { + setSelectedFilter, + setAvailableFilterDefinitions, + setObjectFilterDropdownSelectedRecordIds, + } = useFilterDropdown({ + filterDropdownId: filterDropdownId, + }); useEffect(() => { setAvailableFilterDefinitions(tasksFilterDefinitions); @@ -35,7 +38,13 @@ export const TasksEffect = ({ filterDropdownId }: TasksEffectProps) => { displayAvatarUrl: currentWorkspaceMember.avatarUrl ?? undefined, definition: tasksFilterDefinitions[0], }); + + setObjectFilterDropdownSelectedRecordIds([currentWorkspaceMember.id]); } - }, [currentWorkspaceMember, setSelectedFilter]); + }, [ + currentWorkspaceMember, + setSelectedFilter, + setObjectFilterDropdownSelectedRecordIds, + ]); return <>; };