Performance improvements (#1166)

#1166 * Update angular libs
document-list: performance improvements
caching ‘heavy’ cell evaluations (i.e. date pipe)
code/test fixes
document-list: performance improvements
Removed ‘AfterViewChecked’ bottleneck as underlying data-table already
does it.
data-table: performance improvements
This commit is contained in:
Denys Vuika
2016-11-28 21:36:00 +00:00
committed by Eugenio Romano
parent 0f563e38bb
commit 3ca2c28a41
9 changed files with 223 additions and 235 deletions

View File

@@ -1,4 +1,3 @@
<div *ngIf="!fileShowed">
<div class="container"> <div class="container">
<alfresco-upload-drag-area <alfresco-upload-drag-area
[currentFolderPath]="currentPath" [currentFolderPath]="currentPath"
@@ -184,7 +183,6 @@
</alfresco-upload-button> </alfresco-upload-button>
</div> </div>
<file-uploading-dialog #fileDialog></file-uploading-dialog> <file-uploading-dialog #fileDialog></file-uploading-dialog>
</div>
<div *ngIf="fileShowed"> <div *ngIf="fileShowed">
<alfresco-viewer [(showViewer)]="fileShowed" <alfresco-viewer [(showViewer)]="fileShowed"

View File

@@ -16,7 +16,9 @@
*/ */
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
// enableProdMode();
const platform = platformBrowserDynamic(); const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule); platform.bootstrapModule(AppModule);

View File

