diff --git a/app/react/components/datatables/types.ts b/app/react/components/datatables/types.ts index 94e8ab5bf..b81aaeec5 100644 --- a/app/react/components/datatables/types.ts +++ b/app/react/components/datatables/types.ts @@ -25,21 +25,24 @@ export function paginationSettings( } export interface SortableTableSettings { - sortBy: { id: string; desc: boolean }; - setSortBy: (id: string, desc: boolean) => void; + sortBy: { id: string; desc: boolean } | undefined; + setSortBy: (id: string | undefined, desc: boolean) => void; } export function sortableSettings( set: ZustandSetFunc, - initialSortBy: string | { id: string; desc: boolean } + initialSortBy?: string | { id: string; desc: boolean } ): SortableTableSettings { return { sortBy: typeof initialSortBy === 'string' ? { id: initialSortBy, desc: false } : initialSortBy, - setSortBy: (id: string, desc: boolean) => - set((s) => ({ ...s, sortBy: { id, desc } })), + setSortBy: (id: string | undefined, desc: boolean) => + set((s) => ({ + ...s, + sortBy: typeof id === 'string' ? { id, desc } : id, + })), }; } @@ -79,7 +82,7 @@ export interface BasicTableSettings export function createPersistedStore( storageKey: string, - initialSortBy: string | { id: string; desc: boolean } = 'name', + initialSortBy?: string | { id: string; desc: boolean }, create: (set: ZustandSetFunc) => Omit = () => ({} as T) ) { @@ -87,11 +90,8 @@ export function createPersistedStore( persist( (set) => ({ - ...sortableSettings( - set as ZustandSetFunc, - initialSortBy - ), - ...paginationSettings(set as ZustandSetFunc), + ...sortableSettings(set, initialSortBy), + ...paginationSettings(set), ...create(set), } as T), { diff --git a/app/react/components/datatables/useTableState.ts b/app/react/components/datatables/useTableState.ts index 0bd74c9a8..5681a5d43 100644 --- a/app/react/components/datatables/useTableState.ts +++ b/app/react/components/datatables/useTableState.ts @@ -23,21 +23,24 @@ export function useTableState< } export function useTableStateWithoutStorage( - defaultSortKey: string + defaultSortKey?: string ): BasicTableSettings & { setSearch: (search: string) => void; search: string; } { const [search, setSearch] = useState(''); const [pageSize, setPageSize] = useState(10); - const [sortBy, setSortBy] = useState({ id: defaultSortKey, desc: false }); + const [sortBy, setSortBy] = useState( + defaultSortKey ? { id: defaultSortKey, desc: false } : undefined + ); return { search, setSearch, pageSize, setPageSize, - setSortBy: (id: string, desc: boolean) => setSortBy({ id, desc }), + setSortBy: (id: string | undefined, desc: boolean) => + setSortBy(id ? { id, desc } : undefined), sortBy, }; } diff --git a/app/react/edge/components/EdgeGroupAssociationTable.tsx b/app/react/edge/components/EdgeGroupAssociationTable.tsx index 749374414..f1f315223 100644 --- a/app/react/edge/components/EdgeGroupAssociationTable.tsx +++ b/app/react/edge/components/EdgeGroupAssociationTable.tsx @@ -56,8 +56,8 @@ export function EdgeGroupAssociationTable({ pageLimit: tableState.pageSize, page: page + 1, search: tableState.search, - sort: tableState.sortBy.id as 'Group' | 'Name', - order: tableState.sortBy.desc ? 'desc' : 'asc', + sort: tableState.sortBy?.id as 'Group' | 'Name', + order: tableState.sortBy?.desc ? 'desc' : 'asc', ...query, }); const groupsQuery = useGroups({ diff --git a/app/react/edge/edge-devices/WaitingRoomView/Datatable/Datatable.tsx b/app/react/edge/edge-devices/WaitingRoomView/Datatable/Datatable.tsx index 0a1ddc132..4c5c408a7 100644 --- a/app/react/edge/edge-devices/WaitingRoomView/Datatable/Datatable.tsx +++ b/app/react/edge/edge-devices/WaitingRoomView/Datatable/Datatable.tsx @@ -9,7 +9,7 @@ import { useEnvironments } from './useEnvironments'; const storageKey = 'edge-devices-waiting-room'; -const settingsStore = createPersistedStore(storageKey); +const settingsStore = createPersistedStore(storageKey, 'name'); export function Datatable() { const tableState = useTableState(settingsStore, storageKey); diff --git a/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/EnvironmentsDatatable.tsx b/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/EnvironmentsDatatable.tsx index ad2029c76..6dd261178 100644 --- a/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/EnvironmentsDatatable.tsx +++ b/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/EnvironmentsDatatable.tsx @@ -44,8 +44,8 @@ export function EnvironmentsDatatable() { pageLimit: tableState.pageSize, page: page + 1, search: tableState.search, - sort: tableState.sortBy.id as 'Group' | 'Name', - order: tableState.sortBy.desc ? 'desc' : 'asc', + sort: tableState.sortBy?.id as 'Group' | 'Name', + order: tableState.sortBy?.desc ? 'desc' : 'asc', edgeStackId: stackId, edgeStackStatus: statusFilter, }); diff --git a/app/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatable.tsx b/app/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatable.tsx index cc5b462da..d9eaef5a6 100644 --- a/app/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatable.tsx +++ b/app/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatable.tsx @@ -15,7 +15,7 @@ import { IngressControllerClassMap } from '../types'; import { columns } from './columns'; const storageKey = 'ingressClasses'; -const settingsStore = createPersistedStore(storageKey); +const settingsStore = createPersistedStore(storageKey, 'name'); interface Props { onChangeControllers: ( diff --git a/app/react/portainer/environments/ListView/EnvironmentsDatatable.tsx b/app/react/portainer/environments/ListView/EnvironmentsDatatable.tsx index dba304a65..1b17a818c 100644 --- a/app/react/portainer/environments/ListView/EnvironmentsDatatable.tsx +++ b/app/react/portainer/environments/ListView/EnvironmentsDatatable.tsx @@ -37,8 +37,10 @@ export function EnvironmentsDatatable({ excludeSnapshots: true, page: page + 1, pageLimit: tableState.pageSize, - sort: isSortType(tableState.sortBy.id) ? tableState.sortBy.id : undefined, - order: tableState.sortBy.desc ? 'desc' : 'asc', + sort: isSortType(tableState.sortBy?.id) + ? tableState.sortBy?.id + : undefined, + order: tableState.sortBy?.desc ? 'desc' : 'asc', }, { enabled: groupsQuery.isSuccess, refetchInterval: 30 * 1000 } ); diff --git a/app/react/portainer/environments/environment-groups/components/GroupAssociationTable.tsx b/app/react/portainer/environments/environment-groups/components/GroupAssociationTable.tsx index 33f172fdf..061e15286 100644 --- a/app/react/portainer/environments/environment-groups/components/GroupAssociationTable.tsx +++ b/app/react/portainer/environments/environment-groups/components/GroupAssociationTable.tsx @@ -38,8 +38,8 @@ export function GroupAssociationTable({ pageLimit: tableState.pageSize, page: page + 1, search: tableState.search, - sort: tableState.sortBy.id as 'Name', - order: tableState.sortBy.desc ? 'desc' : 'asc', + sort: tableState.sortBy?.id as 'Name', + order: tableState.sortBy?.desc ? 'desc' : 'asc', ...query, }); diff --git a/app/react/portainer/environments/queries/useEnvironmentList.ts b/app/react/portainer/environments/queries/useEnvironmentList.ts index ba05e9e23..64432d53d 100644 --- a/app/react/portainer/environments/queries/useEnvironmentList.ts +++ b/app/react/portainer/environments/queries/useEnvironmentList.ts @@ -14,7 +14,7 @@ export const ENVIRONMENTS_POLLING_INTERVAL = 30000; // in ms export const SortOptions = ['Name', 'Group', 'Status'] as const; export type SortType = (typeof SortOptions)[number]; -export function isSortType(value: string): value is SortType { +export function isSortType(value?: string): value is SortType { return SortOptions.includes(value as SortType); } diff --git a/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/TeamMembersList/TeamMembersList.tsx b/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/TeamMembersList/TeamMembersList.tsx index f0a6a1d1f..e7f25dc75 100644 --- a/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/TeamMembersList/TeamMembersList.tsx +++ b/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/TeamMembersList/TeamMembersList.tsx @@ -33,7 +33,9 @@ export function TeamMembersList({ users, roles, disabled, teamId }: Props) { const [search, setSearch] = useState(''); const [pageSize, setPageSize] = useState(10); - const [sortBy, setSortBy] = useState({ id: 'name', desc: false }); + const [sortBy, setSortBy] = useState< + { id: string; desc: boolean } | undefined + >({ id: 'name', desc: false }); const { isAdmin } = useUser(); @@ -79,8 +81,8 @@ export function TeamMembersList({ users, roles, disabled, teamId }: Props) { ); - function handleSetSort(colId: string, desc: boolean) { - setSortBy({ id: colId, desc }); + function handleSetSort(colId: string | undefined, desc: boolean) { + setSortBy(colId ? { id: colId, desc } : undefined); } function handleRemoveMembers(userIds: UserId[]) { diff --git a/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/UsersList/UsersList.tsx b/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/UsersList/UsersList.tsx index fd790d2b3..15c5f8e55 100644 --- a/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/UsersList/UsersList.tsx +++ b/app/react/portainer/users/teams/ItemView/TeamAssociationSelector/UsersList/UsersList.tsx @@ -25,7 +25,9 @@ export function UsersList({ users, disabled, teamId }: Props) { const [search, setSearch] = useState(''); const [pageSize, setPageSize] = useState(10); const addMemberMutation = useAddMemberMutation(teamId); - const [sortBy, setSortBy] = useState({ id: 'name', desc: false }); + const [sortBy, setSortBy] = useState< + { id: string; desc: boolean } | undefined + >({ id: 'name', desc: false }); const { isAdmin } = useUser(); @@ -62,8 +64,8 @@ export function UsersList({ users, disabled, teamId }: Props) { ); - function handleSetSort(colId: string, desc: boolean) { - setSortBy({ id: colId, desc }); + function handleSetSort(colId: string | undefined, desc: boolean) { + setSortBy(colId ? { id: colId, desc } : undefined); } function handleAddAllMembers(userIds: UserId[]) { diff --git a/app/react/portainer/users/teams/ListView/TeamsDatatable/TeamsDatatable.tsx b/app/react/portainer/users/teams/ListView/TeamsDatatable/TeamsDatatable.tsx index e266c839d..a8f277385 100644 --- a/app/react/portainer/users/teams/ListView/TeamsDatatable/TeamsDatatable.tsx +++ b/app/react/portainer/users/teams/ListView/TeamsDatatable/TeamsDatatable.tsx @@ -25,7 +25,7 @@ interface Props { isAdmin: boolean; } -const settingsStore = createPersistedStore(storageKey); +const settingsStore = createPersistedStore(storageKey, 'name'); export function TeamsDatatable({ teams, isAdmin }: Props) { const { handleRemove } = useRemoveMutation();