diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 91dc4840df..ee6cfa0767 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -30,6 +30,7 @@ "MAX_SIZE" : "Max size filter", "ENABLE_VERSIONING" :"Enable versioning", "DESCRIPTION_UPLOAD" : "Enable upload", + "ENABLE_INFINITE_SCROLL":"Enable Infinite Scrolling", "MULTISELECT_DESCRIPTION" : "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items", "COLUMNS": { "DISPLAY_NAME": "Display name", diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index b66f65ede1..4ce1ad5e85 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -115,6 +115,9 @@ + + + + {{ 'ADF-DOCUMENT-LIST.LAYOUT.LOAD_MORE' | translate }} +
@@ -330,6 +351,12 @@ +
+ + {{'DOCUMENT_LIST.ENABLE_INFINITE_SCROLL' | translate}} + +
+
Upload
diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index a8722517ee..9022a9b5fd 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -21,11 +21,11 @@ import { } from '@angular/core'; import { MatDialog } from '@angular/material'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { MinimalNodeEntity, NodePaging } from 'alfresco-js-api'; +import { MinimalNodeEntity, NodePaging, Pagination } from 'alfresco-js-api'; import { AlfrescoApiService, ContentService, TranslationService, FileUploadEvent, FolderCreatedEvent, LogService, NotificationService, - SiteModel, UploadService, DataColumn, DataRow + SiteModel, UploadService, DataColumn, DataRow, UserPreferencesService } from '@alfresco/adf-core'; import { DocumentListComponent, PermissionStyleModel, DownloadZipDialogComponent } from '@alfresco/adf-content-services'; @@ -92,13 +92,35 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { @Input() nodeResult: NodePaging; + @Input() + pagination: Pagination; + @Output() documentListReady: EventEmitter = new EventEmitter(); + @Output() + changedPageSize: EventEmitter = new EventEmitter(); + + @Output() + changedPageNumber: EventEmitter = new EventEmitter(); + + @Output() + turnedNextPage: EventEmitter = new EventEmitter(); + + @Output() + turnedPreviousPage: EventEmitter = new EventEmitter(); + + @Output() + loadNext: EventEmitter = new EventEmitter(); + @ViewChild(DocumentListComponent) documentList: DocumentListComponent; permissionsStyle: PermissionStyleModel[] = []; + supportedPages: number[] = [5, 10, 15, 20]; + infiniteScrolling: boolean; + currentMaxItems: number; + currentSkipCount: number = 0; private onCreateFolder: Subscription; private onEditFolder: Subscription; @@ -112,7 +134,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { private translateService: TranslationService, private router: Router, @Optional() private route: ActivatedRoute, - private logService: LogService) { + private logService: LogService, + private preference: UserPreferencesService) { } showFile(event) { @@ -134,6 +157,13 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { } ngOnInit() { + if (!this.pagination) { + this.pagination = { + maxItems: this.preference.paginationSize, + skipCount: 0 + }; + this.currentMaxItems = this.preference.paginationSize; + } if (this.route) { this.route.params.forEach((params: Params) => { if (params['id']) { @@ -225,6 +255,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { emitReadyEvent(event: any) { this.documentListReady.emit(event); + this.pagination = event.list.pagination; } onContentActionError(errors) { @@ -376,4 +407,35 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { } return false; } + + onChangePageSize(event: Pagination): void { + this.preference.paginationSize = event.maxItems; + this.currentMaxItems = event.maxItems; + this.currentSkipCount = event.skipCount; + this.changedPageSize.emit(event); + } + + onChangePageNumber(event: Pagination): void { + this.currentMaxItems = event.maxItems; + this.currentSkipCount = event.skipCount; + this.changedPageNumber.emit(event); + } + + onNextPage(event: Pagination): void { + this.currentMaxItems = event.maxItems; + this.currentSkipCount = event.skipCount; + this.turnedNextPage.emit(event); + } + + loadNextBatch(event: Pagination) { + this.currentMaxItems = event.maxItems; + this.currentSkipCount = event.skipCount; + this.loadNext.emit(event); + } + + onPrevPage(event: Pagination): void { + this.currentMaxItems = event.maxItems; + this.currentSkipCount = event.skipCount; + this.turnedPreviousPage.emit(event); + } } diff --git a/demo-shell/src/app/components/search/search-result.component.html b/demo-shell/src/app/components/search/search-result.component.html index 2e7d372f20..a36874aa78 100644 --- a/demo-shell/src/app/components/search/search-result.component.html +++ b/demo-shell/src/app/components/search/search-result.component.html @@ -1,4 +1,6 @@ @@ -6,5 +8,10 @@ + (documentListReady)="refreshResults($event)" + (changedPageSize)="refreshPage($event)" + (changedPageNumber)="refreshPage($event)" + (turnedNextPage)="refreshPage($event)" + (loadNext)="refreshPage($event)" + (turnedPreviousPage)="refreshPage($event)"> diff --git a/demo-shell/src/app/components/search/search-result.component.ts b/demo-shell/src/app/components/search/search-result.component.ts index b8eb7ba836..83375a2c1b 100644 --- a/demo-shell/src/app/components/search/search-result.component.ts +++ b/demo-shell/src/app/components/search/search-result.component.ts @@ -17,8 +17,9 @@ import { Component, OnInit, Optional, ViewChild } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; -import { NodePaging } from 'alfresco-js-api'; +import { NodePaging, Pagination } from 'alfresco-js-api'; import { SearchComponent } from '@alfresco/adf-content-services'; +import { UserPreferencesService } from '@alfresco/adf-core'; @Component({ selector: 'adf-search-result-component', @@ -36,9 +37,14 @@ export class SearchResultComponent implements OnInit { fileShowed: boolean = false; navigationMode: string = 'dblclick'; resultNodePageList: NodePaging; + maxItems: number; + skipCount: number = 0; + paging: Pagination; constructor(public router: Router, + private preferences: UserPreferencesService, @Optional() private route: ActivatedRoute) { + this.maxItems = this.preferences.paginationSize; } ngOnInit() { @@ -51,9 +57,15 @@ export class SearchResultComponent implements OnInit { showSearchResult(event: NodePaging) { this.resultNodePageList = event; + this.paging = event.list.pagination; } refreshResults(event: any) { this.search.reload(); } + + refreshPage(event: Pagination) { + this.maxItems = event.maxItems; + this.skipCount = event.skipCount; + } } diff --git a/lib/content-services/content-node-selector/content-node-selector.component.html b/lib/content-services/content-node-selector/content-node-selector.component.html index 650ef20cd2..536dbe4598 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component.html +++ b/lib/content-services/content-node-selector/content-node-selector.component.html @@ -34,6 +34,7 @@ @@ -47,6 +48,9 @@ adf-highlight adf-highlight-selector=".cell-value adf-datatable-cell .adf-datatable-cell-value" [node]="nodes" + [maxItems]="pageSize" + [skipCount]="skipCount" + [enableInfiniteScrolling]="infiniteScroll" [rowFilter]="rowFilter" [imageResolver]="imageResolver" [currentFolderId]="folderIdToShow" @@ -54,11 +58,8 @@ [contextMenuActions]="false" [contentActions]="false" [allowDropFiles]="false" - [enablePagination]="!showingSearchResults" - paginationStrategy="{{paginationStrategy}}" - [pageSize]="pageSize" (folderChange)="onFolderChange()" - (ready)="onFolderLoaded()" + (ready)="onFolderLoaded($event)" data-automation-id="content-node-selector-document-list"> @@ -68,7 +69,6 @@ { DocumentListService, SearchService, ContentNodeSelectorService, + UserPreferencesService, ...plusProviders ], schemas: [CUSTOM_ELEMENTS_SCHEMA] @@ -164,19 +165,21 @@ describe('ContentNodeSelectorComponent', () => { describe('Cancel button', () => { let dummyMdDialogRef; + let fakePreference: UserPreferencesService = jasmine.createSpyObj('UserPreferencesService', ['paginationSize']); + fakePreference.paginationSize = 10; beforeEach(() => { dummyMdDialogRef = > { close: () => {} }; }); it('should be shown if dialogRef is injected', () => { - const componentInstance = new ContentNodeSelectorComponent(null, null, data, dummyMdDialogRef); + const componentInstance = new ContentNodeSelectorComponent(null, null, fakePreference, data, dummyMdDialogRef); expect(componentInstance.inDialog).toBeTruthy(); }); it('should should call the close method in the injected dialogRef', () => { spyOn(dummyMdDialogRef, 'close'); - const componentInstance = new ContentNodeSelectorComponent(null, null, data, dummyMdDialogRef); + const componentInstance = new ContentNodeSelectorComponent(null, null, fakePreference, data, dummyMdDialogRef); componentInstance.close(); @@ -339,7 +342,7 @@ describe('ContentNodeSelectorComponent', () => { skipCount, rootNodeId, nodeType: 'cm:folder', - maxItems: 10, + maxItems: 25, orderBy: null }; } @@ -524,7 +527,7 @@ describe('ContentNodeSelectorComponent', () => { it('should NOT be shown by default', () => { fixture.detectChanges(); - const pagination = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-pagination"]')); + const pagination = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); expect(pagination).toBeNull(); }); @@ -539,19 +542,6 @@ describe('ContentNodeSelectorComponent', () => { }); })); - it('should NOT be shown when modifying searchTerm to be less then 4 characters after search results have been diplayed', async(() => { - typeToSearchBox('shenron'); - respondWithSearchResults(ONE_FOLDER_RESULT); - - fixture.whenStable().then(() => { - typeToSearchBox('sh'); - fixture.detectChanges(); - - const pagination = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-pagination"]')); - expect(pagination).toBeNull(); - }); - })); - it('button\'s callback should load the next batch of results by calling the search api', () => { const skipCount = 8; component.searchTerm = 'kakarot'; diff --git a/lib/content-services/content-node-selector/content-node-selector.component.ts b/lib/content-services/content-node-selector/content-node-selector.component.ts index 3e7f9b9cff..51a38fae61 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component.ts +++ b/lib/content-services/content-node-selector/content-node-selector.component.ts @@ -16,7 +16,7 @@ */ import { Component, EventEmitter, Inject, Input, OnInit, Optional, Output, ViewChild, ViewEncapsulation } from '@angular/core'; -import { ContentService, HighlightDirective, SiteModel } from '@alfresco/adf-core'; +import { ContentService, HighlightDirective, SiteModel, UserPreferencesService } from '@alfresco/adf-core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; import { MinimalNodeEntryEntity, NodePaging, Pagination } from 'alfresco-js-api'; import { DocumentListComponent, PaginationStrategy } from '../document-list/components/document-list.component'; @@ -52,6 +52,7 @@ export class ContentNodeSelectorComponent implements OnInit { paginationStrategy: PaginationStrategy; pagination: Pagination; skipCount: number = 0; + infiniteScroll: boolean = false; @Input() title: string; @@ -66,7 +67,7 @@ export class ContentNodeSelectorComponent implements OnInit { imageResolver: ImageResolver = null; @Input() - pageSize: number = 10; + pageSize: number; @Output() select: EventEmitter = new EventEmitter(); @@ -79,6 +80,7 @@ export class ContentNodeSelectorComponent implements OnInit { constructor(private contentNodeSelectorService: ContentNodeSelectorService, private contentService: ContentService, + private preferences: UserPreferencesService, @Optional() @Inject(MAT_DIALOG_DATA) data?: ContentNodeSelectorComponentData, @Optional() private containingDialog?: MatDialogRef) { if (data) { @@ -92,6 +94,7 @@ export class ContentNodeSelectorComponent implements OnInit { if (this.containingDialog) { this.inDialog = true; } + this.pageSize = this.preferences.paginationSize; } ngOnInit() { @@ -180,6 +183,7 @@ export class ContentNodeSelectorComponent implements OnInit { * @param event Pagination object */ getNextPageOfSearch(event: Pagination): void { + this.infiniteScroll = true; this.skipCount = event.skipCount; this.querySearch(); } @@ -245,14 +249,17 @@ export class ContentNodeSelectorComponent implements OnInit { * Sets showingSearchResults state to be able to differentiate between search results or folder results */ onFolderChange(): void { + this.skipCount = 0; + this.infiniteScroll = false; this.showingSearchResults = false; } /** * Attempts to set the currently loaded node */ - onFolderLoaded(): void { + onFolderLoaded(nodePage: NodePaging): void { this.attemptNodeSelection(this.documentList.folderNode); + this.pagination = nodePage.list.pagination; } /** diff --git a/lib/content-services/document-list/components/document-list.component.html b/lib/content-services/document-list/components/document-list.component.html index 253e77e4c2..6160d8158a 100644 --- a/lib/content-services/document-list/components/document-list.component.html +++ b/lib/content-services/document-list/components/document-list.component.html @@ -61,25 +61,3 @@
- - - - - - - {{ 'ADF-DOCUMENT-LIST.LAYOUT.LOAD_MORE' | translate }} - - diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index f5e3c95dbe..8dd9794a74 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -17,8 +17,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgZone, SimpleChange, TemplateRef } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { Pagination } from 'alfresco-js-api'; -import { AlfrescoApiService, TranslationService, AppConfigService, UserPreferencesService } from '@alfresco/adf-core'; +import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core'; import { DataColumn, DataTableComponent } from '@alfresco/adf-core'; import { DataTableModule } from '@alfresco/adf-core'; import { Observable, Subject } from 'rxjs/Rx'; @@ -48,8 +47,6 @@ describe('DocumentList', () => { let fixture: ComponentFixture; let element: HTMLElement; let eventMock: any; - let appConfig: AppConfigService; - let userPreferences: UserPreferencesService; beforeEach(async(() => { let zone = new NgZone({ enableLongStackTrace: false }); @@ -87,8 +84,6 @@ describe('DocumentList', () => { documentList = fixture.componentInstance; documentListService = TestBed.get(DocumentListService); apiService = TestBed.get(AlfrescoApiService); - userPreferences = TestBed.get(UserPreferencesService); - appConfig = TestBed.get(AppConfigService); fixture.detectChanges(); }); @@ -128,8 +123,7 @@ describe('DocumentList', () => { it('should call action\'s handler with node', () => { let node = new FileNode(); let action = new ContentActionModel(); - action.handler = () => { - }; + action.handler = () => { }; spyOn(action, 'handler').and.stub(); @@ -141,8 +135,7 @@ describe('DocumentList', () => { it('should call action\'s handler with node and permission', () => { let node = new FileNode(); let action = new ContentActionModel(); - action.handler = () => { - }; + action.handler = () => { }; action.permission = 'fake-permission'; spyOn(action, 'handler').and.stub(); @@ -154,8 +147,7 @@ describe('DocumentList', () => { it('should call action\'s execute with node if it is defined', () => { let node = new FileNode(); let action = new ContentActionModel(); - action.execute = () => { - }; + action.execute = () => { }; spyOn(action, 'execute').and.stub(); documentList.executeContentAction(node, action); @@ -168,8 +160,7 @@ describe('DocumentList', () => { let node = new FileNode(); let action = new ContentActionModel(); action.handler = () => deleteObservable; - action.execute = () => { - }; + action.execute = () => { }; spyOn(action, 'execute').and.stub(); documentList.executeContentAction(node, action); @@ -203,12 +194,14 @@ describe('DocumentList', () => { it('should reset selection on loading folder by node id', () => { spyOn(documentList, 'resetSelection').and.callThrough(); + documentList.loadFolderByNodeId('-trashcan-'); expect(documentList.resetSelection).toHaveBeenCalled(); }); it('should reset selection in the datatable also', () => { spyOn(documentList.dataTable, 'resetSelection').and.callThrough(); + documentList.loadFolderByNodeId('-trashcan-'); expect(documentList.dataTable.resetSelection).toHaveBeenCalled(); }); @@ -217,6 +210,7 @@ describe('DocumentList', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; documentList.folderNode = new NodeMinimal(); documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692'; + documentList.reload(); fixture.detectChanges(); @@ -842,6 +836,7 @@ describe('DocumentList', () => { it('should load folder by ID on init', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; spyOn(documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve()); + documentList.ngOnChanges({ folderNode: new SimpleChange(null, documentList.currentFolderId, true) }); expect(documentList.loadFolderNodesByFolderNodeId).toHaveBeenCalled(); }); @@ -888,11 +883,8 @@ describe('DocumentList', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; documentList.folderNode = new NodeMinimal(); documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692'; - documentList.skipCount = 5; - documentList.pageSize = 5; - spyOn(documentList, 'isPaginationEnabled').and.returnValue(true); - documentList.reload(); + documentList.reload(); fixture.detectChanges(); documentList.ready.subscribe(() => { @@ -920,8 +912,6 @@ describe('DocumentList', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; documentList.folderNode = new NodeMinimal(); documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692'; - documentList.skipCount = 5; - documentList.pageSize = 5; spyOn(documentListService, 'getFolderNode').and.returnValue(Promise.resolve(fakeNodeWithCreatePermission)); spyOn(documentListService, 'getFolder').and.returnValue(Promise.resolve(fakeNodeAnswerWithNOEntries)); @@ -940,8 +930,7 @@ describe('DocumentList', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; documentList.folderNode = new NodeMinimal(); documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692'; - documentList.skipCount = 5; - documentList.pageSize = 5; + spyOn(documentListService, 'getFolderNode').and.returnValue(Promise.resolve(fakeNodeWithNoPermission)); spyOn(documentListService, 'getFolder').and.returnValue(Promise.resolve(fakeNodeAnswerWithNOEntries)); @@ -1106,59 +1095,11 @@ describe('DocumentList', () => { documentList.loadFolderByNodeId('-recent-'); }); - it('should switch to another page', () => { - spyOn(documentList, 'reload').and.stub(); - - const page1: Pagination = { - maxItems: 5, - skipCount: 0 - }; - const page2: Pagination = { - maxItems: 5, - skipCount: 10 - }; - - documentList.onChangePageNumber(page1); - expect(documentList.pageSize).toBe(page1.maxItems); - expect(documentList.skipCount).toBe(page1.skipCount); - - documentList.onChangePageNumber(page2); - expect(documentList.pageSize).toBe(page2.maxItems); - expect(documentList.skipCount).toBe(page2.skipCount); - - expect(documentList.reload).toHaveBeenCalledTimes(2); - }); - - it('should reset pagination when switching sources', () => { - spyOn(documentList, 'resetPagination').and.callThrough(); - - documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, '-trashcan-', false) }); - documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, '-sites-', false) }); - - expect(documentList.resetPagination).toHaveBeenCalledTimes(2); - }); - it('should reset folder node upon changing current folder id', () => { documentList.folderNode = {}; + documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, '-sites-', false) }); expect(documentList.folderNode).toBeNull(); }); - - it('should fallback to first page size supported', () => { - userPreferences.paginationSize = 10; - appConfig.config = Object.assign(appConfig.config, { - 'document-list': { - supportedPageSizes: [20, 30, 40] - } - }); - - let customFixture = TestBed.createComponent(DocumentListComponent); - let component: DocumentListComponent = customFixture.componentInstance; - - customFixture.detectChanges(); - - expect(component.supportedPageSizes).toEqual([20, 30, 40]); - expect(component.pageSize).toBe(20); - }); }); diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 13771f8082..0377e70133 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -33,7 +33,6 @@ import { MinimalNodeEntity, MinimalNodeEntryEntity, NodePaging, - Pagination, PersonEntry, SitePaging } from 'alfresco-js-api'; @@ -91,9 +90,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni @Input() multiselect: boolean = false; - @Input() - enablePagination: boolean = true; - @Input() contentActions: boolean = false; @@ -103,9 +99,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni @Input() contextMenuActions: boolean = false; - @Input() - pageSize: number = DocumentListComponent.DEFAULT_PAGE_SIZE; - @Input() emptyFolderImageUrl: string = require('../../assets/images/empty_doc_lib.svg'); @@ -124,19 +117,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni @Input() loading: boolean = false; - @Input() - paginationStrategy: PaginationStrategy = PaginationStrategy.Finite; - - @Input() - supportedPageSizes: number[]; - - infiniteLoading: boolean = false; - noPermission: boolean = false; - - selection = new Array(); - skipCount: number = 0; - pagination: Pagination; - @Input() rowFilter: RowFilter | null = null; @@ -153,6 +133,15 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni @Input() node: NodePaging = null; + @Input() + maxItems: number; + + @Input() + skipCount: number = 0; + + @Input() + enableInfiniteScrolling: boolean = false; + @Output() nodeClick: EventEmitter = new EventEmitter(); @@ -180,11 +169,13 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni noPermissionTemplate: TemplateRef; contextActionHandler: Subject = new Subject(); data: ShareDataTableAdapter; + infiniteLoading: boolean = false; + noPermission: boolean = false; + selection = new Array(); private layoutPresets = {}; private currentNodeAllowableOperations: string[] = []; private CREATE_PERMISSION = 'create'; - private defaultPageSizes = [5, 10, 15, 20]; constructor(private documentListService: DocumentListService, private ngZone: NgZone, @@ -192,7 +183,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private apiService: AlfrescoApiService, private appConfig: AppConfigService, private preferences: UserPreferencesService) { - this.supportedPageSizes = appConfig.get('document-list.supportedPageSizes', this.defaultPageSizes); + this.maxItems = this.preferences.paginationSize; } getContextActions(node: MinimalNodeEntity) { @@ -221,19 +212,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni return this.columnList && this.columnList.columns && this.columnList.columns.length > 0; } - getDefaultPageSize(): number { - let result = this.preferences.paginationSize; - - const pageSizes = this.supportedPageSizes || this.defaultPageSizes; - if (pageSizes && pageSizes.length > 0 && pageSizes.indexOf(result) < 0) { - result = pageSizes[0]; - } - - return result; - } - ngOnInit() { - this.pageSize = this.getDefaultPageSize(); this.loadLayoutPresets(); this.data = new ShareDataTableAdapter(this.documentListService, null, this.getDefaultSorting()); this.data.thumbnails = this.thumbnails; @@ -272,11 +251,14 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni } ngOnChanges(changes: SimpleChanges) { + if (this.isSkipCountChanged(changes) || + this.isMaxItemsChanged(changes)) { + this.reload(this.enableInfiniteScrolling); + } if (changes.folderNode && changes.folderNode.currentValue) { this.loadFolder(); } else if (changes.currentFolderId && changes.currentFolderId.currentValue) { if (changes.currentFolderId.previousValue !== changes.currentFolderId.currentValue) { - this.resetPagination(); this.folderNode = null; } if (!this.hasCustomLayout) { @@ -290,7 +272,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni } else if (changes.rowFilter) { this.data.setFilter(changes.rowFilter.currentValue); if (this.currentFolderId) { - this.loadFolderNodesByFolderNodeId(this.currentFolderId, this.pageSize, this.skipCount); + this.loadFolderNodesByFolderNodeId(this.currentFolderId, this.maxItems, this.skipCount); } } else if (changes.imageResolver) { this.data.setImageResolver(changes.imageResolver.currentValue); @@ -308,7 +290,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni this.loadFolderByNodeId(this.currentFolderId); } else if (this.node) { this.data.loadPage(this.node); - this.ready.emit(); + this.ready.emit(this.node); } }); } @@ -339,14 +321,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni return !this.data || this.data.getRows().length === 0; } - isPaginationEnabled() { - return this.enablePagination && !this.isEmpty(); - } - - isPaginationNeeded() { - return this.paginationStrategy === PaginationStrategy.Finite; - } - getNodeActions(node: MinimalNodeEntity | any): ContentActionModel[] { let target = null; @@ -445,7 +419,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni let nodeId = this.folderNode ? this.folderNode.id : this.currentFolderId; if (nodeId) { - this.loadFolderNodesByFolderNodeId(nodeId, this.pageSize, this.skipCount, merge).catch(err => this.error.emit(err)); + this.loadFolderNodesByFolderNodeId(nodeId, this.maxItems, this.skipCount, merge).catch(err => this.error.emit(err)); } } @@ -474,7 +448,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni this.currentFolderId = node.id; this.skipCount = 0; this.currentNodeAllowableOperations = node['allowableOperations'] ? node['allowableOperations'] : []; - return this.loadFolderNodesByFolderNodeId(node.id, this.pageSize, this.skipCount); + return this.loadFolderNodesByFolderNodeId(node.id, this.maxItems, this.skipCount); }) .catch(err => { if (JSON.parse(err.message).error.statusCode === 403) { @@ -496,25 +470,16 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni rootFolderId: id }) .subscribe( - val => { - if (this.isCurrentPageEmpty(val, skipCount)) { - this.updateSkipCount(skipCount - maxItems); - this.loadFolderNodesByFolderNodeId(id, maxItems, skipCount - maxItems).then( - () => resolve(true), - error => reject(error) - ); - } else { - this.data.loadPage( val, merge); - this.pagination = val.list.pagination; - this.loading = false; - this.infiniteLoading = false; - this.ready.emit(); - resolve(true); - } - }, - error => { - reject(error); - }); + val => { + this.data.loadPage( val, merge); + this.loading = false; + this.infiniteLoading = false; + this.ready.emit(val); + resolve(true); + }, + error => { + reject(error); + }); }); } @@ -524,14 +489,23 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni this.selection = []; } - resetPagination() { - this.skipCount = 0; + private isSkipCountChanged(changePage: SimpleChanges) { + return changePage.skipCount && + changePage.skipCount.currentValue !== null && + changePage.skipCount.currentValue !== undefined && + changePage.skipCount.currentValue !== changePage.skipCount.previousValue; + } + + private isMaxItemsChanged(changePage: SimpleChanges) { + return changePage.maxItems && + changePage.maxItems.currentValue && + changePage.maxItems.currentValue !== changePage.maxItems.previousValue; } private loadTrashcan(): void { const options = { include: ['path', 'properties'], - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount }; this.apiService.nodesApi.getDeletedNodes(options) @@ -542,7 +516,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private loadSharedLinks(): void { const options = { include: ['properties', 'allowableOperations', 'path'], - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount }; this.apiService.sharedLinksApi.findSharedLinks(options) @@ -553,7 +527,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private loadSites(): void { const options = { include: ['properties'], - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount }; @@ -565,7 +539,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private loadMemberSites(): void { const options = { include: ['properties'], - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount }; @@ -588,7 +562,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private loadFavorites(): void { const options = { - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount, where: '(EXISTS(target/file) OR EXISTS(target/folder))', include: ['properties', 'allowableOperations', 'path'] @@ -638,7 +612,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni ascending: false }], paging: { - maxItems: this.pageSize, + maxItems: this.maxItems, skipCount: this.skipCount } }; @@ -652,24 +626,11 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni private onPageLoaded(page: NodePaging) { if (page) { this.data.loadPage(page); - this.pagination = page.list.pagination; this.loading = false; - this.ready.emit(); + this.ready.emit(page); } } - private isCurrentPageEmpty(node, skipCount): boolean { - return !this.hasNodeEntries(node) && this.hasPages(skipCount); - } - - private hasPages(skipCount): boolean { - return skipCount > 0 && this.isPaginationEnabled(); - } - - private hasNodeEntries(node): boolean { - return node && node.list && node.list.entries && node.list.entries.length > 0; - } - /** * Creates a set of predefined columns. */ @@ -795,34 +756,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni } } - onChangePageSize(event: Pagination): void { - this.preferences.paginationSize = event.maxItems; - this.pageSize = event.maxItems; - this.skipCount = 0; - this.reload(); - } - - onChangePageNumber(page: Pagination): void { - this.pageSize = page.maxItems; - this.skipCount = page.skipCount; - this.reload(); - } - - onNextPage(event: Pagination): void { - this.skipCount = event.skipCount; - this.reload(); - } - - loadNextBatch(event: Pagination) { - this.skipCount = event.skipCount; - this.reload(true); - } - - onPrevPage(event: Pagination): void { - this.skipCount = event.skipCount; - this.reload(); - } - private enforceSingleClickNavigationForMobile(): void { if (this.isMobile()) { this.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; @@ -860,10 +793,6 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni return false; } - updateSkipCount(newSkipCount) { - this.skipCount = newSkipCount; - } - hasCurrentNodePermission(permission: string): boolean { let hasPermission: boolean = false; if (this.currentNodeAllowableOperations.length > 0) { diff --git a/lib/core/pagination/pagination.component.ts b/lib/core/pagination/pagination.component.ts index 8e10bc91fa..8989742fb6 100644 --- a/lib/core/pagination/pagination.component.ts +++ b/lib/core/pagination/pagination.component.ts @@ -56,11 +56,6 @@ export class PaginationComponent implements OnInit { @Input() supportedPageSizes: number[] = [ 25, 50, 100 ]; - /** @deprecated */ - /** "pagination" object already has "maxItems" */ - @Input() - maxItems: number = PaginationComponent.DEFAULT_PAGE_SIZE; - @Input() pagination: Pagination;