mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
- expose ‘error’ event - change path only on successful navigation - extend demo shell with error handling and reporting - additional unit tests for document-list
This commit is contained in:
committed by
Eugenio Romano
parent
da70a72bba
commit
7eab89c5ef
@@ -7,3 +7,11 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message--text {
|
||||||
|
color: #d50000;
|
||||||
|
}
|
||||||
|
@@ -7,11 +7,18 @@
|
|||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[target]="documentList">
|
[target]="documentList">
|
||||||
</alfresco-document-list-breadcrumb>
|
</alfresco-document-list-breadcrumb>
|
||||||
|
<div *ngIf="errorMessage" class="error-message">
|
||||||
|
<button (click)="resetError()" class="mdl-button mdl-js-button mdl-button--icon">
|
||||||
|
<i class="material-icons">highlight_off</i>
|
||||||
|
</button>
|
||||||
|
<span class="error-message--text">{{errorMessage}}</span>
|
||||||
|
</div>
|
||||||
<alfresco-document-list
|
<alfresco-document-list
|
||||||
#documentList
|
#documentList
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[contextMenuActions]="true"
|
[contextMenuActions]="true"
|
||||||
[contentActions]="true"
|
[contentActions]="true"
|
||||||
|
(error)="onNavigationError($event)"
|
||||||
(preview)="showFile($event)"
|
(preview)="showFile($event)"
|
||||||
(folderChange)="onFolderChanged($event)">
|
(folderChange)="onFolderChanged($event)">
|
||||||
<!--
|
<!--
|
||||||
@@ -117,6 +124,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<button (click)="documentList.currentFolderPath = '/'">Go to root</button>
|
<button (click)="documentList.currentFolderPath = '/'">Go to root</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<button (click)="documentList.currentFolderPath = '!@£$%^&*()'">Go to the wrong path</button>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button (click)="fileDialog.toggleShowDialog()">Show/Hide File Dialog</button>
|
<button (click)="fileDialog.toggleShowDialog()">Show/Hide File Dialog</button>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -38,6 +38,7 @@ declare let __moduleName: string;
|
|||||||
export class FilesComponent implements OnInit {
|
export class FilesComponent implements OnInit {
|
||||||
currentPath: string = '/Sites/swsdp/documentLibrary';
|
currentPath: string = '/Sites/swsdp/documentLibrary';
|
||||||
|
|
||||||
|
errorMessage: string = null;
|
||||||
fileNodeId: any;
|
fileNodeId: any;
|
||||||
fileShowed: boolean = false;
|
fileShowed: boolean = false;
|
||||||
multipleFileUpload: boolean = false;
|
multipleFileUpload: boolean = false;
|
||||||
@@ -120,6 +121,16 @@ export class FilesComponent implements OnInit {
|
|||||||
this.router.navigate(['/activiti/tasksnode', event.value.entry.id]);
|
this.router.navigate(['/activiti/tasksnode', event.value.entry.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onNavigationError(err: any) {
|
||||||
|
if (err) {
|
||||||
|
this.errorMessage = err.message || 'Navigation error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetError() {
|
||||||
|
this.errorMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
private setupBpmActions(actions: any[]) {
|
private setupBpmActions(actions: any[]) {
|
||||||
actions.map(def => {
|
actions.map(def => {
|
||||||
let documentAction = new DocumentActionModel();
|
let documentAction = new DocumentActionModel();
|
||||||
|
@@ -85,15 +85,18 @@ describe('DocumentListBreadcrumb', () => {
|
|||||||
component.onRoutePathClick(node, null);
|
component.onRoutePathClick(node, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update document list on click', () => {
|
it('should update document list on click', (done) => {
|
||||||
let documentList = new DocumentList(null, null, null);
|
let documentList = new DocumentList(null, null, null);
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
|
||||||
|
|
||||||
let node = <PathNode> { name: 'name', path: '/path' };
|
let node = <PathNode> { name: 'name', path: '/path' };
|
||||||
component.target = documentList;
|
component.target = documentList;
|
||||||
|
|
||||||
component.onRoutePathClick(node, null);
|
component.onRoutePathClick(node, null);
|
||||||
|
setTimeout(() => {
|
||||||
expect(documentList.currentFolderPath).toBe(node.path);
|
expect(documentList.currentFolderPath).toBe(node.path);
|
||||||
|
done();
|
||||||
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing for same path', () => {
|
it('should do nothing for same path', () => {
|
||||||
|
@@ -15,13 +15,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NgZone } from '@angular/core';
|
import { NgZone, TemplateRef } from '@angular/core';
|
||||||
import { DataColumn } from 'ng2-alfresco-datatable';
|
import { DataTableComponent, DataColumn, DataRowEvent } from 'ng2-alfresco-datatable';
|
||||||
import { DocumentList } from './document-list';
|
import { DocumentList } from './document-list';
|
||||||
import { DocumentListServiceMock } from './../assets/document-list.service.mock';
|
import { DocumentListServiceMock } from './../assets/document-list.service.mock';
|
||||||
import { ContentActionModel } from '../models/content-action.model';
|
import { ContentActionModel } from '../models/content-action.model';
|
||||||
import { FileNode, FolderNode } from '../assets/document-library.model.mock';
|
import { FileNode, FolderNode } from '../assets/document-library.model.mock';
|
||||||
import { NodeMinimalEntry } from '../models/document-library.model';
|
import { NodeMinimalEntry } from '../models/document-library.model';
|
||||||
|
import { ShareDataRow, RowFilter, ImageResolver } from './../data/share-datatable-adapter';
|
||||||
|
|
||||||
describe('DocumentList', () => {
|
describe('DocumentList', () => {
|
||||||
|
|
||||||
@@ -204,23 +205,14 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should display folder content for new folder path', () => {
|
it('should display folder content for new folder path', () => {
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
|
||||||
let newPath = '/some/new/path';
|
let newPath = '/some/new/path';
|
||||||
documentList.currentFolderPath = newPath;
|
documentList.currentFolderPath = newPath;
|
||||||
expect(documentList.displayFolderContent).toHaveBeenCalledWith(newPath);
|
expect(documentList.displayFolderContent).toHaveBeenCalledWith(newPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not display folder content for same path', () => {
|
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
|
||||||
documentList.currentFolderPath = '/test';
|
|
||||||
expect(documentList.displayFolderContent).toHaveBeenCalledTimes(1);
|
|
||||||
|
|
||||||
documentList.currentFolderPath = '/test';
|
|
||||||
expect(documentList.displayFolderContent).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset to default path', () => {
|
it('should reset to default path', () => {
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
|
||||||
documentList.currentFolderPath = null;
|
documentList.currentFolderPath = null;
|
||||||
|
|
||||||
expect(documentList.currentFolderPath).toBe(documentList.DEFAULT_ROOT_FOLDER);
|
expect(documentList.currentFolderPath).toBe(documentList.DEFAULT_ROOT_FOLDER);
|
||||||
@@ -228,7 +220,7 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit folder changed event', (done) => {
|
it('should emit folder changed event', (done) => {
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
|
||||||
documentList.folderChange.subscribe(e => {
|
documentList.folderChange.subscribe(e => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -237,7 +229,7 @@ describe('DocumentList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should emit folder changed event with folder details', (done) => {
|
it('should emit folder changed event with folder details', (done) => {
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
|
||||||
|
|
||||||
let path = '/path';
|
let path = '/path';
|
||||||
|
|
||||||
@@ -249,20 +241,6 @@ describe('DocumentList', () => {
|
|||||||
documentList.currentFolderPath = path;
|
documentList.currentFolderPath = path;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit folder changed event only once', () => {
|
|
||||||
spyOn(documentList, 'displayFolderContent').and.stub();
|
|
||||||
let path = '/new/path';
|
|
||||||
let calls = 0;
|
|
||||||
documentList.folderChange.subscribe(e => {
|
|
||||||
calls++;
|
|
||||||
});
|
|
||||||
|
|
||||||
documentList.currentFolderPath = path;
|
|
||||||
documentList.currentFolderPath = path;
|
|
||||||
documentList.currentFolderPath = path;
|
|
||||||
expect(calls).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should execute context action on callback', () => {
|
it('should execute context action on callback', () => {
|
||||||
let action = {
|
let action = {
|
||||||
node: {},
|
node: {},
|
||||||
@@ -500,4 +478,87 @@ describe('DocumentList', () => {
|
|||||||
expect(documentList.isMobile).toHaveBeenCalled();
|
expect(documentList.isMobile).toHaveBeenCalled();
|
||||||
expect(documentList.navigationMode).toBe(DocumentList.SINGLE_CLICK_NAVIGATION);
|
expect(documentList.navigationMode).toBe(DocumentList.SINGLE_CLICK_NAVIGATION);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit error on wrong path', (done) => {
|
||||||
|
let raised = false;
|
||||||
|
documentList.error.subscribe(err => raised = true);
|
||||||
|
spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.reject(false));
|
||||||
|
|
||||||
|
documentList.currentFolderPath = 'wrong-path';
|
||||||
|
setTimeout(() => {
|
||||||
|
expect(raised).toBeTruthy();
|
||||||
|
done();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should require dataTable to check empty template', () => {
|
||||||
|
documentList.dataTable = null;
|
||||||
|
expect(documentList.isEmptyTemplateDefined()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check [empty folder] template ', () => {
|
||||||
|
documentList.emptyFolderTemplate = <TemplateRef<any>> {};
|
||||||
|
documentList.dataTable = new DataTableComponent();
|
||||||
|
expect(documentList.dataTable).toBeDefined();
|
||||||
|
expect(documentList.isEmptyTemplateDefined()).toBeTruthy();
|
||||||
|
|
||||||
|
documentList.emptyFolderTemplate = null;
|
||||||
|
expect(documentList.isEmptyTemplateDefined()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set root path for underlying adapter', () => {
|
||||||
|
documentList.rootPath = 'test';
|
||||||
|
expect(documentList.data.rootPath).toBe('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set default root path for underlying adapter', () => {
|
||||||
|
documentList.rootPath = null;
|
||||||
|
expect(documentList.data.rootPath).toBe(documentList.data.DEFAULT_ROOT_PATH);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch root path from underlying adapter', () => {
|
||||||
|
documentList.data.rootPath = 'test';
|
||||||
|
expect(documentList.rootPath).toBe('test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fetch root path when adapter missing', () => {
|
||||||
|
documentList.data = null;
|
||||||
|
expect(documentList.rootPath).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set row filter for underlying adapter', () => {
|
||||||
|
let filter = <RowFilter> {};
|
||||||
|
spyOn(documentList.data, 'setFilter').and.callThrough();
|
||||||
|
|
||||||
|
documentList.rowFilter = filter;
|
||||||
|
expect(documentList.data.setFilter).toHaveBeenCalledWith(filter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set image resolver for underlying adapter', () => {
|
||||||
|
let resolver = <ImageResolver> {};
|
||||||
|
spyOn(documentList.data, 'setImageResolver').and.callThrough();
|
||||||
|
|
||||||
|
documentList.imageResolver = resolver;
|
||||||
|
expect(documentList.data.setImageResolver).toHaveBeenCalledWith(resolver);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit [nodeClick] event on row click', () => {
|
||||||
|
let node = new NodeMinimalEntry();
|
||||||
|
let row = new ShareDataRow(node);
|
||||||
|
let event = <DataRowEvent> { value: row };
|
||||||
|
|
||||||
|
spyOn(documentList, 'onNodeClick').and.callThrough();
|
||||||
|
documentList.onRowClick(event);
|
||||||
|
expect(documentList.onNodeClick).toHaveBeenCalledWith(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit [nodeDblClick] event on row double-click', () => {
|
||||||
|
let node = new NodeMinimalEntry();
|
||||||
|
let row = new ShareDataRow(node);
|
||||||
|
let event = <DataRowEvent> { value: row };
|
||||||
|
|
||||||
|
spyOn(documentList, 'onNodeDblClick').and.callThrough();
|
||||||
|
documentList.onRowDblClick(event);
|
||||||
|
expect(documentList.onNodeDblClick).toHaveBeenCalledWith(node);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -118,6 +118,9 @@ export class DocumentList implements OnInit, AfterContentInit {
|
|||||||
@Output()
|
@Output()
|
||||||
preview: EventEmitter<any> = new EventEmitter();
|
preview: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
error: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
@ViewChild(DataTableComponent)
|
@ViewChild(DataTableComponent)
|
||||||
dataTable: DataTableComponent;
|
dataTable: DataTableComponent;
|
||||||
|
|
||||||
@@ -130,10 +133,14 @@ export class DocumentList implements OnInit, AfterContentInit {
|
|||||||
@Input()
|
@Input()
|
||||||
set currentFolderPath(value: string) {
|
set currentFolderPath(value: string) {
|
||||||
if (value !== this._path) {
|
if (value !== this._path) {
|
||||||
this._path = value || this.DEFAULT_ROOT_FOLDER;
|
const path = value || this.DEFAULT_ROOT_FOLDER;
|
||||||
this.displayFolderContent(this._path);
|
this.displayFolderContent(path)
|
||||||
this.folderChange.emit({
|
.then(() => {
|
||||||
path: this.currentFolderPath
|
this._path = path;
|
||||||
|
this.folderChange.emit({ path: path });
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.error.emit(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,14 +267,17 @@ export class DocumentList implements OnInit, AfterContentInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
displayFolderContent(path: string) {
|
displayFolderContent(path: string): Promise<any> {
|
||||||
this.data.loadPath(path);
|
return this.data.loadPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
this.ngZone.run(() => {
|
this.ngZone.run(() => {
|
||||||
if (this.currentFolderPath) {
|
if (this.currentFolderPath) {
|
||||||
this.displayFolderContent(this.currentFolderPath);
|
this.displayFolderContent(this.currentFolderPath)
|
||||||
|
.catch(err => {
|
||||||
|
this.error.emit(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -322,7 +322,7 @@ describe('ShareDataTableAdapter', () => {
|
|||||||
expect(value).toBeNull();
|
expect(value).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should log load error', () => {
|
it('should log load error', (done) => {
|
||||||
let error = 'My Error';
|
let error = 'My Error';
|
||||||
documentListService.getFolderReject = true;
|
documentListService.getFolderReject = true;
|
||||||
documentListService.getFolderRejectError = error;
|
documentListService.getFolderRejectError = error;
|
||||||
@@ -331,10 +331,10 @@ describe('ShareDataTableAdapter', () => {
|
|||||||
spyOn(documentListService, 'getFolder').and.callThrough();
|
spyOn(documentListService, 'getFolder').and.callThrough();
|
||||||
|
|
||||||
let adapter = new ShareDataTableAdapter(documentListService, null, null);
|
let adapter = new ShareDataTableAdapter(documentListService, null, null);
|
||||||
adapter.loadPath('/some/path');
|
adapter.loadPath('/some/path').catch(err => {
|
||||||
|
expect(err).toBe(error);
|
||||||
expect(documentListService.getFolder).toHaveBeenCalled();
|
done();
|
||||||
expect(console.error).toHaveBeenCalledWith(error);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate file icon path based on mime type', () => {
|
it('should generate file icon path based on mime type', () => {
|
||||||
|
@@ -203,9 +203,9 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
|
|||||||
this.setSorting(sorting);
|
this.setSorting(sorting);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPath(path: string) {
|
loadPath(path: string): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
if (path && this.documentListService) {
|
if (path && this.documentListService) {
|
||||||
this.currentPath = path;
|
|
||||||
this.documentListService
|
this.documentListService
|
||||||
.getFolder(path, {
|
.getFolder(path, {
|
||||||
maxItems: this._maxItems,
|
maxItems: this._maxItems,
|
||||||
@@ -213,11 +213,19 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
|
|||||||
rootPath: this.rootPath
|
rootPath: this.rootPath
|
||||||
})
|
})
|
||||||
.subscribe(val => {
|
.subscribe(val => {
|
||||||
|
this.currentPath = path;
|
||||||
this.loadPage(<NodePaging>val);
|
this.loadPage(<NodePaging>val);
|
||||||
this.dataLoaded.emit(null);
|
this.dataLoaded.emit(null);
|
||||||
|
resolve(true);
|
||||||
},
|
},
|
||||||
error => console.error(error));
|
error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve(false);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilter(filter: RowFilter) {
|
setFilter(filter: RowFilter) {
|
||||||
|
Reference in New Issue
Block a user