Added a search box in sort menu (#5045)
Closes #4368 --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||||
|
|
||||||
|
export const objectSortDropdownSearchInputComponentState =
|
||||||
|
createComponentState<string>({
|
||||||
|
key: 'objectSortDropdownSearchInputComponentState',
|
||||||
|
defaultValue: '',
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user