11import { To , useSearchParams } from 'react-router-dom'
22import { AppErrors } from '../../../types/errors'
3- import { ComprehensivePaginationEngine } from './PaginationEngine'
3+ import { ComprehensivePaginatedResults , ComprehensivePaginationEngine } from './PaginationEngine'
44import { List } from '../../../oasis-nexus/api'
55import { TablePaginationProps } from './TablePagination'
66
7- type ClientSizePaginationParams < Item > = {
7+ type ClientSizePaginationParams < Item , QueryResult extends List , ExtractedData = typeof undefined > = {
8+ /**
9+ * How should we call the query parameter (in the URL)?
10+ */
811 paramName : string
12+
13+ /**
14+ * The pagination page size from the POV of the data consumer component
15+ */
916 clientPageSize : number
17+
18+ /**
19+ * The pagination page size used for actually loading the data from the server.
20+ *
21+ * Please note that currently this engine doesn't handle when the data consumer requires data which is not
22+ * part of the initial window on the server side.
23+ */
1024 serverPageSize : number
25+
26+ /**
27+ * Filter to be applied to the loaded data.
28+ *
29+ * If both transform and filter is set, transform will run first.
30+ */
1131 filter ?: ( item : Item ) => boolean
32+
33+ /**
34+ * Transformation to be applied after loading the data from the server, before presenting it to the data consumer component
35+ *
36+ * Can be used for ordering, aggregation, etc.D
37+ * If both transform and filter is set, transform will run first.
38+ */
39+ transform ?: ( input : Item [ ] , results : QueryResult ) => [ Item [ ] , ExtractedData ]
1240}
1341
1442const knownListKeys : string [ ] = [ 'total_count' , 'is_total_count_clipped' ]
@@ -27,13 +55,20 @@ function findListIn<T extends List, Item>(data: T): Item[] {
2755 }
2856}
2957
30- export function useClientSidePagination < Item , QueryResult extends List > ( {
58+ /**
59+ * The ClientSidePagination engine loads the data from the server with a big window in one go, for in-memory pagination
60+ */
61+ export function useClientSidePagination < Item , QueryResult extends List , ExtractedData = typeof undefined > ( {
3162 paramName,
3263 clientPageSize,
3364 serverPageSize,
3465 filter,
35- } : ClientSizePaginationParams < Item > ) : ComprehensivePaginationEngine < Item , QueryResult > {
36- const selectedServerPage = 1
66+ transform,
67+ } : ClientSizePaginationParams < Item , QueryResult , ExtractedData > ) : ComprehensivePaginationEngine <
68+ Item ,
69+ QueryResult ,
70+ ExtractedData
71+ > {
3772 const [ searchParams ] = useSearchParams ( )
3873 const selectedClientPageString = searchParams . get ( paramName )
3974 const selectedClientPage = parseInt ( selectedClientPageString ?? '1' , 10 )
@@ -57,30 +92,43 @@ export function useClientSidePagination<Item, QueryResult extends List>({
5792 return { search : newSearchParams . toString ( ) }
5893 }
5994
60- const limit = serverPageSize
61- const offset = ( selectedServerPage - 1 ) * clientPageSize
95+ // From the server, we always want to load the first batch of data, with the provided (big) window.
96+ // In theory, we could move this window as required, but currently this is not implemented.
97+ const selectedServerPage = 1
98+
99+ // The query parameters that should be used for loading the data from the server
62100 const paramsForQuery = {
63- offset,
64- limit,
101+ offset : ( selectedServerPage - 1 ) * serverPageSize ,
102+ limit : serverPageSize ,
65103 }
66104
67105 return {
68- selectedPage : selectedClientPage ,
69- offsetForQuery : offset ,
70- limitForQuery : limit ,
71- paramsForQuery,
72- getResults : ( queryResult , key ) => {
73- const data = queryResult
74- ? key
75- ? ( queryResult [ key ] as Item [ ] )
76- : findListIn < QueryResult , Item > ( queryResult )
106+ selectedPageForClient : selectedClientPage ,
107+ paramsForServer : paramsForQuery ,
108+ getResults : (
109+ isLoading ,
110+ isFetched ,
111+ queryResult ,
112+ key ,
113+ ) : ComprehensivePaginatedResults < Item , ExtractedData > => {
114+ const data = queryResult // we want to get list of items out from the incoming results
115+ ? key // do we know where (in which field) to look?
116+ ? ( queryResult [ key ] as Item [ ] ) // If yes, just get out the data
117+ : findListIn < QueryResult , Item > ( queryResult ) // If no, we will try to guess
77118 : undefined
78- const filteredData = ! ! data && ! ! filter ? data . filter ( filter ) : data
79119
120+ // Apply the specified client-side transformation
121+ const [ transformedData , extractedData ] = ! ! data && ! ! transform ? transform ( data , queryResult ! ) : [ data ]
122+
123+ // Apply the specified filtering
124+ const filteredData = ! ! transformedData && ! ! filter ? transformedData . filter ( filter ) : transformedData
125+
126+ // The data window from the POV of the data consumer component
80127 const offset = ( selectedClientPage - 1 ) * clientPageSize
81128 const limit = clientPageSize
82129 const dataWindow = filteredData ? filteredData . slice ( offset , offset + limit ) : undefined
83130
131+ // The control interface for the data consumer component (i.e. Table)
84132 const tableProps : TablePaginationProps = {
85133 selectedPage : selectedClientPage ,
86134 linkToPage,
@@ -96,8 +144,10 @@ export function useClientSidePagination<Item, QueryResult extends List>({
96144 return {
97145 tablePaginationProps : tableProps ,
98146 data : dataWindow ,
147+ extractedData,
148+ isLoading,
149+ isFetched,
99150 }
100151 } ,
101- // tableProps,
102152 }
103153}
0 commit comments