Added a search box in sort menu (#5045)

Closes #4368

---------

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Vinod Rathod
2024-04-25 19:01:41 +05:30
committed by GitHub
parent 806666d909
commit 4af2c5f298
5 changed files with 91 additions and 3 deletions

View File

@ -1,3 +1,5 @@
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { IconChevronDown, useIcons } from 'twenty-ui'; import { IconChevronDown, useIcons } from 'twenty-ui';
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId'; import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
@ -7,12 +9,35 @@ import { LightButton } from '@/ui/input/button/components/LightButton';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { SORT_DIRECTIONS } from '../types/SortDirection'; import { SORT_DIRECTIONS } from '../types/SortDirection';
export const StyledInput = styled.input`
background: ${({ theme }) => theme.background.secondary};
border: none;
border-top: 1px solid ${({ theme }) => theme.border.color.light};
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: 0;
color: ${({ theme }) => theme.font.color.primary};
margin: 0;
outline: none;
padding: ${({ theme }) => theme.spacing(2)};
height: 20px;
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};
}
`;
export type ObjectSortDropdownButtonProps = { export type ObjectSortDropdownButtonProps = {
sortDropdownId: string; sortDropdownId: string;
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
@ -32,6 +57,9 @@ export const ObjectSortDropdownButton = ({
isSortSelected, isSortSelected,
availableSortDefinitions, availableSortDefinitions,
handleAddSort, handleAddSort,
objectSortDropdownSearchInputState,
setObjectSortDropdownSearchInput,
resetSearchInput,
} = useObjectSortDropdown(); } = useObjectSortDropdown();
const handleButtonClick = () => { const handleButtonClick = () => {
@ -39,9 +67,14 @@ export const ObjectSortDropdownButton = ({
}; };
const handleDropdownButtonClose = () => { const handleDropdownButtonClose = () => {
resetSearchInput();
resetState(); resetState();
}; };
const objectSortDropdownSearchInput = useRecoilValue(
objectSortDropdownSearchInputState,
);
const { getIcon } = useIcons(); const { getIcon } = useIcons();
return ( return (
@ -80,15 +113,32 @@ export const ObjectSortDropdownButton = ({
> >
{selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'} {selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
</DropdownMenuHeader> </DropdownMenuHeader>
<DropdownMenuSeparator /> <StyledInput
autoFocus
value={objectSortDropdownSearchInput}
placeholder="Search fields"
onChange={(event) =>
setObjectSortDropdownSearchInput(event.target.value)
}
/>
<DropdownMenuItemsContainer> <DropdownMenuItemsContainer>
{[...availableSortDefinitions] {[...availableSortDefinitions]
.sort((a, b) => a.label.localeCompare(b.label)) .sort((a, b) => a.label.localeCompare(b.label))
.filter((item) =>
item.label
.toLocaleLowerCase()
.includes(
objectSortDropdownSearchInput.toLocaleLowerCase(),
),
)
.map((availableSortDefinition, index) => ( .map((availableSortDefinition, index) => (
<MenuItem <MenuItem
testId={`select-sort-${index}`} testId={`select-sort-${index}`}
key={index} key={index}
onClick={() => handleAddSort(availableSortDefinition)} onClick={() => {
setObjectSortDropdownSearchInput('');
handleAddSort(availableSortDefinition);
}}
LeftIcon={getIcon(availableSortDefinition.iconName)} LeftIcon={getIcon(availableSortDefinition.iconName)}
text={availableSortDefinition.label} text={availableSortDefinition.label}
/> />

View File

@ -44,6 +44,9 @@ export const useObjectSortDropdown = () => {
availableSortDefinitionsState, availableSortDefinitionsState,
onSortSelectState, onSortSelectState,
isSortSelectedState, isSortSelectedState,
objectSortDropdownSearchInputState,
setObjectSortDropdownSearchInput,
resetSearchInput,
} = useSortDropdown({ } = useSortDropdown({
sortDropdownId: VIEW_SORT_DROPDOWN_ID, sortDropdownId: VIEW_SORT_DROPDOWN_ID,
}); });
@ -71,6 +74,9 @@ export const useObjectSortDropdown = () => {
toggleSortDropdown, toggleSortDropdown,
resetState, resetState,
isSortSelected, isSortSelected,
objectSortDropdownSearchInputState,
setObjectSortDropdownSearchInput,
resetSearchInput,
availableSortDefinitions, availableSortDefinitions,
handleAddSort, handleAddSort,
}; };

View File

@ -1,3 +1,5 @@
import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates'; import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
@ -16,12 +18,28 @@ export const useSortDropdown = (props?: UseSortProps) => {
availableSortDefinitionsState, availableSortDefinitionsState,
isSortSelectedState, isSortSelectedState,
onSortSelectState, onSortSelectState,
objectSortDropdownSearchInputState,
} = useSortDropdownStates(scopeId); } = useSortDropdownStates(scopeId);
const setObjectSortDropdownSearchInput = useSetRecoilState(
objectSortDropdownSearchInputState,
);
const resetSearchInput = useRecoilCallback(
({ set }) =>
() => {
set(objectSortDropdownSearchInputState, '');
},
[objectSortDropdownSearchInputState],
);
return { return {
scopeId, scopeId,
availableSortDefinitionsState, availableSortDefinitionsState,
isSortSelectedState, isSortSelectedState,
onSortSelectState, onSortSelectState,
objectSortDropdownSearchInputState,
setObjectSortDropdownSearchInput,
resetSearchInput,
}; };
}; };

View File

@ -1,4 +1,5 @@
import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdown/states/isSortSelectedScopedState'; import { isSortSelectedComponentState } from '@/object-record/object-sort-dropdown/states/isSortSelectedScopedState';
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState'; import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState'; import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
@ -19,9 +20,15 @@ export const useSortDropdownStates = (scopeId: string) => {
scopeId, scopeId,
); );
const objectSortDropdownSearchInputState = extractComponentState(
objectSortDropdownSearchInputComponentState,
scopeId,
);
return { return {
availableSortDefinitionsState, availableSortDefinitionsState,
isSortSelectedState, isSortSelectedState,
onSortSelectState, onSortSelectState,
objectSortDropdownSearchInputState,
}; };
}; };

View File

@ -0,0 +1,7 @@
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
export const objectSortDropdownSearchInputComponentState =
createComponentState<string>({
key: 'objectSortDropdownSearchInputComponentState',
defaultValue: '',
});