Fix changing sort direction

This commit is contained in:
Mark McDowall 2025-11-15 11:49:59 -08:00
parent 21592f3d69
commit aac4760d30
13 changed files with 133 additions and 38 deletions

View file

@ -17,6 +17,7 @@ import TableBody from 'Components/Table/TableBody';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import { executeCommand } from 'Store/Actions/commandActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
@ -31,6 +32,7 @@ import translate from 'Utilities/String/translate';
import BlocklistFilterModal from './BlocklistFilterModal';
import {
setBlocklistOption,
setBlocklistSort,
useBlocklistOptions,
} from './blocklistOptionsStore';
import BlocklistRow from './BlocklistRow';
@ -129,9 +131,15 @@ function BlocklistContent() {
[]
);
const handleSortPress = useCallback((sortKey: string) => {
setBlocklistOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setBlocklistSort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {

View file

@ -6,7 +6,7 @@ import translate from 'Utilities/String/translate';
export type BlocklistOptions = PageableOptions;
const { useOptions, useOption, setOptions, setOption } =
const { useOptions, useOption, setOptions, setOption, setSort } =
createOptionsStore<BlocklistOptions>('blocklist_options', () => {
return {
pageSize: 20,
@ -69,3 +69,4 @@ export const useBlocklistOptions = useOptions;
export const setBlocklistOptions = setOptions;
export const useBlocklistOption = useOption;
export const setBlocklistOption = setOption;
export const setBlocklistSort = setSort;

View file

@ -1,9 +1,5 @@
import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
setQueueOption,
setQueueOptions,
} from 'Activity/Queue/queueOptionsStore';
import Alert from 'Components/Alert';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
@ -19,6 +15,7 @@ import TablePager from 'Components/Table/TablePager';
import createEpisodesFetchingSelector from 'Episode/createEpisodesFetchingSelector';
import useCurrentPage from 'Helpers/Hooks/useCurrentPage';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import { clearEpisodes, fetchEpisodes } from 'Store/Actions/episodeActions';
import { clearEpisodeFiles } from 'Store/Actions/episodeFileActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
@ -31,7 +28,12 @@ import {
} from 'Utilities/pagePopulator';
import translate from 'Utilities/String/translate';
import HistoryFilterModal from './HistoryFilterModal';
import { useHistoryOptions } from './historyOptionsStore';
import {
setHistoryOption,
setHistoryOptions,
setHistorySort,
useHistoryOptions,
} from './historyOptionsStore';
import HistoryRow from './HistoryRow';
import useHistory, { useFilters } from './useHistory';
@ -67,18 +69,24 @@ function History() {
const handleFilterSelect = useCallback(
(selectedFilterKey: string | number) => {
setQueueOption('selectedFilterKey', selectedFilterKey);
setHistoryOption('selectedFilterKey', selectedFilterKey);
},
[]
);
const handleSortPress = useCallback((sortKey: string) => {
setQueueOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setHistorySort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {
setQueueOptions(payload);
setHistoryOptions(payload);
if (payload.pageSize) {
goToPage(1);

View file

@ -9,7 +9,7 @@ import translate from 'Utilities/String/translate';
export type HistoryOptions = PageableOptions;
const { useOptions, useOption, setOptions, setOption } =
const { useOptions, useOption, setOptions, setOption, setSort } =
createOptionsStore<HistoryOptions>('history_options', () => {
return {
includeUnknownSeriesItems: true,
@ -107,3 +107,4 @@ export const useHistoryOptions = useOptions;
export const setHistoryOptions = setOptions;
export const useHistoryOption = useOption;
export const setHistoryOption = setOption;
export const setHistorySort = setSort;

View file

@ -24,6 +24,7 @@ import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptions
import TablePager from 'Components/Table/TablePager';
import createEpisodesFetchingSelector from 'Episode/createEpisodesFetchingSelector';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import { executeCommand } from 'Store/Actions/commandActions';
import { clearEpisodes, fetchEpisodes } from 'Store/Actions/episodeActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
@ -42,6 +43,7 @@ import QueueOptions from './QueueOptions';
import {
setQueueOption,
setQueueOptions,
setQueueSort,
useQueueOptions,
} from './queueOptionsStore';
import QueueRow from './QueueRow';
@ -164,9 +166,15 @@ function QueueContent() {
[]
);
const handleSortPress = useCallback((sortKey: string) => {
setQueueOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setQueueSort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {

View file

@ -17,7 +17,7 @@ export interface QueueOptions extends PageableOptions {
removalOptions: QueueRemovalOptions;
}
const { useOptions, useOption, setOptions, setOption } =
const { useOptions, useOption, setOptions, setOption, setSort } =
createOptionsStore<QueueOptions>('queue_options', () => {
return {
includeUnknownSeriesItems: true,
@ -158,3 +158,4 @@ export const useQueueOptions = useOptions;
export const setQueueOptions = setOptions;
export const useQueueOption = useOption;
export const setQueueOption = setOption;
export const setQueueSort = setSort;

View file

@ -8,9 +8,12 @@ type TSettingsWithoutColumns = object;
interface TSettingsWithColumns {
columns: Column[];
selectedFilterKey: string | number;
sortKey: string;
sortDirection: SortDirection;
}
type TSettingd = TSettingsWithoutColumns | TSettingsWithColumns;
type TSettings = TSettingsWithoutColumns | TSettingsWithColumns;
export interface PageableOptions {
pageSize: number;
@ -25,7 +28,7 @@ export type OptionChanged<T> = {
value: T[keyof T];
};
export const createOptionsStore = <T extends TSettingd>(
export const createOptionsStore = <T extends TSettings>(
name: string,
state: StateCreator<T>,
options: Omit<PersistOptions<T>, 'name' | 'storage'> = {}
@ -52,6 +55,10 @@ export const createOptionsStore = <T extends TSettingd>(
};
const setOptions = (options: Partial<T>) => {
if ('sortKey' in options || 'sortDirection' in options) {
throw new Error('Use setSort to set sortKey and sortDirection');
}
store.setState((state) => ({
...state,
...options,
@ -59,12 +66,47 @@ export const createOptionsStore = <T extends TSettingd>(
};
const setOption = <K extends keyof T>(key: K, value: T[K]) => {
if (key === 'sortKey' || key === 'sortDirection') {
throw new Error('Use setSort to set sortKey and sortDirection');
}
store.setState((state) => ({
...state,
[key]: value,
}));
};
const setSort = ({
sortKey,
sortDirection,
}: {
sortKey: string;
sortDirection: SortDirection | undefined;
}) => {
// @ts-expect-error - Cannot verify if T has sortKey and sortDirection
store.setState((state) => {
if ('sortKey' in state === false || 'sortDirection' in state === false) {
return state;
}
let newSortDirection = sortDirection;
if (sortDirection == null) {
if (state.sortKey === sortKey) {
newSortDirection =
state.sortDirection === 'ascending' ? 'descending' : 'ascending';
} else {
newSortDirection = state.sortDirection;
}
}
return {
sortKey,
sortDirection: newSortDirection,
};
});
};
return {
store,
useOptions,
@ -73,10 +115,11 @@ export const createOptionsStore = <T extends TSettingd>(
getOption,
setOptions,
setOption,
setSort,
};
};
const merge = <T extends TSettingd>(
const merge = <T extends TSettings>(
persistedState: unknown,
currentState: T
) => {

View file

@ -14,6 +14,7 @@ import TableBody from 'Components/Table/TableBody';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import { executeCommand } from 'Store/Actions/commandActions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import { TableOptionsChangePayload } from 'typings/Table';
@ -21,6 +22,7 @@ import translate from 'Utilities/String/translate';
import {
setEventOption,
setEventOptions,
setEventSort,
useEventOptions,
} from './eventOptionsStore';
import LogsTableRow from './LogsTableRow';
@ -56,9 +58,15 @@ function LogsTable() {
[]
);
const handleSortPress = useCallback((sortKey: string) => {
setEventOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setEventSort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {

View file

@ -6,9 +6,8 @@ import translate from 'Utilities/String/translate';
export type EventOptions = PageableOptions;
const { useOptions, setOptions, setOption } = createOptionsStore<EventOptions>(
'event_options',
() => {
const { useOptions, setOptions, setOption, setSort } =
createOptionsStore<EventOptions>('event_options', () => {
return {
pageSize: 50,
selectedFilterKey: 'all',
@ -52,9 +51,9 @@ const { useOptions, setOptions, setOption } = createOptionsStore<EventOptions>(
},
],
};
}
);
});
export const useEventOptions = useOptions;
export const setEventOptions = setOptions;
export const setEventOption = setOption;
export const setEventSort = setSort;

View file

@ -21,6 +21,7 @@ import TablePager from 'Components/Table/TablePager';
import Episode from 'Episode/Episode';
import { useToggleEpisodesMonitored } from 'Episode/useEpisode';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import { executeCommand } from 'Store/Actions/commandActions';
import { fetchEpisodeFiles } from 'Store/Actions/episodeFileActions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
@ -36,6 +37,7 @@ import translate from 'Utilities/String/translate';
import {
setCutoffUnmetOption,
setCutoffUnmetOptions,
setCutoffUnmetSort,
useCutoffUnmetOptions,
} from './cutoffUnmetOptionsStore';
import CutoffUnmetRow from './CutoffUnmetRow';
@ -156,9 +158,15 @@ function CutoffUnmetContent() {
setCutoffUnmetOption('selectedFilterKey', filterKey);
}, []);
const handleSortPress = useCallback((sortKey: string) => {
setCutoffUnmetOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setCutoffUnmetSort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {

View file

@ -4,7 +4,7 @@ import {
} from 'Helpers/Hooks/useOptionsStore';
import translate from 'Utilities/String/translate';
const { useOptions, useOption, setOptions, setOption } =
const { useOptions, useOption, setOptions, setOption, setSort } =
createOptionsStore<PageableOptions>('cutoffUnmet_options', () => {
return {
pageSize: 20,
@ -65,3 +65,4 @@ export const useCutoffUnmetOptions = useOptions;
export const setCutoffUnmetOptions = setOptions;
export const useCutoffUnmetOption = useOption;
export const setCutoffUnmetOption = setOption;
export const setCutoffUnmetSort = setSort;

View file

@ -21,6 +21,7 @@ import TablePager from 'Components/Table/TablePager';
import Episode from 'Episode/Episode';
import { useToggleEpisodesMonitored } from 'Episode/useEpisode';
import { align, icons, kinds } from 'Helpers/Props';
import { SortDirection } from 'Helpers/Props/sortDirections';
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
import { executeCommand } from 'Store/Actions/commandActions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
@ -36,6 +37,7 @@ import translate from 'Utilities/String/translate';
import {
setMissingOption,
setMissingOptions,
setMissingSort,
useMissingOptions,
} from './missingOptionsStore';
import MissingRow from './MissingRow';
@ -163,9 +165,15 @@ function MissingContent() {
setMissingOption('selectedFilterKey', filterKey);
}, []);
const handleSortPress = useCallback((sortKey: string) => {
setMissingOption('sortKey', sortKey);
}, []);
const handleSortPress = useCallback(
(sortKey: string, sortDirection?: SortDirection) => {
setMissingSort({
sortKey,
sortDirection,
});
},
[]
);
const handleTableOptionChange = useCallback(
(payload: TableOptionsChangePayload) => {

View file

@ -4,7 +4,7 @@ import {
} from 'Helpers/Hooks/useOptionsStore';
import translate from 'Utilities/String/translate';
const { useOptions, useOption, setOptions, setOption } =
const { useOptions, useOption, setOptions, setOption, setSort } =
createOptionsStore<PageableOptions>('missing_options', () => {
return {
pageSize: 20,
@ -60,3 +60,4 @@ export const useMissingOptions = useOptions;
export const setMissingOptions = setOptions;
export const useMissingOption = useOption;
export const setMissingOption = setOption;
export const setMissingSort = setSort;