From f3d5b88671dcfda8616adb2e50030e5e171179cf Mon Sep 17 00:00:00 2001 From: Eugenio Romano Date: Wed, 14 Jun 2017 20:18:52 +0100 Subject: [PATCH] [ADF-524] Datatable loading state (#1958) * loading state datatable * modify readme after review --- .../ng2-alfresco-datatable/README.md | 57 ++++++++++-- .../ng2-alfresco-datatable/index.ts | 4 +- .../datatable/datatable.component.css | 13 ++- .../datatable/datatable.component.html | 43 +++++---- .../datatable/datatable.component.ts | 22 ++--- .../src/components/datatable/index.ts | 1 - .../src/directives/index.ts | 19 ++++ .../loading-template.component.spec.ts | 41 +++++++++ .../directives/loading-template.component.ts | 36 ++++++++ .../no-content-template.component.spec.ts | 4 +- .../no-content-template.component.ts | 12 +-- .../ng2-alfresco-documentlist/README.md | 1 + .../ng2-alfresco-documentlist/index.ts | 5 +- .../components/document-list.component.css | 4 + .../components/document-list.component.html | 34 +++++--- .../document-list.component.spec.ts | 54 ++++++++---- .../src/components/document-list.component.ts | 87 ++++++++----------- 17 files changed, 305 insertions(+), 132 deletions(-) create mode 100644 ng2-components/ng2-alfresco-datatable/src/directives/index.ts create mode 100644 ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.spec.ts create mode 100644 ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.ts rename ng2-components/ng2-alfresco-datatable/src/{components/datatable => directives}/no-content-template.component.spec.ts (88%) rename ng2-components/ng2-alfresco-datatable/src/{components/datatable => directives}/no-content-template.component.ts (81%) diff --git a/ng2-components/ng2-alfresco-datatable/README.md b/ng2-components/ng2-alfresco-datatable/README.md index 660c448a8e..ef312cecd0 100644 --- a/ng2-components/ng2-alfresco-datatable/README.md +++ b/ng2-components/ng2-alfresco-datatable/README.md @@ -123,6 +123,7 @@ export class DataTableDemo { | fallbackThumbnail | string | | Fallback image for row ehre thubnail is missing| | contextMenu | boolean | false | Toggles custom context menu for the component | | allowDropFiles | boolean | false | Toggle file drop support for rows (see **ng2-alfresco-core/UploadDirective** for more details) | +| loading | boolean | false | Flag that indicate if the datable is in loading state and need to show the loading template. Read the documentation above to know how to configure a loading template | ### DataColumn Properties @@ -176,7 +177,9 @@ onRowClick(event) { ![](docs/assets/datatable-dom-events.png) -### Advanced usage +### Empty content template + +You can add a template that will be showed when there are no result in your datatable: ```html - - - + + + + + +

Sorry, no content

+
+
+
``` +### Loading content template + +You can add a template that will be showed during the loading of your data: + +```html + + + + + + + + + + + +``` + +```js + isLoading(): boolean { + //your custom logic to identify if you are in a loading state + } +``` + +Note: the `` and `` can be used together + #### Column Templates It is possible assigning a custom column template like the following: diff --git a/ng2-components/ng2-alfresco-datatable/index.ts b/ng2-components/ng2-alfresco-datatable/index.ts index 9c599b0290..bba922f795 100644 --- a/ng2-components/ng2-alfresco-datatable/index.ts +++ b/ng2-components/ng2-alfresco-datatable/index.ts @@ -26,7 +26,8 @@ export * from './src/components/datatable/data-cell.event'; export * from './src/components/datatable/data-row-action.event'; import { DataTableComponent } from './src/components/datatable/datatable.component'; -import { NoContentTemplateComponent } from './src/components/datatable/no-content-template.component'; +import { NoContentTemplateComponent } from './src/directives/no-content-template.component'; +import { LoadingContentTemplateComponent } from './src/directives/loading-template.component'; import { PaginationComponent } from './src/components/pagination/pagination.component'; import { DataTableCellComponent } from './src/components/datatable/datatable-cell.component'; @@ -34,6 +35,7 @@ export const ALFRESCO_DATATABLE_DIRECTIVES: [any] = [ DataTableComponent, DataTableCellComponent, NoContentTemplateComponent, + LoadingContentTemplateComponent, PaginationComponent ]; diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.css b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.css index d7157b532c..5fe1ddaa6d 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.css +++ b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.css @@ -26,11 +26,20 @@ /* Empty folder */ -:host .no-content-container { +:host .adf-no-content-container { padding: 0 !important; } -:host .no-content-container > img { +:host .adf-no-content-container > img { + width: 100%; +} +/* Loading folder */ + +:host .adf-loading-content-container { + padding: 0 !important; +} + +:host .adf-loading-content-container > img { width: 100%; } diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.html b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.html index 710ee9d1ae..528445ea4e 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.html +++ b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.html @@ -38,7 +38,8 @@ -
    {{asIconValue(row, col)}} {{ iconAltTextKey(data.getValue(row, col)) | translate }} + class="image-cell" + alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}" + src="{{ data.getValue(row, col) }}" + (error)="onImageLoadingError($event)">
    {{ iconAltTextKey(data.getValue(row, col)) | translate }} + alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}" + src="{{ data.getValue(row, col) }}" + (error)="onImageLoadingError($event)">
    -
    +
    -
    +
    @@ -98,7 +101,8 @@ -
      - - + + ngFor [ngForOf]="[data]" + [ngForTemplate]="noContentTemplate"> + + + + + + diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.ts b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.ts index ab5ec1e4be..19b9de8911 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.ts +++ b/ng2-components/ng2-alfresco-datatable/src/components/datatable/datatable.component.ts @@ -15,20 +15,7 @@ * limitations under the License. */ -import { - Component, - OnChanges, - SimpleChange, - SimpleChanges, - Input, - Output, - EventEmitter, - ElementRef, - TemplateRef, - AfterContentInit, - ContentChild, - Optional -} from '@angular/core'; +import { Component, OnChanges, SimpleChange, SimpleChanges, Input, Output, EventEmitter, ElementRef, TemplateRef, AfterContentInit, ContentChild, Optional } from '@angular/core'; import { DataTableAdapter, DataRow, DataColumn, DataSorting, DataRowEvent, ObjectDataTableAdapter, ObjectDataRow } from '../../data/index'; import { DataCellEvent } from './data-cell.event'; import { DataRowActionEvent } from './data-row-action.event'; @@ -94,7 +81,12 @@ export class DataTableComponent implements AfterContentInit, OnChanges { @Output() executeRowAction: EventEmitter = new EventEmitter(); - noContentTemplate: TemplateRef; + @Input() + loading: boolean = false; + + public noContentTemplate: TemplateRef; + public loadingTemplate: TemplateRef; + isSelectAllChecked: boolean = false; constructor(@Optional() private el: ElementRef) { diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/index.ts b/ng2-components/ng2-alfresco-datatable/src/components/datatable/index.ts index 0e872f6241..4ff4ce73c5 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/index.ts +++ b/ng2-components/ng2-alfresco-datatable/src/components/datatable/index.ts @@ -16,5 +16,4 @@ */ export * from './datatable.component'; -export * from './no-content-template.component'; export * from './datatable-cell.component'; diff --git a/ng2-components/ng2-alfresco-datatable/src/directives/index.ts b/ng2-components/ng2-alfresco-datatable/src/directives/index.ts new file mode 100644 index 0000000000..d6cee74613 --- /dev/null +++ b/ng2-components/ng2-alfresco-datatable/src/directives/index.ts @@ -0,0 +1,19 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './no-content-template.component'; +export * from './loading-template.component'; diff --git a/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.spec.ts b/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.spec.ts new file mode 100644 index 0000000000..f2822157f5 --- /dev/null +++ b/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.spec.ts @@ -0,0 +1,41 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LoadingContentTemplateComponent } from './loading-template.component'; +import { Injector } from '@angular/core'; +import { getTestBed, TestBed } from '@angular/core/testing'; +import { DataTableComponent } from '../components/datatable/datatable.component'; + +describe('LoadingContentTemplateComponent', () => { + let injector: Injector; + let loadingContentTemplateComponent: LoadingContentTemplateComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + LoadingContentTemplateComponent, + DataTableComponent + ] + }); + injector = getTestBed(); + loadingContentTemplateComponent = injector.get(LoadingContentTemplateComponent); + }); + + it('is defined', () => { + expect(loadingContentTemplateComponent).toBeDefined(); + }); +}); diff --git a/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.ts b/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.ts new file mode 100644 index 0000000000..4d7286c025 --- /dev/null +++ b/ng2-components/ng2-alfresco-datatable/src/directives/loading-template.component.ts @@ -0,0 +1,36 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Directive, ContentChild, TemplateRef, AfterContentInit } from '@angular/core'; +import { DataTableComponent } from '../components/datatable/datatable.component'; + +@Directive({ + selector: 'loading-content-template' +}) +export class LoadingContentTemplateComponent implements AfterContentInit { + + @ContentChild(TemplateRef) + template: any; + + constructor(private dataTable: DataTableComponent) { + } + + ngAfterContentInit() { + this.dataTable.loadingTemplate = this.template; + } + +} diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.spec.ts b/ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.spec.ts similarity index 88% rename from ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.spec.ts rename to ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.spec.ts index 83fafdf962..48fe9519a5 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.spec.ts +++ b/ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.spec.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { NoContentTemplateComponent } from '../datatable/no-content-template.component'; +import { NoContentTemplateComponent } from './no-content-template.component'; import { Injector } from '@angular/core'; import { getTestBed, TestBed } from '@angular/core/testing'; -import { DataTableComponent } from './datatable.component'; +import { DataTableComponent } from '../components/datatable/datatable.component'; describe('NoContentTemplateComponent', () => { let injector: Injector; diff --git a/ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.ts b/ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.ts similarity index 81% rename from ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.ts rename to ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.ts index 081d31b733..5cbad292e5 100644 --- a/ng2-components/ng2-alfresco-datatable/src/components/datatable/no-content-template.component.ts +++ b/ng2-components/ng2-alfresco-datatable/src/directives/no-content-template.component.ts @@ -15,13 +15,8 @@ * limitations under the License. */ -import { - Directive, - ContentChild, - TemplateRef, - AfterContentInit -} from '@angular/core'; -import { DataTableComponent } from './datatable.component'; +import { Directive, ContentChild, TemplateRef, AfterContentInit } from '@angular/core'; +import { DataTableComponent } from '../components/datatable/datatable.component'; @Directive({ selector: 'no-content-template' @@ -31,8 +26,7 @@ export class NoContentTemplateComponent implements AfterContentInit { @ContentChild(TemplateRef) template: any; - constructor( - private dataTable: DataTableComponent) { + constructor(private dataTable: DataTableComponent) { } ngAfterContentInit() { diff --git a/ng2-components/ng2-alfresco-documentlist/README.md b/ng2-components/ng2-alfresco-documentlist/README.md index 36e5181061..979673048a 100644 --- a/ng2-components/ng2-alfresco-documentlist/README.md +++ b/ng2-components/ng2-alfresco-documentlist/README.md @@ -689,6 +689,7 @@ DocumentList emits the following events: | folderChange | emitted once current display folder has changed | | preview | emitted when user acts upon files with either single or double click (depends on `navigation-mode`), recommended for Viewer components integration | | permissionError | emitted when user is attempting to create a folder via action menu but it doesn't have the permission to do it | +| ready | emitted when the documentList is ready and load all the elements| ## Advanced usage and customization diff --git a/ng2-components/ng2-alfresco-documentlist/index.ts b/ng2-components/ng2-alfresco-documentlist/index.ts index 6067118c71..50b97d9a6c 100644 --- a/ng2-components/ng2-alfresco-documentlist/index.ts +++ b/ng2-components/ng2-alfresco-documentlist/index.ts @@ -16,7 +16,7 @@ */ import { NgModule, ModuleWithProviders } from '@angular/core'; -import { MdMenuModule, MdButtonModule, MdIconModule } from '@angular/material'; +import { MdMenuModule, MdButtonModule, MdIconModule, MdProgressSpinnerModule } from '@angular/material'; import { CoreModule } from 'ng2-alfresco-core'; import { DataTableModule } from 'ng2-alfresco-datatable'; @@ -79,7 +79,8 @@ export const DOCUMENT_LIST_PROVIDERS: any[] = [ DataTableModule, MdMenuModule, MdButtonModule, - MdIconModule + MdIconModule, + MdProgressSpinnerModule ], declarations: [ ...DOCUMENT_LIST_DIRECTIVES diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.css b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.css index 91b6e02eb4..eb6a18cf6e 100644 --- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.css +++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.css @@ -42,3 +42,7 @@ object-fit: contain; margin-top: 17px; } + +.adf-document-list-loading-margin { + margin: auto; +} diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html index 07fc6021c6..5f57b46f56 100644 --- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html +++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.html @@ -16,6 +16,7 @@ [contextMenu]="contextMenuActions" [rowStyle]="rowStyle" [rowStyleClass]="rowStyleClass" + [loading]="loading" (showRowContextMenu)="onShowRowContextMenu($event)" (showRowActionsMenu)="onShowRowActionsMenu($event)" (executeRowAction)="onExecuteRowAction($event)" @@ -24,20 +25,31 @@
      -
      -
      This folder is empty
      -
      Drag and Drop
      -
      any files here to add
      - -
      + + +
      +
      + + + + + + +
      + (changePageSize)="onChangePageSize($event)" + (nextPage)="onNextPage($event)" + (prevPage)="onPrevPage($event)" + [pagination]="pagination" + [supportedPageSizes]="[5, 10, 15, 20]"> diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.spec.ts index 2469fe6b25..9224ce51aa 100644 --- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.spec.ts +++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.spec.ts @@ -28,6 +28,7 @@ import { ShareDataRow, RowFilter, ImageResolver } from './../data/share-datatabl import { DataTableModule } from 'ng2-alfresco-datatable'; import { DocumentMenuActionComponent } from './document-menu-action.component'; import { Observable } from 'rxjs/Rx'; +import { MdProgressSpinnerModule } from '@angular/material'; declare let jasmine: any; @@ -43,7 +44,7 @@ let fakeNodeAnswerWithEntries = { 'entries': [{ 'entry': { 'isFile': true, - 'createdByUser': { 'id': 'admin', 'displayName': 'Administrator' }, + 'createdByUser': {'id': 'admin', 'displayName': 'Administrator'}, 'modifiedAt': '2017-05-24T15:08:55.640Z', 'nodeType': 'cm:content', 'content': { @@ -60,13 +61,13 @@ let fakeNodeAnswerWithEntries = { 'elements': [{ 'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c', 'name': 'Company Home' - }, { 'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home' }] + }, {'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home'}] }, 'isFolder': false, - 'modifiedByUser': { 'id': 'admin', 'displayName': 'Administrator' }, + 'modifiedByUser': {'id': 'admin', 'displayName': 'Administrator'}, 'name': 'b_txt_file.rtf', 'id': '67b80f77-dbca-4f58-be6c-71b9dd61ea53', - 'properties': { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' }, + 'properties': {'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR'}, 'allowableOperations': ['delete', 'update'] } }] @@ -100,7 +101,8 @@ describe('DocumentList', () => { TestBed.configureTestingModule({ imports: [ CoreModule.forRoot(), - DataTableModule.forRoot() + DataTableModule.forRoot(), + MdProgressSpinnerModule ], declarations: [ DocumentListComponent, @@ -108,7 +110,7 @@ describe('DocumentList', () => { ], providers: [ DocumentListService, - { provide: NgZone, useValue: zone } + {provide: NgZone, useValue: zone} ] }).compileComponents(); })); @@ -199,6 +201,19 @@ describe('DocumentList', () => { }); + it('should show the loading state during the loading of new elements', (done) => { + documentList.ngAfterContentInit(); + documentList.node = new NodePaging(); + + fixture.detectChanges(); + + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('#adf-document-list-loading')).toBeDefined(); + done(); + }); + }); + it('should not execute action without node provided', () => { let action = new ContentActionModel(); action.handler = function () { @@ -248,7 +263,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -269,7 +284,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -290,7 +305,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -310,7 +325,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -330,7 +345,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; + let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -350,7 +365,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; + let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete']}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -369,7 +384,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } }; + let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: null}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -388,7 +403,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } }; + let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: null}}; let actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); @@ -692,7 +707,7 @@ describe('DocumentList', () => { }); documentList.currentFolderId = 'wrong-id'; - documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, documentList.currentFolderId, true) }); + documentList.ngOnChanges({currentFolderId: new SimpleChange(null, documentList.currentFolderId, true)}); }); it('should require dataTable to check empty template', () => { @@ -784,11 +799,11 @@ 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) }); + documentList.ngOnChanges({folderNode: new SimpleChange(null, documentList.currentFolderId, true)}); expect(documentList.loadFolderNodesByFolderNodeId).toHaveBeenCalled(); }); - it('should load previous page if there are no other elements in multi page table', async(() => { + it('should load previous page if there are no other elements in multi page table', () => { documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692'; documentList.folderNode = new NodeMinimal(); documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692'; @@ -799,11 +814,12 @@ describe('DocumentList', () => { fixture.detectChanges(); - fixture.whenStable().then(() => { + documentList.ready.subscribe(() => { fixture.detectChanges(); let rowElement = element.querySelector('[data-automation-id="b_txt_file.rtf"]'); expect(rowElement).toBeDefined(); expect(rowElement).not.toBeNull(); + done(); }); jasmine.Ajax.requests.at(0).respondWith({ @@ -817,5 +833,5 @@ describe('DocumentList', () => { contentType: 'application/json', responseText: JSON.stringify(fakeNodeAnswerWithEntries) }); - })); + }); }); diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.ts index e35be1f686..0e658d787b 100644 --- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.ts +++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.component.ts @@ -146,6 +146,9 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni @Output() success: EventEmitter = new EventEmitter(); + @Output() + ready: EventEmitter = new EventEmitter(); + @Output() error: EventEmitter = new EventEmitter(); @@ -161,6 +164,8 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni contextActionHandler: Subject = new Subject(); data: ShareDataTableAdapter; + loading: boolean = false; + constructor(private documentListService: DocumentListService, private ngZone: NgZone, private translateService: AlfrescoTranslationService, @@ -223,19 +228,12 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni ngOnChanges(changes: SimpleChanges) { if (changes['folderNode'] && changes['folderNode'].currentValue) { this.loadFolder(); - return; - } - - if (changes['currentFolderId'] && changes['currentFolderId'].currentValue) { + } else if (changes['currentFolderId'] && changes['currentFolderId'].currentValue) { this.loadFolderByNodeId(changes['currentFolderId'].currentValue); - return; - } - - if (changes['node'] && changes['node'].currentValue) { + } else if (changes['node'] && changes['node'].currentValue) { if (this.data) { this.data.loadPage(changes['node'].currentValue); } - return; } } @@ -243,17 +241,11 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni this.ngZone.run(() => { if (this.folderNode) { this.loadFolder(); - return; - } - - if (this.currentFolderId) { + } else if (this.currentFolderId) { this.loadFolderByNodeId(this.currentFolderId); - return; - } - - if (this.node) { + } else if (this.node) { this.data.loadPage(this.node); - return; + this.ready.emit(); } }); } @@ -356,6 +348,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni } loadFolder() { + this.loading = true; let nodeId = this.folderNode ? this.folderNode.id : this.currentFolderId; if (nodeId) { this.loadFolderNodesByFolderNodeId(nodeId, this.pageSize, this.skipCount).catch(err => this.error.emit(err)); @@ -364,6 +357,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni // gets folder node and its content loadFolderByNodeId(nodeId: string) { + this.loading = true; this.documentListService.getFolderNode(nodeId).then(node => { this.folderNode = node; this.currentFolderId = node.id; @@ -375,42 +369,36 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni loadFolderNodesByFolderNodeId(id: string, maxItems: number, skipCount: number): Promise { return new Promise((resolve, reject) => { - if (id && this.documentListService) { - this.documentListService - .getFolder(null, { - maxItems: maxItems, - skipCount: skipCount, - rootFolderId: id - }) - .subscribe( - val => { - if (this.checkIfTheCurrentPageIsEmpty(val, skipCount)) { - this.updateSkipCount(skipCount - maxItems); - this.loadFolderNodesByFolderNodeId(id, maxItems, skipCount - maxItems); - } else { - this.data.loadPage(val); - this.pagination = val.list.pagination; + this.documentListService + .getFolder(null, { + maxItems: maxItems, + skipCount: skipCount, + 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 { - resolve(false); - } + }, () => { + reject(error); + }); + } else { + this.data.loadPage(val); + this.pagination = val.list.pagination; + this.loading = false; + this.ready.emit(); + resolve(true); + } + }, + error => { + reject(error); + }); }); } - private checkIfTheCurrentPageIsEmpty(node, skipCount): boolean { - let isCheckNeeded: boolean = false; - if (this.isCurrentPageEmpty(node, skipCount)) { - isCheckNeeded = true; - } - return isCheckNeeded; - } - private isCurrentPageEmpty(node, skipCount): boolean { return !this.hasNodeEntries(node) && this.hasPages(skipCount); } @@ -592,4 +580,5 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni updateSkipCount(newSkipCount) { this.skipCount = newSkipCount; } + }