@@ -28,6 +28,8 @@ const defaultQuotaOptions = {
2828 Unlimited : - 3 ,
2929}
3030
31+ const pageSize = 50
32+
3133export type SortKey = 'mount_point' | 'quota' | 'groups' | 'acl' ;
3234
3335export interface AppState {
@@ -45,6 +47,7 @@ export interface AppState {
4547 sortOrder : number ;
4648 isAdminNextcloud : boolean ;
4749 checkAppsInstalled : boolean ;
50+ currentPage : number ;
4851}
4952
5053export class App extends Component < unknown , AppState > implements OC . Plugin < OC . Search . Core > {
@@ -66,10 +69,12 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
6669 sortOrder : 1 ,
6770 isAdminNextcloud : false ,
6871 checkAppsInstalled : false ,
72+ currentPage : 0 ,
6973 }
7074
7175 componentDidMount ( ) {
72- this . api . listFolders ( ) . then ( ( folders ) => {
76+ // list first pageSize + 1 folders so we know if there are more pages
77+ this . api . listFolders ( 0 , pageSize + 1 ) . then ( ( folders ) => {
7378 this . setState ( { folders } )
7479 } )
7580 this . api . listGroups ( ) . then ( ( groups ) => {
@@ -169,6 +174,21 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
169174 this . api . setACL ( folder . id , acl )
170175 }
171176
177+ async goToPage ( page : number ) {
178+ const loadedPage = Math . floor ( this . state . folders . length / pageSize )
179+ if ( loadedPage <= page ) {
180+ const folders = await this . api . listFolders ( this . state . folders . length , ( page + 1 ) * pageSize - this . state . folders . length + 1 )
181+ this . setState ( {
182+ folders : [ ...this . state . folders , ...folders ] ,
183+ currentPage : page ,
184+ } )
185+ } else {
186+ this . setState ( {
187+ currentPage : page ,
188+ } )
189+ }
190+ }
191+
172192 onSortClick = ( sort : SortKey ) => {
173193 if ( this . state . sort === sort ) {
174194 this . setState ( { sortOrder : - this . state . sortOrder } )
@@ -213,7 +233,7 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
213233 if ( this . state . filter === '' ) {
214234 return true
215235 }
216- return folder . mount_point . toLowerCase ( ) . indexOf ( this . state . filter . toLowerCase ( ) ) !== - 1
236+ return folder . mount_point . toLowerCase ( ) . includes ( this . state . filter . toLowerCase ( ) )
217237 } )
218238 . sort ( ( a , b ) => {
219239 switch ( this . state . sort ) {
@@ -239,6 +259,7 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
239259 }
240260 return 0
241261 } )
262+ . slice ( this . state . currentPage * pageSize , this . state . currentPage * pageSize + pageSize )
242263 . map ( folder => {
243264 const id = folder . id
244265 return < tr key = { id } >
@@ -361,6 +382,60 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
361382 </ tr >
362383 </ FlipMove >
363384 </ table >
385+ < nav className = "groupfolders-pagination" aria-label = { t ( 'groupfolders' , 'Pagination of team folders' ) } >
386+ < ul className = "groupfolders-pagination__list" >
387+ < li >
388+ < button
389+ aria-label = { t ( 'groupfolders' , 'Previous' ) }
390+ className = "groupfolders-pagination__button"
391+ disabled = { this . state . currentPage === 0 }
392+ title = { t ( 'groupfolders' , 'Previous' ) }
393+ onClick = { ( ) => this . goToPage ( this . state . currentPage - 1 ) } > ⮜</ button >
394+ </ li >
395+ {
396+ // show the "1" button if we are not on the first page
397+ this . state . currentPage > 0 && < li > < button onClick = { ( ) => this . goToPage ( 0 ) } > 1</ button > </ li >
398+ }
399+ {
400+ // show the ellipsis button if there are more than 2 pages before the current
401+ this . state . currentPage > 2 && < li > < button disabled > …</ button > </ li > }
402+ {
403+ // show the page right before the current - if there is such a page
404+ this . state . currentPage > 1 && < li > < button onClick = { ( ) => this . goToPage ( this . state . currentPage - 1 ) } > { this . state . currentPage } </ button > </ li >
405+ }
406+ { /* the current page as a button */ }
407+ < li > < button aria-current = "page" aria-disabled className = "primary" > { this . state . currentPage + 1 } </ button > </ li >
408+ {
409+ // show the next page if it exists (we know at least that the next exists or not)
410+ ( this . state . currentPage + 1 ) < ( this . state . folders . length / pageSize )
411+ && < li >
412+ < button onClick = { ( ) => this . goToPage ( this . state . currentPage + 1 ) } > { this . state . currentPage + 2 } </ button >
413+ </ li >
414+ }
415+ {
416+ // If we know more than two next pages exist we show the ellipsis for the intermediate pages
417+ ( this . state . currentPage + 3 ) < ( this . state . folders . length / pageSize )
418+ && < li >
419+ < button disabled > …</ button >
420+ </ li >
421+ }
422+ {
423+ // If more than one next page exist we show the last page as a button
424+ ( this . state . currentPage + 2 ) < ( this . state . folders . length / pageSize )
425+ && < li >
426+ < button onClick = { ( ) => this . goToPage ( Math . floor ( this . state . folders . length / pageSize ) ) } > { Math . floor ( this . state . folders . length / pageSize ) + 1 } </ button >
427+ </ li >
428+ }
429+ < li >
430+ < button
431+ aria-label = { t ( 'groupfolders' , 'Next' ) }
432+ className = "groupfolders-pagination__button"
433+ disabled = { this . state . currentPage >= Math . floor ( this . state . folders . length / pageSize ) }
434+ title = { t ( 'groupfolders' , 'Next' ) }
435+ onClick = { ( ) => this . goToPage ( this . state . currentPage + 1 ) } > ⮞</ button >
436+ </ li >
437+ </ ul >
438+ </ nav >
364439 </ div >
365440 }
366441
0 commit comments