@@ -53,23 +53,21 @@
"alfresco" "alfresco"
], ],
"dependencies": { "dependencies": {
"@angular/common": "2.0.0", "@angular/common": "~2.2.0",
"@angular/compiler": "2.0.0", "@angular/compiler": "~2.2.0",
"@angular/core": "2.0.0", "@angular/core": "~2.2.0",
"@angular/forms": "2.0.0", "@angular/forms": "~2.2.0",
"@angular/http": "2.0.0", "@angular/http": "~2.2.0",
"@angular/platform-browser": "2.0.0", "@angular/platform-browser": "~2.2.0",
"@angular/platform-browser-dynamic": "2.0.0", "@angular/platform-browser-dynamic": "~2.2.0",
"@angular/router": "3.0.0", "@angular/router": "~3.2.0",
"@angular/upgrade": "2.0.0",
"@types/node": "^6.0.42", "systemjs": "0.19.40",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"reflect-metadata": "^0.1.3", "reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.12", "rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27", "zone.js": "^0.6.26",
"zone.js": "^0.6.23",
"rimraf": "2.5.2",
"material-design-icons": "2.2.3", "material-design-icons": "2.2.3",
"material-design-lite": "1.2.1", "material-design-lite": "1.2.1",
"ng2-translate": "2.5.0", "ng2-translate": "2.5.0",
@@ -100,9 +98,11 @@
"element.scrollintoviewifneeded-polyfill": "^1.0.1" "element.scrollintoviewifneeded-polyfill": "^1.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^6.0.42",
"@types/core-js": "^0.9.32", "@types/core-js": "^0.9.32",
"@types/jasmine": "^2.2.33", "@types/jasmine": "^2.2.33",
"concurrently": "^2.2.0", "concurrently": "^2.2.0",
"rimraf": "2.5.2",
"license-check": "1.1.5", "license-check": "1.1.5",
"mime": "^1.3.4", "mime": "^1.3.4",
"tslint": "3.15.1", "tslint": "3.15.1",

View File

@@ -172,13 +172,13 @@ describe('DataTable', () => {
let handler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered']); let handler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered']);
window['componentHandler'] = handler; window['componentHandler'] = handler;
dataTable.ngAfterViewChecked(); dataTable.ngOnInit();
expect(handler.upgradeAllRegistered).toHaveBeenCalled(); expect(handler.upgradeAllRegistered).toHaveBeenCalled();
}); });
it('should upgrade MDL components only when component handler present', () => { it('should upgrade MDL components only when component handler present', () => {
expect(window['componentHandler']).toBeNull(); expect(window['componentHandler']).toBeNull();
dataTable.ngAfterViewChecked(); dataTable.ngOnInit();
}); });
it('should invert "select all" status', () => { it('should invert "select all" status', () => {

View File

@@ -15,16 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { import { Component, OnInit, Input, Output, EventEmitter, TemplateRef } from '@angular/core';
Component,
OnInit,
Input,
Output,
EventEmitter,
AfterViewChecked,
TemplateRef
} from '@angular/core';
import { import {
DataTableAdapter, DataTableAdapter,
DataRow, DataRow,
@@ -42,7 +33,7 @@ declare var componentHandler;
styleUrls: ['./datatable.component.css'], styleUrls: ['./datatable.component.css'],
templateUrl: './datatable.component.html' templateUrl: './datatable.component.html'
}) })
export class DataTableComponent implements OnInit, AfterViewChecked { export class DataTableComponent implements OnInit {
@Input() @Input()
data: DataTableAdapter; data: DataTableAdapter;
@@ -79,9 +70,7 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
if (!this.data) { if (!this.data) {
this.data = new ObjectDataTableAdapter([], []); this.data = new ObjectDataTableAdapter([], []);
} }
}
ngAfterViewChecked() {
// workaround for MDL issues with dynamic components // workaround for MDL issues with dynamic components
if (componentHandler) { if (componentHandler) {
componentHandler.upgradeAllRegistered(); componentHandler.upgradeAllRegistered();

View File

@@ -272,11 +272,6 @@ describe('DocumentList', () => {
expect(documentList.executeContentAction).not.toHaveBeenCalled(); expect(documentList.executeContentAction).not.toHaveBeenCalled();
}); });
it('should upgrade material design components', () => {
documentList.ngAfterViewChecked();
expect(componentHandler.upgradeAllRegistered).toHaveBeenCalled();
});
it('should subscribe to context action handler', () => { it('should subscribe to context action handler', () => {
spyOn(documentList, 'displayFolderContent').and.stub(); spyOn(documentList, 'displayFolderContent').and.stub();
spyOn(documentList, 'contextActionCallback').and.stub(); spyOn(documentList, 'contextActionCallback').and.stub();

View File

@@ -22,7 +22,6 @@ import {
Output, Output,
EventEmitter, EventEmitter,
AfterContentInit, AfterContentInit,
AfterViewChecked,
TemplateRef, TemplateRef,
NgZone, NgZone,
ViewChild, ViewChild,
@@ -41,15 +40,13 @@ import {
ImageResolver ImageResolver
} from './../data/share-datatable-adapter'; } from './../data/share-datatable-adapter';
declare var componentHandler;
@Component({ @Component({
moduleId: module.id, moduleId: module.id,
selector: 'alfresco-document-list', selector: 'alfresco-document-list',
styleUrls: ['./document-list.css'], styleUrls: ['./document-list.css'],
templateUrl: './document-list.html' templateUrl: './document-list.html'
}) })
export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit { export class DocumentList implements OnInit, AfterContentInit {
static SINGLE_CLICK_NAVIGATION: string = 'click'; static SINGLE_CLICK_NAVIGATION: string = 'click';
static DOUBLE_CLICK_NAVIGATION: string = 'dblclick'; static DOUBLE_CLICK_NAVIGATION: string = 'dblclick';
@@ -196,16 +193,8 @@ export class DocumentList implements OnInit, AfterViewChecked, AfterContentInit
return false; return false;
} }
ngAfterViewChecked() {
// workaround for MDL issues with dynamic components
if (componentHandler) {
componentHandler.upgradeAllRegistered();
}
}
isMobile(): boolean { isMobile(): boolean {
return !!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); return !!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
} }
getNodeActions(node: MinimalNodeEntity): ContentActionModel[] { getNodeActions(node: MinimalNodeEntity): ContentActionModel[] {

View File

@@ -203,8 +203,8 @@ describe('ShareDataTableAdapter', () => {
spyOn(console, 'error').and.stub(); spyOn(console, 'error').and.stub();
let value = adapter.getValue(row, col); let value = adapter.getValue(row, col);
expect(value).toBe(dateValue); expect(value).toBe('Error');
expect(console.error).toHaveBeenCalledWith(`Error parsing date ${value} to format ${col.format}`); expect(console.error).toHaveBeenCalled();
}); });
it('should generate fallback icon for a file thumbnail with unknown mime type', () => { it('should generate fallback icon for a file thumbnail with unknown mime type', () => {

View File

@@ -121,15 +121,21 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
if (!col) { if (!col) {
throw new Error(this.ERR_COL_NOT_FOUND); throw new Error(this.ERR_COL_NOT_FOUND);
} }
let value = row.getValue(col.key); let dataRow: ShareDataRow = <ShareDataRow> row;
let value: any = row.getValue(col.key);
if (dataRow.cache[col.key] !== undefined) {
return dataRow.cache[col.key];
}
if (col.type === 'date') { if (col.type === 'date') {
let datePipe = new DatePipe('en-US'); let datePipe = new DatePipe('en-US');
let format = col.format || this.DEFAULT_DATE_FORMAT; let format = col.format || this.DEFAULT_DATE_FORMAT;
try { try {
return datePipe.transform(value, format); let result = datePipe.transform(value, format);
return dataRow.cacheValue(col.key, result);
} catch (err) { } catch (err) {
console.error(`Error parsing date ${value} to format ${format}`); console.error(`Error parsing date ${value} to format ${format}`);
return 'Error';
} }
} }
@@ -174,7 +180,7 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
} }
return value; return dataRow.cacheValue(col.key, value);
} }
getSorting(): DataSorting { getSorting(): DataSorting {
@@ -308,6 +314,7 @@ export class ShareDataRow implements DataRow {
static ERR_OBJECT_NOT_FOUND: string = 'Object source not found'; static ERR_OBJECT_NOT_FOUND: string = 'Object source not found';
cache: { [key: string]: any } = {};
isSelected: boolean = false; isSelected: boolean = false;
get node(): NodeMinimalEntry { get node(): NodeMinimalEntry {
@@ -320,7 +327,15 @@ export class ShareDataRow implements DataRow {
} }
} }
cacheValue(key: string, value: any): any {
this.cache[key] = value;
return value;
}
getValue(key: string): any { getValue(key: string): any {
if (this.cache[key] !== undefined) {
return this.cache[key];
}
return ObjectUtils.getValue(this.obj.entry, key); return ObjectUtils.getValue(this.obj.entry, key);
} }