@@ -29,6 +29,8 @@ const defaultQuotaOptions = {
2929 Unlimited : - 3 ,
3030}
3131
32+ const pageSize = 50
33+
3234export type SortKey = 'mount_point' | 'quota' | 'groups' | 'acl' ;
3335
3436export interface AppState {
@@ -46,6 +48,7 @@ export interface AppState {
4648 sortOrder : number ;
4749 isAdminNextcloud : boolean ;
4850 checkAppsInstalled : boolean ;
51+ currentPage : number ;
4952}
5053
5154export class App extends Component < unknown , AppState > implements OC . Plugin < OC . Search . Core > {
@@ -67,10 +70,12 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
6770 sortOrder : 1 ,
6871 isAdminNextcloud : false ,
6972 checkAppsInstalled : false ,
73+ currentPage : 0 ,
7074 }
7175
7276 componentDidMount ( ) {
73- this . api . listFolders ( ) . then ( ( folders ) => {
77+ // list first pageSize + 1 folders so we know if there are more pages
78+ this . api . listFolders ( 0 , pageSize + 1 ) . then ( ( folders ) => {
7479 this . setState ( { folders } )
7580 } )
7681 this . api . listGroups ( ) . then ( ( groups ) => {
@@ -170,6 +175,21 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
170175 this . api . setACL ( folder . id , acl )
171176 }
172177
178+ async goToPage ( page : number ) {
179+ const loadedPage = Math . floor ( this . state . folders . length / pageSize )
180+ if ( loadedPage <= page ) {
181+ const folders = await this . api . listFolders ( this . state . folders . length , ( page + 1 ) * pageSize - this . state . folders . length + 1 )
182+ this . setState ( {
183+ folders : [ ...this . state . folders , ...folders ] ,
184+ currentPage : page ,
185+ } )
186+ } else {
187+ this . setState ( {
188+ currentPage : page ,
189+ } )
190+ }
191+ }
192+
173193 onSortClick = ( sort : SortKey ) => {
174194 if ( this . state . sort === sort ) {
175195 this . setState ( { sortOrder : - this . state . sortOrder } )
@@ -233,11 +253,12 @@ export class App extends Component<unknown, AppState> implements OC.Plugin<OC.Se
233253 if ( this . state . filter === '' ) {
234254 return true
235255 }
236- return folder . mount_point . toLowerCase ( ) . indexOf ( this . state . filter . toLowerCase ( ) ) !== - 1
256+ return folder . mount_point . toLowerCase ( ) . includes ( this . state . filter . toLowerCase ( ) )
237257 } ) ,
238258 identifiers ,
239259 direction ,
240260 )
261+ . slice ( this . state . currentPage * pageSize , this . state . currentPage * pageSize + pageSize )
241262 . map ( folder => {
242263 const id = folder . id
243264 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