Skip to content

Commit

Permalink
Improve how the pagination engine interfaces with other components
Browse files Browse the repository at this point in the history
W.I.P.
  • Loading branch information
csillag committed Mar 31, 2024
1 parent 9ac134e commit 14361c3
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 28 deletions.
47 changes: 42 additions & 5 deletions src/app/components/Table/PaginationEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,52 @@ export interface SimplePaginationEngine {
linkToPage: (pageNumber: number) => To
}

/**
* The data returned by a comprehensive pagination engine to the data consumer component
*/
export interface PaginatedResults<Item> {
/**
* Control interface that can be plugged to a Table's `pagination` prop
*/
tablePaginationProps: TablePaginationProps

/**
* The data provided to the data consumer in the current window
*/
data: Item[] | undefined

/**
* Is the data set still loading from the server?
*/
isLoading: boolean
}

/**
* A Comprehensive PaginationEngine sits between the server and the consumer of the data and does transformations
*
* Specifically, the interface for loading the data and the one for the data consumers are decoupled.
*/
export interface ComprehensivePaginationEngine<Item, QueryResult extends List> {
selectedPage: number
offsetForQuery: number
limitForQuery: number
paramsForQuery: { offset: number; limit: number }
getResults: (queryResult: QueryResult | undefined, key?: keyof QueryResult) => PaginatedResults<Item>
/**
* The currently selected page from the data consumer's POV
*/
selectedPageForClient: number

/**
* Parameters for data to be loaded from the server
*/
paramsForServer: { offset: number; limit: number }

/**
* Get the current data/state info for the data consumer component.
*
* @param isLoading Is the data still being loaded from the server?
* @param queryResult the data coming in the server, requested according to this engine's specs, including metadata
* @param key The field where the actual records can be found within queryResults
*/
getResults: (
isLoading: boolean,
queryResult: QueryResult | undefined,
key?: keyof QueryResult,
) => PaginatedResults<Item>
}
63 changes: 45 additions & 18 deletions src/app/components/Table/useClientSidePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@ import { List } from '../../../oasis-nexus/api'
import { TablePaginationProps } from './TablePagination'

type ClientSizePaginationParams<Item> = {
/**
* How should we call the query parameter (in the URL)?
*/
paramName: string

/**
* The pagination page size from the POV of the data consumer component
*/
clientPageSize: number

/**
* The pagination page size used for actually loading the data from the server.
*
* Please note that currently this engine doesn't handle when the data consumer requires data which is not
* part of the initial window on the server side.
*/
serverPageSize: number
filter?: (item: Item) => boolean

/**
* Transformation to be applied after loading the data from the server, before presenting it to the data consumer component
*
* Can be used for filtering, ordering, etc
*/
transform?: (input: Item[]) => Item[]
}

const knownListKeys: string[] = ['total_count', 'is_total_count_clipped']
Expand All @@ -27,13 +47,15 @@ function findListIn<T extends List, Item>(data: T): Item[] {
}
}

/**
* The ClientSidePagination engine loads the data from the server with a big window in one go, for in-memory pagination
*/
export function useClientSidePagination<Item, QueryResult extends List>({
paramName,
clientPageSize,
serverPageSize,
filter,
transform,
}: ClientSizePaginationParams<Item>): ComprehensivePaginationEngine<Item, QueryResult> {
const selectedServerPage = 1
const [searchParams] = useSearchParams()
const selectedClientPageString = searchParams.get(paramName)
const selectedClientPage = parseInt(selectedClientPageString ?? '1', 10)
Expand All @@ -57,30 +79,35 @@ export function useClientSidePagination<Item, QueryResult extends List>({
return { search: newSearchParams.toString() }
}

const limit = serverPageSize
const offset = (selectedServerPage - 1) * clientPageSize
// From the server, we always want to load the first batch of data, with the provided (big) window.
// In theory, we could move this window as required, but currently this is not implemented.
const selectedServerPage = 1

// The query parameters that should be used for loading the data from the server
const paramsForQuery = {
offset,
limit,
offset: (selectedServerPage - 1) * serverPageSize,
limit: serverPageSize,
}

return {
selectedPage: selectedClientPage,
offsetForQuery: offset,
limitForQuery: limit,
paramsForQuery,
getResults: (queryResult, key) => {
const data = queryResult
? key
? (queryResult[key] as Item[])
: findListIn<QueryResult, Item>(queryResult)
selectedPageForClient: selectedClientPage,
paramsForServer: paramsForQuery,
getResults: (isLoading, queryResult, key) => {
const data = queryResult // we want to get list of items out from the incoming results
? key // do we know where (in which field) to look?
? (queryResult[key] as Item[]) // If yes, just get out the data
: findListIn<QueryResult, Item>(queryResult) // If no, we will try to guess
: undefined
const filteredData = !!data && !!filter ? data.filter(filter) : data

// Apply the specified client-side transformation
const filteredData = !!data && !!transform ? transform(data) : data

// The data window from the POV of the data consumer component
const offset = (selectedClientPage - 1) * clientPageSize
const limit = clientPageSize
const dataWindow = filteredData ? filteredData.slice(offset, offset + limit) : undefined

// The control interface for the data consumer component (i.e. Table)
const tableProps: TablePaginationProps = {
selectedPage: selectedClientPage,
linkToPage,
Expand All @@ -96,8 +123,8 @@ export function useClientSidePagination<Item, QueryResult extends List>({
return {
tablePaginationProps: tableProps,
data: dataWindow,
isLoading,
}
},
// tableProps,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ export function useComprehensiveSearchParamsPagination<Item, QueryResult extends
}

return {
selectedPage,
offsetForQuery: offset,
limitForQuery: limit,
paramsForQuery,
getResults: (queryResult, key) => {
selectedPageForClient: selectedPage,
paramsForServer: paramsForQuery,
getResults: (isLoading, queryResult, key) => {
const data = queryResult
? key
? (queryResult[key] as Item[])
Expand All @@ -85,6 +83,7 @@ export function useComprehensiveSearchParamsPagination<Item, QueryResult extends
return {
tablePaginationProps: tableProps,
data: filteredData,
isLoading,
}
},
// tableProps,
Expand Down

0 comments on commit 14361c3

Please sign in to comment.