Refactored sort dropdown hooks (#9584)
- Removed useObjectSortDropdown hook - Removed useSortDropdown hook
This commit is contained in:
@ -1,10 +1,16 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconChevronDown, MenuItem, useIcons } from 'twenty-ui';
|
||||
|
||||
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
|
||||
import { useObjectSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useObjectSortDropdown';
|
||||
import { ObjectSortDropdownScope } from '@/object-record/object-sort-dropdown/scopes/ObjectSortDropdownScope';
|
||||
import { useCloseSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useCloseSortDropdown';
|
||||
import { useResetRecordSortDropdownSearchInput } from '@/object-record/object-sort-dropdown/hooks/useResetRecordSortDropdownSearchInput';
|
||||
import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown';
|
||||
import { useToggleSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useToggleSortDropdown';
|
||||
import { isSortDirectionMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isSortDirectionMenuUnfoldedState';
|
||||
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { selectedSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedSortDirectionState';
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { hiddenTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/hiddenTableColumnsComponentSelector';
|
||||
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
||||
@ -14,8 +20,11 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
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 { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { SORT_DIRECTIONS } from '../types/SortDirection';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { SORT_DIRECTIONS, SortDirection } from '../types/SortDirection';
|
||||
|
||||
export const StyledInput = styled.input`
|
||||
background: transparent;
|
||||
@ -53,41 +62,35 @@ const StyledSelectedSortDirectionContainer = styled.div`
|
||||
`;
|
||||
|
||||
export type ObjectSortDropdownButtonProps = {
|
||||
sortDropdownId: string;
|
||||
hotkeyScope: HotkeyScope;
|
||||
};
|
||||
|
||||
export const ObjectSortDropdownButton = ({
|
||||
sortDropdownId,
|
||||
hotkeyScope,
|
||||
}: ObjectSortDropdownButtonProps) => {
|
||||
const {
|
||||
isSortDirectionMenuUnfolded,
|
||||
setIsSortDirectionMenuUnfolded,
|
||||
selectedSortDirection,
|
||||
setSelectedSortDirection,
|
||||
toggleSortDropdown,
|
||||
resetState,
|
||||
availableSortDefinitions,
|
||||
handleAddSort,
|
||||
objectSortDropdownSearchInputState,
|
||||
setObjectSortDropdownSearchInput,
|
||||
resetSearchInput,
|
||||
} = useObjectSortDropdown();
|
||||
const { toggleSortDropdown } = useToggleSortDropdown();
|
||||
|
||||
const { resetRecordSortDropdownSearchInput } =
|
||||
useResetRecordSortDropdownSearchInput();
|
||||
|
||||
const setObjectSortDropdownSearchInput = useSetRecoilComponentStateV2(
|
||||
objectSortDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const isSortDirectionMenuUnfolded = useRecoilComponentValueV2(
|
||||
isSortDirectionMenuUnfoldedComponentState,
|
||||
);
|
||||
|
||||
const { resetSortDropdown } = useResetSortDropdown();
|
||||
|
||||
const { recordIndexId } = useRecordIndexContextOrThrow();
|
||||
|
||||
const handleButtonClick = () => {
|
||||
toggleSortDropdown();
|
||||
};
|
||||
const objectSortDropdownSearchInput = useRecoilComponentValueV2(
|
||||
objectSortDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const handleDropdownButtonClose = () => {
|
||||
resetSearchInput();
|
||||
resetState();
|
||||
};
|
||||
|
||||
const objectSortDropdownSearchInput = useRecoilValue(
|
||||
objectSortDropdownSearchInputState,
|
||||
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
@ -131,86 +134,108 @@ export const ObjectSortDropdownButton = ({
|
||||
visibleColumnsSortDefinitions.length > 0 &&
|
||||
hiddenColumnsSortDefinitions.length > 0;
|
||||
|
||||
const handleButtonClick = () => {
|
||||
toggleSortDropdown();
|
||||
};
|
||||
|
||||
const handleDropdownButtonClose = () => {
|
||||
resetRecordSortDropdownSearchInput();
|
||||
resetSortDropdown();
|
||||
};
|
||||
|
||||
const { closeSortDropdown } = useCloseSortDropdown();
|
||||
|
||||
const onSortSelect = useRecoilComponentValueV2(onSortSelectComponentState);
|
||||
|
||||
const handleAddSort = (sortDefinition: SortDefinition) => {
|
||||
setObjectSortDropdownSearchInput('');
|
||||
closeSortDropdown();
|
||||
onSortSelect?.({
|
||||
fieldMetadataId: sortDefinition.fieldMetadataId,
|
||||
direction: selectedSortDirection,
|
||||
definition: sortDefinition,
|
||||
});
|
||||
};
|
||||
|
||||
const [selectedSortDirection, setSelectedSortDirection] =
|
||||
useRecoilComponentStateV2(selectedSortDirectionComponentState);
|
||||
|
||||
const setIsSortDirectionMenuUnfolded = useSetRecoilComponentStateV2(
|
||||
isSortDirectionMenuUnfoldedComponentState,
|
||||
);
|
||||
|
||||
const handleSortDirectionClick = (sortDirection: SortDirection) => {
|
||||
setSelectedSortDirection(sortDirection);
|
||||
setIsSortDirectionMenuUnfolded(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<ObjectSortDropdownScope sortScopeId={sortDropdownId}>
|
||||
<Dropdown
|
||||
dropdownId={OBJECT_SORT_DROPDOWN_ID}
|
||||
dropdownHotkeyScope={hotkeyScope}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
clickableComponent={
|
||||
<StyledHeaderDropdownButton onClick={handleButtonClick}>
|
||||
Sort
|
||||
</StyledHeaderDropdownButton>
|
||||
}
|
||||
dropdownComponents={
|
||||
<>
|
||||
{isSortDirectionMenuUnfolded && (
|
||||
<StyledSelectedSortDirectionContainer>
|
||||
<DropdownMenuItemsContainer>
|
||||
{SORT_DIRECTIONS.map((sortOrder, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setSelectedSortDirection(sortOrder);
|
||||
setIsSortDirectionMenuUnfolded(false);
|
||||
}}
|
||||
text={sortOrder === 'asc' ? 'Ascending' : 'Descending'}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</StyledSelectedSortDirectionContainer>
|
||||
<Dropdown
|
||||
dropdownId={OBJECT_SORT_DROPDOWN_ID}
|
||||
dropdownHotkeyScope={hotkeyScope}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
clickableComponent={
|
||||
<StyledHeaderDropdownButton onClick={handleButtonClick}>
|
||||
Sort
|
||||
</StyledHeaderDropdownButton>
|
||||
}
|
||||
dropdownComponents={
|
||||
<>
|
||||
{isSortDirectionMenuUnfolded && (
|
||||
<StyledSelectedSortDirectionContainer>
|
||||
<DropdownMenuItemsContainer>
|
||||
{SORT_DIRECTIONS.map((sortDirection, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
onClick={() => handleSortDirectionClick(sortDirection)}
|
||||
text={sortDirection === 'asc' ? 'Ascending' : 'Descending'}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</StyledSelectedSortDirectionContainer>
|
||||
)}
|
||||
<DropdownMenuHeader
|
||||
EndIcon={IconChevronDown}
|
||||
onClick={() =>
|
||||
setIsSortDirectionMenuUnfolded(!isSortDirectionMenuUnfolded)
|
||||
}
|
||||
>
|
||||
{selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
|
||||
</DropdownMenuHeader>
|
||||
<StyledInput
|
||||
autoFocus
|
||||
value={objectSortDropdownSearchInput}
|
||||
placeholder="Search fields"
|
||||
onChange={(event) =>
|
||||
setObjectSortDropdownSearchInput(event.target.value)
|
||||
}
|
||||
/>
|
||||
<DropdownMenuItemsContainer>
|
||||
{visibleColumnsSortDefinitions.map(
|
||||
(visibleSortDefinition, index) => (
|
||||
<MenuItem
|
||||
testId={`visible-select-sort-${index}`}
|
||||
key={index}
|
||||
onClick={() => handleAddSort(visibleSortDefinition)}
|
||||
LeftIcon={getIcon(visibleSortDefinition.iconName)}
|
||||
text={visibleSortDefinition.label}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
<DropdownMenuHeader
|
||||
EndIcon={IconChevronDown}
|
||||
onClick={() =>
|
||||
setIsSortDirectionMenuUnfolded(!isSortDirectionMenuUnfolded)
|
||||
}
|
||||
>
|
||||
{selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
|
||||
</DropdownMenuHeader>
|
||||
<StyledInput
|
||||
autoFocus
|
||||
value={objectSortDropdownSearchInput}
|
||||
placeholder="Search fields"
|
||||
onChange={(event) =>
|
||||
setObjectSortDropdownSearchInput(event.target.value)
|
||||
}
|
||||
/>
|
||||
<DropdownMenuItemsContainer>
|
||||
{visibleColumnsSortDefinitions.map(
|
||||
(visibleSortDefinition, index) => (
|
||||
<MenuItem
|
||||
testId={`visible-select-sort-${index}`}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setObjectSortDropdownSearchInput('');
|
||||
handleAddSort(visibleSortDefinition);
|
||||
}}
|
||||
LeftIcon={getIcon(visibleSortDefinition.iconName)}
|
||||
text={visibleSortDefinition.label}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
{shoudShowSeparator && <DropdownMenuSeparator />}
|
||||
{hiddenColumnsSortDefinitions.map(
|
||||
(hiddenSortDefinition, index) => (
|
||||
<MenuItem
|
||||
testId={`hidden-select-sort-${index}`}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setObjectSortDropdownSearchInput('');
|
||||
handleAddSort(hiddenSortDefinition);
|
||||
}}
|
||||
LeftIcon={getIcon(hiddenSortDefinition.iconName)}
|
||||
text={hiddenSortDefinition.label}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
}
|
||||
onClose={handleDropdownButtonClose}
|
||||
/>
|
||||
</ObjectSortDropdownScope>
|
||||
{shoudShowSeparator && <DropdownMenuSeparator />}
|
||||
{hiddenColumnsSortDefinitions.map((hiddenSortDefinition, index) => (
|
||||
<MenuItem
|
||||
testId={`hidden-select-sort-${index}`}
|
||||
key={index}
|
||||
onClick={() => handleAddSort(hiddenSortDefinition)}
|
||||
LeftIcon={getIcon(hiddenSortDefinition.iconName)}
|
||||
text={hiddenSortDefinition.label}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
}
|
||||
onClose={handleDropdownButtonClose}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
import { expect } from '@storybook/test';
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { RecoilRoot, useRecoilState } from 'recoil';
|
||||
|
||||
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
||||
import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates';
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
);
|
||||
|
||||
const sortDropdownId = 'sortDropdownId';
|
||||
const renderHookConfig = {
|
||||
wrapper: Wrapper,
|
||||
};
|
||||
|
||||
const sortDefinitions: SortDefinition[] = [
|
||||
{ fieldMetadataId: 'id', label: 'definition label', iconName: 'icon' },
|
||||
];
|
||||
|
||||
describe('useSortDropdown', () => {
|
||||
it('should set availableSortDefinitions', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
useSortDropdown({ sortDropdownId });
|
||||
|
||||
// TODO: verify this instance id works
|
||||
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
||||
useRecoilComponentStateV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
sortDropdownId,
|
||||
);
|
||||
|
||||
return {
|
||||
availableSortDefinitions,
|
||||
setAvailableSortDefinitions,
|
||||
};
|
||||
}, renderHookConfig);
|
||||
expect(result.current.availableSortDefinitions).toEqual([]);
|
||||
act(() => {
|
||||
result.current.setAvailableSortDefinitions(sortDefinitions);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.availableSortDefinitions).toEqual(sortDefinitions);
|
||||
});
|
||||
});
|
||||
|
||||
it('should set isSortSelected', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
useSortDropdown({ sortDropdownId });
|
||||
const { isSortSelectedState } = useSortDropdownStates(sortDropdownId);
|
||||
|
||||
const [isSortSelected, setIsSortSelected] =
|
||||
useRecoilState(isSortSelectedState);
|
||||
|
||||
return {
|
||||
isSortSelected,
|
||||
setIsSortSelected,
|
||||
};
|
||||
}, renderHookConfig);
|
||||
|
||||
expect(result.current.isSortSelected).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.setIsSortSelected(true);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isSortSelected).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should set onSortSelect', async () => {
|
||||
const OnSortSelectFunction = () => {};
|
||||
const mockOnSortSelect = jest.fn(() => OnSortSelectFunction);
|
||||
const { result } = renderHook(() => {
|
||||
useSortDropdown({ sortDropdownId });
|
||||
const { onSortSelectState } = useSortDropdownStates(sortDropdownId);
|
||||
|
||||
const [onSortSelect, setOnSortSelect] = useRecoilState(onSortSelectState);
|
||||
|
||||
return {
|
||||
onSortSelect,
|
||||
setOnSortSelect,
|
||||
};
|
||||
}, renderHookConfig);
|
||||
|
||||
expect(result.current.onSortSelect).toBeUndefined();
|
||||
|
||||
act(() => {
|
||||
result.current.setOnSortSelect(mockOnSortSelect);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.onSortSelect).toBe(OnSortSelectFunction);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onSortSelect when a sort option is selected', async () => {
|
||||
const mockOnSortSelect = jest.fn(() => jest.fn());
|
||||
const sort: Sort = {
|
||||
fieldMetadataId: 'id',
|
||||
direction: 'asc',
|
||||
definition: sortDefinitions[0],
|
||||
};
|
||||
|
||||
const { result } = renderHook(() => {
|
||||
useSortDropdown({ sortDropdownId });
|
||||
const { onSortSelectState } = useSortDropdownStates(sortDropdownId);
|
||||
|
||||
const [onSortSelect, setOnSortSelect] = useRecoilState(onSortSelectState);
|
||||
|
||||
return {
|
||||
onSortSelect,
|
||||
setOnSortSelect,
|
||||
};
|
||||
}, renderHookConfig);
|
||||
|
||||
act(() => {
|
||||
result.current.setOnSortSelect(mockOnSortSelect);
|
||||
result.current.onSortSelect?.(sort);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.onSortSelect?.(sort);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnSortSelect.mock.results[0].value).toHaveBeenCalledWith(sort);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
|
||||
import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const useCloseSortDropdown = () => {
|
||||
const { resetSortDropdown } = useResetSortDropdown();
|
||||
|
||||
const { closeDropdown } = useDropdown(OBJECT_SORT_DROPDOWN_ID);
|
||||
|
||||
const closeSortDropdown = () => {
|
||||
closeDropdown();
|
||||
resetSortDropdown();
|
||||
};
|
||||
|
||||
return {
|
||||
closeSortDropdown,
|
||||
};
|
||||
};
|
||||
@ -1,84 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
import { VIEW_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ViewSortDropdownId';
|
||||
import { isSortDirectionMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isSortDirectionMenuUnfoldedState';
|
||||
import { selectedSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedSortDirectionState';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { OBJECT_SORT_DROPDOWN_ID } from '../constants/ObjectSortDropdownId';
|
||||
|
||||
// TODO: merge this with useSortDropdown
|
||||
export const useObjectSortDropdown = () => {
|
||||
const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] =
|
||||
useRecoilComponentStateV2(isSortDirectionMenuUnfoldedComponentState);
|
||||
|
||||
const [selectedSortDirection, setSelectedSortDirection] =
|
||||
useRecoilComponentStateV2(selectedSortDirectionComponentState);
|
||||
|
||||
const resetState = useCallback(() => {
|
||||
setIsSortDirectionMenuUnfolded(false);
|
||||
setSelectedSortDirection('asc');
|
||||
}, [setIsSortDirectionMenuUnfolded, setSelectedSortDirection]);
|
||||
|
||||
const { toggleDropdown, closeDropdown } = useDropdown(
|
||||
OBJECT_SORT_DROPDOWN_ID,
|
||||
);
|
||||
|
||||
const toggleSortDropdown = () => {
|
||||
toggleDropdown();
|
||||
resetState();
|
||||
};
|
||||
|
||||
const closeSortDropdown = () => {
|
||||
closeDropdown();
|
||||
resetState();
|
||||
};
|
||||
|
||||
const {
|
||||
onSortSelectState,
|
||||
isSortSelectedState,
|
||||
objectSortDropdownSearchInputState,
|
||||
setObjectSortDropdownSearchInput,
|
||||
resetSearchInput,
|
||||
} = useSortDropdown({
|
||||
sortDropdownId: VIEW_SORT_DROPDOWN_ID,
|
||||
});
|
||||
|
||||
const isSortSelected = useRecoilValue(isSortSelectedState);
|
||||
|
||||
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
VIEW_SORT_DROPDOWN_ID,
|
||||
);
|
||||
const onSortSelect = useRecoilValue(onSortSelectState);
|
||||
|
||||
const handleAddSort = (selectedSortDefinition: SortDefinition) => {
|
||||
closeSortDropdown();
|
||||
onSortSelect?.({
|
||||
fieldMetadataId: selectedSortDefinition.fieldMetadataId,
|
||||
direction: selectedSortDirection,
|
||||
definition: selectedSortDefinition,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
isSortDirectionMenuUnfolded,
|
||||
setIsSortDirectionMenuUnfolded,
|
||||
selectedSortDirection,
|
||||
setSelectedSortDirection,
|
||||
toggleSortDropdown,
|
||||
resetState,
|
||||
isSortSelected,
|
||||
objectSortDropdownSearchInputState,
|
||||
setObjectSortDropdownSearchInput,
|
||||
resetSearchInput,
|
||||
availableSortDefinitions,
|
||||
handleAddSort,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useResetRecordSortDropdownSearchInput = () => {
|
||||
const objectSortDropdownSearchInputCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
objectSortDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const resetRecordSortDropdownSearchInput = useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(objectSortDropdownSearchInputCallbackState, '');
|
||||
},
|
||||
[objectSortDropdownSearchInputCallbackState],
|
||||
);
|
||||
|
||||
return {
|
||||
resetRecordSortDropdownSearchInput,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
import { isSortDirectionMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isSortDirectionMenuUnfoldedState';
|
||||
import { selectedSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedSortDirectionState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
export const useResetSortDropdown = () => {
|
||||
const setIsSortDirectionMenuUnfolded = useSetRecoilComponentStateV2(
|
||||
isSortDirectionMenuUnfoldedComponentState,
|
||||
);
|
||||
|
||||
const setSelectedSortDirection = useSetRecoilComponentStateV2(
|
||||
selectedSortDirectionComponentState,
|
||||
);
|
||||
|
||||
const resetSortDropdown = () => {
|
||||
setIsSortDirectionMenuUnfolded(false);
|
||||
setSelectedSortDirection('asc');
|
||||
};
|
||||
|
||||
return {
|
||||
resetSortDropdown,
|
||||
};
|
||||
};
|
||||
@ -1,44 +0,0 @@
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useSortDropdownStates } from '@/object-record/object-sort-dropdown/hooks/useSortDropdownStates';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
|
||||
import { ObjectSortDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext';
|
||||
|
||||
type UseSortProps = {
|
||||
sortDropdownId?: string;
|
||||
};
|
||||
|
||||
export const useSortDropdown = (props?: UseSortProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
ObjectSortDropdownScopeInternalContext,
|
||||
props?.sortDropdownId,
|
||||
);
|
||||
|
||||
const {
|
||||
isSortSelectedState,
|
||||
onSortSelectState,
|
||||
objectSortDropdownSearchInputState,
|
||||
} = useSortDropdownStates(scopeId);
|
||||
|
||||
const setObjectSortDropdownSearchInput = useSetRecoilState(
|
||||
objectSortDropdownSearchInputState,
|
||||
);
|
||||
|
||||
const resetSearchInput = useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(objectSortDropdownSearchInputState, '');
|
||||
},
|
||||
[objectSortDropdownSearchInputState],
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
isSortSelectedState,
|
||||
onSortSelectState,
|
||||
objectSortDropdownSearchInputState,
|
||||
setObjectSortDropdownSearchInput,
|
||||
resetSearchInput,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId';
|
||||
import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useResetSortDropdown';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const useToggleSortDropdown = () => {
|
||||
const { toggleDropdown } = useDropdown(OBJECT_SORT_DROPDOWN_ID);
|
||||
|
||||
const { resetSortDropdown } = useResetSortDropdown();
|
||||
|
||||
const toggleSortDropdown = () => {
|
||||
toggleDropdown();
|
||||
resetSortDropdown();
|
||||
};
|
||||
|
||||
return {
|
||||
toggleSortDropdown,
|
||||
};
|
||||
};
|
||||
@ -1,21 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { ObjectSortDropdownScopeInternalContext } from './scope-internal-context/ObjectSortDropdownScopeInternalContext';
|
||||
|
||||
type ObjectSortDropdownScopeProps = {
|
||||
children: ReactNode;
|
||||
sortScopeId: string;
|
||||
};
|
||||
|
||||
export const ObjectSortDropdownScope = ({
|
||||
children,
|
||||
sortScopeId,
|
||||
}: ObjectSortDropdownScopeProps) => {
|
||||
return (
|
||||
<ObjectSortDropdownScopeInternalContext.Provider
|
||||
value={{ scopeId: sortScopeId }}
|
||||
>
|
||||
{children}
|
||||
</ObjectSortDropdownScopeInternalContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -1,11 +0,0 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey';
|
||||
|
||||
import { Sort } from '../../types/Sort';
|
||||
|
||||
type ObjectSortDropdownScopeInternalContextProps = RecoilComponentStateKey & {
|
||||
onSortSelect?: (sort: Sort) => void;
|
||||
};
|
||||
|
||||
export const ObjectSortDropdownScopeInternalContext =
|
||||
createScopeInternalContext<ObjectSortDropdownScopeInternalContextProps>();
|
||||
@ -18,6 +18,7 @@ import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDro
|
||||
|
||||
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
||||
|
||||
import { VIEW_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ViewSortDropdownId';
|
||||
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
|
||||
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
|
||||
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
||||
@ -39,7 +40,6 @@ export const ViewBar = ({
|
||||
const { objectNamePlural } = useParams();
|
||||
|
||||
const filterDropdownId = 'view-filter';
|
||||
const sortDropdownId = 'view-sort';
|
||||
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
@ -48,56 +48,55 @@ export const ViewBar = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<ViewEventContext.Provider value={{ onCurrentViewChange }}>
|
||||
<ViewBarEffect viewBarId={viewBarId} />
|
||||
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
||||
<ViewBarSortEffect sortDropdownId={sortDropdownId} />
|
||||
<QueryParamsFiltersEffect />
|
||||
<QueryParamsViewIdEffect />
|
||||
<ObjectSortDropdownComponentInstanceContext.Provider
|
||||
value={{ instanceId: VIEW_SORT_DROPDOWN_ID }}
|
||||
>
|
||||
<ViewEventContext.Provider value={{ onCurrentViewChange }}>
|
||||
<ViewBarEffect viewBarId={viewBarId} />
|
||||
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
||||
<ViewBarSortEffect />
|
||||
<QueryParamsFiltersEffect />
|
||||
<QueryParamsViewIdEffect />
|
||||
|
||||
<ViewBarPageTitle viewBarId={viewBarId} />
|
||||
<TopBar
|
||||
className={className}
|
||||
leftComponent={
|
||||
loading ? <ViewBarSkeletonLoader /> : <ViewPickerDropdown />
|
||||
}
|
||||
rightComponent={
|
||||
<>
|
||||
<ObjectFilterDropdownButton
|
||||
filterDropdownId={filterDropdownId}
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
|
||||
}}
|
||||
/>
|
||||
<ObjectSortDropdownComponentInstanceContext.Provider
|
||||
value={{ instanceId: sortDropdownId }}
|
||||
>
|
||||
<ViewBarPageTitle viewBarId={viewBarId} />
|
||||
<TopBar
|
||||
className={className}
|
||||
leftComponent={
|
||||
loading ? <ViewBarSkeletonLoader /> : <ViewPickerDropdown />
|
||||
}
|
||||
rightComponent={
|
||||
<>
|
||||
<ObjectFilterDropdownButton
|
||||
filterDropdownId={filterDropdownId}
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
|
||||
}}
|
||||
/>
|
||||
<ObjectSortDropdownButton
|
||||
sortDropdownId={sortDropdownId}
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
|
||||
}}
|
||||
/>
|
||||
</ObjectSortDropdownComponentInstanceContext.Provider>
|
||||
{optionsDropdownButton}
|
||||
</>
|
||||
}
|
||||
bottomComponent={
|
||||
<ViewBarDetails
|
||||
filterDropdownId={filterDropdownId}
|
||||
hasFilterButton
|
||||
viewBarId={viewBarId}
|
||||
objectNamePlural={objectNamePlural}
|
||||
rightComponent={
|
||||
<UpdateViewButtonGroup
|
||||
hotkeyScope={{
|
||||
scope: ViewsHotkeyScope.UpdateViewButtonDropdown,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</ViewEventContext.Provider>
|
||||
{optionsDropdownButton}
|
||||
</>
|
||||
}
|
||||
bottomComponent={
|
||||
<ViewBarDetails
|
||||
filterDropdownId={filterDropdownId}
|
||||
hasFilterButton
|
||||
viewBarId={viewBarId}
|
||||
objectNamePlural={objectNamePlural}
|
||||
rightComponent={
|
||||
<UpdateViewButtonGroup
|
||||
hotkeyScope={{
|
||||
scope: ViewsHotkeyScope.UpdateViewButtonDropdown,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</ViewEventContext.Provider>
|
||||
</ObjectSortDropdownComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
||||
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
@ -9,13 +8,7 @@ import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewS
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type ViewBarSortEffectProps = {
|
||||
sortDropdownId: string;
|
||||
};
|
||||
|
||||
export const ViewBarSortEffect = ({
|
||||
sortDropdownId,
|
||||
}: ViewBarSortEffectProps) => {
|
||||
export const ViewBarSortEffect = () => {
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||
|
||||
// TDOO: verify this instance id works
|
||||
@ -23,17 +16,13 @@ export const ViewBarSortEffect = ({
|
||||
availableSortDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const { onSortSelectState } = useSortDropdown({
|
||||
sortDropdownId,
|
||||
});
|
||||
const setOnSortSelect = useSetRecoilComponentStateV2(
|
||||
onSortSelectComponentState,
|
||||
);
|
||||
|
||||
// TDOO: verify this instance id works
|
||||
const setAvailableSortDefinitionsInSortDropdown =
|
||||
useSetRecoilComponentStateV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
sortDropdownId,
|
||||
);
|
||||
const setOnSortSelect = useSetRecoilState(onSortSelectState);
|
||||
useSetRecoilComponentStateV2(availableSortDefinitionsComponentState);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(availableSortDefinitions)) {
|
||||
|
||||
Reference in New Issue
Block a user