diff --git a/frontend/src/component/feature/FeatureToggleList/FeatureToggleListTable.tsx b/frontend/src/component/feature/FeatureToggleList/FeatureToggleListTable.tsx index 3638d65d79..86d8fff352 100644 --- a/frontend/src/component/feature/FeatureToggleList/FeatureToggleListTable.tsx +++ b/frontend/src/component/feature/FeatureToggleList/FeatureToggleListTable.tsx @@ -8,11 +8,7 @@ import { useTheme, } from '@mui/material'; import { Link as RouterLink } from 'react-router-dom'; -import { - useReactTable, - getCoreRowModel, - createColumnHelper, -} from '@tanstack/react-table'; +import { useReactTable, createColumnHelper } from '@tanstack/react-table'; import { PaginatedTable, TablePlaceholder } from 'component/common/Table'; import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext'; import { DateCell } from 'component/common/Table/cells/DateCell/DateCell'; @@ -48,6 +44,7 @@ import { import mapValues from 'lodash.mapvalues'; import { NumberParam, StringParam, withDefault } from 'use-query-params'; import { BooleansStringParam } from 'utils/serializeQueryParams'; +import { withTableState } from 'utils/withTableState'; import { usePersistentTableState } from 'hooks/usePersistentTableState'; export const featuresPlaceholder = Array(15).fill({ @@ -202,74 +199,12 @@ export const FeatureToggleListTable: VFC = () => { [initialLoad, features, loading], ); - const table = useReactTable({ - columns, - data, - enableSorting: true, - enableMultiSort: false, - manualPagination: true, - manualSorting: true, - enableSortingRemoval: false, - getCoreRowModel: getCoreRowModel(), - enableHiding: true, - state: { - sorting: [ - { - id: tableState.sortBy || 'createdAt', - desc: tableState.sortOrder === 'desc', - }, - ], - pagination: { - pageIndex: tableState.offset - ? tableState.offset / tableState.limit - : 0, - pageSize: tableState.limit, - }, - }, - onSortingChange: (newSortBy) => { - if (typeof newSortBy === 'function') { - const computedSortBy = newSortBy([ - { - id: tableState.sortBy || 'createdAt', - desc: tableState.sortOrder === 'desc', - }, - ])[0]; - setTableState({ - sortBy: computedSortBy?.id, - sortOrder: computedSortBy?.desc ? 'desc' : 'asc', - }); - } else { - const sortBy = newSortBy[0]; - setTableState({ - sortBy: sortBy?.id, - sortOrder: sortBy?.desc ? 'desc' : 'asc', - }); - } - }, - onPaginationChange: (newPagination) => { - if (typeof newPagination === 'function') { - const computedPagination = newPagination({ - pageSize: tableState.limit, - pageIndex: tableState.offset - ? Math.floor(tableState.offset / tableState.limit) - : 0, - }); - setTableState({ - limit: computedPagination?.pageSize, - offset: computedPagination?.pageIndex - ? computedPagination?.pageIndex * - computedPagination?.pageSize - : 0, - }); - } else { - const { pageSize, pageIndex } = newPagination; - setTableState({ - limit: pageSize, - offset: pageIndex ? pageIndex * pageSize : 0, - }); - } - }, - }); + const table = useReactTable( + withTableState(tableState, setTableState, { + columns, + data, + }), + ); useEffect(() => { if (isSmallScreen) { diff --git a/frontend/src/component/project/Project/ProjectFeatureToggles/PaginatedProjectFeatureToggles.tsx b/frontend/src/component/project/Project/ProjectFeatureToggles/PaginatedProjectFeatureToggles.tsx index e3b383104e..5160a80bcc 100644 --- a/frontend/src/component/project/Project/ProjectFeatureToggles/PaginatedProjectFeatureToggles.tsx +++ b/frontend/src/component/project/Project/ProjectFeatureToggles/PaginatedProjectFeatureToggles.tsx @@ -23,7 +23,6 @@ import { useSortBy, useTable, } from 'react-table'; -import type { FeatureSchema, SearchFeaturesSchema } from 'openapi'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { PageContent } from 'component/common/PageContent/PageContent'; diff --git a/frontend/src/component/project/Project/ProjectOverview.tsx b/frontend/src/component/project/Project/ProjectOverview.tsx index 22bb2da18b..d44bea44db 100644 --- a/frontend/src/component/project/Project/ProjectOverview.tsx +++ b/frontend/src/component/project/Project/ProjectOverview.tsx @@ -10,14 +10,7 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useLastViewedProject } from 'hooks/useLastViewedProject'; import { ProjectStats } from './ProjectStats/ProjectStats'; import { useUiFlag } from 'hooks/useUiFlag'; -import { - DEFAULT_PAGE_LIMIT, - useFeatureSearch, -} from 'hooks/api/getters/useFeatureSearch/useFeatureSearch'; -import { - // ProjectTableState, - PaginatedProjectFeatureToggles, -} from './ProjectFeatureToggles/PaginatedProjectFeatureToggles'; +import { PaginatedProjectFeatureToggles } from './ProjectFeatureToggles/PaginatedProjectFeatureToggles'; import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview'; import { FeatureTypeCount } from '../../../interfaces/project'; diff --git a/frontend/src/utils/withTableState.ts b/frontend/src/utils/withTableState.ts new file mode 100644 index 0000000000..7c9a574996 --- /dev/null +++ b/frontend/src/utils/withTableState.ts @@ -0,0 +1,128 @@ +import { + type OnChangeFn, + type SortingState, + type PaginationState, + type TableOptions, + getCoreRowModel, +} from '@tanstack/react-table'; + +const createOnSortingChange = + ( + tableState: { + sortBy: string; + sortOrder: string; + }, + setTableState: (newState: { + sortBy?: string; + sortOrder?: string; + }) => void, + ): OnChangeFn => + (newSortBy) => { + if (typeof newSortBy === 'function') { + const computedSortBy = newSortBy([ + { + id: tableState.sortBy, + desc: tableState.sortOrder === 'desc', + }, + ])[0]; + setTableState({ + sortBy: computedSortBy?.id, + sortOrder: computedSortBy?.desc ? 'desc' : 'asc', + }); + } else { + const sortBy = newSortBy[0]; + setTableState({ + sortBy: sortBy?.id, + sortOrder: sortBy?.desc ? 'desc' : 'asc', + }); + } + }; + +const createOnPaginationChange = + ( + tableState: { + limit: number; + offset: number; + }, + setTableState: (newState: { + limit?: number; + offset?: number; + }) => void, + ): OnChangeFn => + (newPagination) => { + if (typeof newPagination === 'function') { + const computedPagination = newPagination({ + pageSize: tableState.limit, + pageIndex: tableState.offset + ? Math.floor(tableState.offset / tableState.limit) + : 0, + }); + setTableState({ + limit: computedPagination?.pageSize, + offset: computedPagination?.pageIndex + ? computedPagination?.pageIndex * + computedPagination?.pageSize + : 0, + }); + } else { + const { pageSize, pageIndex } = newPagination; + setTableState({ + limit: pageSize, + offset: pageIndex ? pageIndex * pageSize : 0, + }); + } + }; + +const createSortingState = (tableState: { + sortBy: string; + sortOrder: string; +}) => ({ + sorting: [ + { + id: tableState.sortBy, + desc: tableState.sortOrder === 'desc', + }, + ], +}); + +const createPaginationState = (tableState: { + limit: number; + offset: number; +}) => ({ + pagination: { + pageIndex: tableState.offset ? tableState.offset / tableState.limit : 0, + pageSize: tableState.limit, + }, +}); + +export const withTableState = ( + tableState: { + sortBy: string; + sortOrder: string; + limit: number; + offset: number; + }, + setTableState: (newState: { + sortBy?: string; + sortOrder?: string; + limit?: number; + offset?: number; + }) => void, + options: Omit, 'getCoreRowModel'>, +) => ({ + getCoreRowModel: getCoreRowModel(), + enableSorting: true, + enableMultiSort: false, + manualPagination: true, + manualSorting: true, + enableSortingRemoval: false, + enableHiding: true, + state: { + ...createSortingState(tableState), + ...createPaginationState(tableState), + ...(options.state || {}), + }, + onPaginationChange: createOnPaginationChange(tableState, setTableState), + onSortingChange: createOnSortingChange(tableState, setTableState), + ...options, +});