diff --git a/demo-shell-ng2/app/app.routes.ts b/demo-shell-ng2/app/app.routes.ts
index 1f88ea31cb..139c70467b 100644
--- a/demo-shell-ng2/app/app.routes.ts
+++ b/demo-shell-ng2/app/app.routes.ts
@@ -54,6 +54,11 @@ export const appRoutes: Routes = [
component: FilesComponent,
canActivate: [AuthGuardEcm]
},
+ {
+ path: 'files/:id',
+ component: FilesComponent,
+ canActivate: [AuthGuardEcm]
+ },
{
path: 'datatable',
component: DataTableDemoComponent,
diff --git a/demo-shell-ng2/app/components/files/files.component.html b/demo-shell-ng2/app/components/files/files.component.html
index bbfc19e4e0..9e2f8a60d2 100644
--- a/demo-shell-ng2/app/components/files/files.component.html
+++ b/demo-shell-ng2/app/components/files/files.component.html
@@ -5,7 +5,7 @@
(onSuccess)="documentList.reload()">
+ (pathChanged)="onBreadcrumbPathChanged($event)" *ngIf="!currentFolderId">
this.setupBpmActions(defs || []),
- err => console.log(err)
- );
- } else {
- console.log('You are not logged in');
- }
+ if (this.route) {
+ this.route.params.forEach((params: Params) => {
+ this.currentFolderId = params.hasOwnProperty('id') ? params['id'] : null;
+ });
+ }
+ if (this.auth.isBpmLoggedIn()) {
+ this.formService.getProcessDefinitions().subscribe(
+ defs => this.setupBpmActions(defs || []),
+ err => console.log(err)
+ );
+ } else {
+ console.log('You are not logged in');
+ }
}
viewActivitiForm(event?: any) {
diff --git a/demo-shell-ng2/app/components/search/search-bar.component.html b/demo-shell-ng2/app/components/search/search-bar.component.html
index 2533df52c2..7f66e7c78b 100644
--- a/demo-shell-ng2/app/components/search/search-bar.component.html
+++ b/demo-shell-ng2/app/components/search/search-bar.component.html
@@ -1,11 +1,10 @@
+ (fileSelect)="onItemClicked($event)">
Search results
-
+
diff --git a/demo-shell-ng2/app/components/search/search.component.ts b/demo-shell-ng2/app/components/search/search.component.ts
index ae8f64d019..6351a0b5b2 100644
--- a/demo-shell-ng2/app/components/search/search.component.ts
+++ b/demo-shell-ng2/app/components/search/search.component.ts
@@ -16,6 +16,8 @@
*/
import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+import { MinimalNodeEntity } from 'alfresco-js-api';
@Component({
selector: 'search-component',
@@ -48,10 +50,15 @@ export class SearchComponent {
fileShowed: boolean = false;
fileNodeId: string;
- onFileClicked(event) {
- if (event.value.entry.isFile) {
- this.fileNodeId = event.value.entry.id;
+ constructor(public router: Router) {
+ }
+
+ onNavigateItem(event: MinimalNodeEntity) {
+ if (event.entry.isFile) {
+ this.fileNodeId = event.entry.id;
this.fileShowed = true;
+ } else if (event.entry.isFolder) {
+ this.router.navigate(['/files', event.entry.id]);
}
}
}
diff --git a/ng2-components/ng2-alfresco-documentlist/README.md b/ng2-components/ng2-alfresco-documentlist/README.md
index 2aaf3da951..8df6a013e4 100644
--- a/ng2-components/ng2-alfresco-documentlist/README.md
+++ b/ng2-components/ng2-alfresco-documentlist/README.md
@@ -168,7 +168,9 @@ platformBrowserDynamic().bootstrapModule(AppModule);
| Name | Type | Default | Description |
| --- | --- | --- | --- |
-| `rootPath` | string | -root- | Root node path, i.e. `-root-`, `-shared-`, `-my-`, etc. |
+| `rootFolderId` | string | -root- | Root node ID, i.e. `-root-`, `-shared-`, `-my-`, etc. or a fixed node ID |
+| `currentFolderPath` | string | null | Initial path of displayed folder below the root node, e.g. "/Sites/swsdp/documentLibrary" |
+| `currentFolderId` | string | null | Initial node ID of displayed folder, if given |
| `navigate` | boolean | true | Toggles navigation to folder content or file preview |
| `navigationMode` | string (click\|dblclick) | dblclick | User interaction for folder navigation or file preview |
| `thumbnails` | boolean | false | Show document thumbnails rather than icons |
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.spec.ts
index 19f7a77ac5..c0c2b61793 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.spec.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.spec.ts
@@ -87,7 +87,7 @@ describe('DocumentListBreadcrumb', () => {
it('should update document list on click', (done) => {
let documentList = new DocumentList(null, null, null);
- spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve());
let node = { name: 'name', path: '/path' };
component.target = documentList;
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.ts b/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.ts
index 441073d3dc..20984867eb 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/breadcrumb/breadcrumb.component.ts
@@ -83,8 +83,11 @@ export class DocumentListBreadcrumb {
}
});
+ this.currentFolderPath = route.path;
+
if (this.target) {
this.target.currentFolderPath = route.path;
+ this.target.loadFolder();
}
}
}
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
index 186f678dd8..4bbc6150d8 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { NgZone, TemplateRef } from '@angular/core';
+import { NgZone, SimpleChange, TemplateRef } from '@angular/core';
import { DataTableComponent, DataColumn, DataRowEvent } from 'ng2-alfresco-datatable';
import { DocumentList } from './document-list';
import { DocumentListServiceMock } from './../assets/document-list.service.mock';
@@ -48,12 +48,12 @@ describe('DocumentList', () => {
window['componentHandler'] = componentHandler;
});
- it('should update root path', () => {
+ it('should update root folder ID', () => {
let adapter = documentList.data;
- expect(adapter.rootPath).toBe(adapter.DEFAULT_ROOT_PATH);
+ expect(adapter.rootFolderId).toBe(adapter.DEFAULT_ROOT_ID);
- documentList.rootPath = '-shared-';
- expect(adapter.rootPath).toBe('-shared-');
+ documentList.rootFolderId = '-shared-';
+ expect(adapter.rootFolderId).toBe('-shared-');
});
it('should setup default columns', () => {
@@ -163,7 +163,7 @@ describe('DocumentList', () => {
let node = new FolderNode('');
spyOn(documentList, 'getNodePath').and.returnValue(path);
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve(true));
documentList.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
documentList.onNodeClick(node);
@@ -173,31 +173,31 @@ describe('DocumentList', () => {
it('should not display folder content when no target node provided', () => {
expect(documentList.navigate).toBe(true);
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.stub();
documentList.onNodeClick(null);
- expect(documentList.displayFolderContent).not.toHaveBeenCalled();
+ expect(documentList.loadFolderByPath).not.toHaveBeenCalled();
});
it('should display folder content only on folder node click', () => {
expect(documentList.navigate).toBe(true);
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.stub();
let node = new FileNode();
documentList.onNodeClick(node);
- expect(documentList.displayFolderContent).not.toHaveBeenCalled();
+ expect(documentList.loadFolderByPath).not.toHaveBeenCalled();
});
it('should not display folder content on click when navigation is off', () => {
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.stub();
let node = new FolderNode('');
documentList.navigate = false;
documentList.onNodeClick(node);
- expect(documentList.displayFolderContent).not.toHaveBeenCalled();
+ expect(documentList.loadFolderByPath).not.toHaveBeenCalled();
});
it('should require node to get path', () => {
@@ -205,31 +205,35 @@ describe('DocumentList', () => {
});
it('should display folder content for new folder path', () => {
- spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve());
let newPath = '/some/new/path';
documentList.currentFolderPath = newPath;
- expect(documentList.displayFolderContent).toHaveBeenCalledWith(newPath);
+ documentList.ngOnChanges({currentFolderPath: new SimpleChange(null, newPath)});
+ expect(documentList.loadFolderByPath).toHaveBeenCalledWith(newPath);
});
it('should reset to default path', () => {
- spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve());
documentList.currentFolderPath = null;
+ documentList.ngOnChanges({currentFolderPath: new SimpleChange('', null)});
- expect(documentList.currentFolderPath).toBe(documentList.DEFAULT_ROOT_FOLDER);
- expect(documentList.displayFolderContent).toHaveBeenCalledWith(documentList.DEFAULT_ROOT_FOLDER);
+ expect(documentList.currentFolderPath).toBe(documentList.DEFAULT_FOLDER_PATH);
+ expect(documentList.loadFolderByPath).toHaveBeenCalledWith(documentList.DEFAULT_FOLDER_PATH);
});
it('should emit folder changed event', (done) => {
- spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve());
documentList.folderChange.subscribe(e => {
done();
});
- documentList.currentFolderPath = '/some/new/path';
+ let newPath = '/some/new/path';
+ documentList.currentFolderPath = newPath;
+ documentList.ngOnChanges({currentFolderPath: new SimpleChange(null, newPath)});
});
it('should emit folder changed event with folder details', (done) => {
- spyOn(documentList, 'displayFolderContent').and.returnValue(Promise.resolve());
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve());
let path = '/path';
@@ -239,6 +243,7 @@ describe('DocumentList', () => {
});
documentList.currentFolderPath = path;
+ documentList.ngOnChanges({currentFolderPath: new SimpleChange(null, path)});
});
it('should execute context action on callback', () => {
@@ -259,7 +264,7 @@ describe('DocumentList', () => {
});
it('should subscribe to context action handler', () => {
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.resolve(true));
spyOn(documentList, 'contextActionCallback').and.stub();
let value = {};
documentList.ngOnInit();
@@ -384,16 +389,16 @@ describe('DocumentList', () => {
});
it('should display folder content on reload', () => {
- spyOn(documentList, 'displayFolderContent').and.callThrough();
+ spyOn(documentList, 'loadFolderByPath').and.callThrough();
documentList.reload();
- expect(documentList.displayFolderContent).toHaveBeenCalled();
+ expect(documentList.loadFolderByPath).toHaveBeenCalled();
});
it('should require path to display folder content', () => {
spyOn(documentListService, 'getFolder').and.callThrough();
- documentList.displayFolderContent(null);
- documentList.displayFolderContent('');
+ documentList.loadFolderByPath(null);
+ documentList.loadFolderByPath('');
expect(documentListService.getFolder).not.toHaveBeenCalled();
});
@@ -464,11 +469,11 @@ describe('DocumentList', () => {
});
expect(documentList.currentFolderPath).toBeNull();
- spyOn(documentList, 'displayFolderContent').and.stub();
+ spyOn(documentList, 'loadFolderByPath').and.stub();
documentList.reload();
- expect(documentList.displayFolderContent).not.toHaveBeenCalled();
+ expect(documentList.loadFolderByPath).not.toHaveBeenCalled();
});
it('should enforce single-click on mobile browser', () => {
@@ -482,9 +487,10 @@ describe('DocumentList', () => {
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));
+ spyOn(documentList, 'loadFolderByPath').and.returnValue(Promise.reject(false));
documentList.currentFolderPath = 'wrong-path';
+ documentList.ngOnChanges({currentFolderPath: new SimpleChange(null, documentList.currentFolderPath)});
setTimeout(() => {
expect(raised).toBeTruthy();
done();
@@ -506,24 +512,24 @@ describe('DocumentList', () => {
expect(documentList.isEmptyTemplateDefined()).toBeFalsy();
});
- it('should set root path for underlying adapter', () => {
- documentList.rootPath = 'test';
- expect(documentList.data.rootPath).toBe('test');
+ it('should set root folder ID for underlying adapter', () => {
+ documentList.rootFolderId = 'test';
+ expect(documentList.data.rootFolderId).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 set default root folder ID for underlying adapter', () => {
+ documentList.rootFolderId = null;
+ expect(documentList.data.rootFolderId).toBe(documentList.data.DEFAULT_ROOT_ID);
});
- it('should fetch root path from underlying adapter', () => {
- documentList.data.rootPath = 'test';
- expect(documentList.rootPath).toBe('test');
+ it('should fetch root folder ID from underlying adapter', () => {
+ documentList.data.rootFolderId = 'test';
+ expect(documentList.rootFolderId).toBe('test');
});
- it('should not fetch root path when adapter missing', () => {
+ it('should not fetch root folder ID when adapter missing', () => {
documentList.data = null;
- expect(documentList.rootPath).toBeNull();
+ expect(documentList.rootFolderId).toBeNull();
});
it('should set row filter for underlying adapter', () => {
@@ -561,4 +567,49 @@ describe('DocumentList', () => {
documentList.onRowDblClick(event);
expect(documentList.onNodeDblClick).toHaveBeenCalledWith(node);
});
+
+ describe('navigate by folder ID', () => {
+
+ it('should load folder by ID on init', () => {
+
+ documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692';
+
+ let loadbyIdSpy: jasmine.Spy = spyOn(documentList.data, 'loadById').and.returnValue(Promise.resolve());
+
+ documentList.ngOnInit();
+ expect(loadbyIdSpy).toHaveBeenCalled();
+ expect(documentList.currentFolderPath).toBe('/');
+ });
+
+ it('should load folder by ID on changes', () => {
+
+ let newNodeId = '1d26e465-dea3-42f3-b415-faa8364b9692';
+
+ documentList.ngOnChanges({currentFolderId: new SimpleChange(null, newNodeId)});
+
+ let loadbyPathSpy: jasmine.Spy = spyOn(documentList.data, 'loadPath').and.returnValue(Promise.resolve());
+
+ documentList.ngOnInit();
+ expect(loadbyPathSpy).toHaveBeenCalled();
+ expect(documentList.currentFolderPath).toBe('/');
+ });
+
+ });
+
+ describe('configure root folder', () => {
+
+ it('should re-load folder when rootFolderId changed', () => {
+
+ let newRootFolder = '-new-';
+
+ documentList.ngOnChanges({rootFolderId: new SimpleChange(null, newRootFolder)});
+
+ let loadbyPathSpy: jasmine.Spy = spyOn(documentList.data, 'loadPath').and.returnValue(Promise.resolve());
+
+ documentList.ngOnInit();
+ expect(loadbyPathSpy).toHaveBeenCalled();
+ expect(documentList.currentFolderPath).toBe('/');
+ });
+
+ });
});
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.ts
index ffdbe44cd0..11e969203a 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.ts
@@ -19,7 +19,9 @@ import {
Component,
OnInit,
Input,
+ OnChanges,
Output,
+ SimpleChanges,
EventEmitter,
AfterContentInit,
TemplateRef,
@@ -48,22 +50,25 @@ declare var module: any;
styleUrls: ['./document-list.css'],
templateUrl: './document-list.html'
})
-export class DocumentList implements OnInit, AfterContentInit {
+export class DocumentList implements OnInit, OnChanges, AfterContentInit {
static SINGLE_CLICK_NAVIGATION: string = 'click';
static DOUBLE_CLICK_NAVIGATION: string = 'dblclick';
static DEFAULT_PAGE_SIZE: number = 20;
- DEFAULT_ROOT_FOLDER: string = '/';
+ DEFAULT_FOLDER_PATH: string = '/';
@Input()
- set rootPath(value: string) {
- this.data.rootPath = value || this.data.DEFAULT_ROOT_PATH;
+ set rootFolderId(value: string) {
+ this.data.rootFolderId = value || this.data.DEFAULT_ROOT_ID;
}
- get rootPath(): string {
+ @Input()
+ currentFolderId: string = null;
+
+ get rootFolderId(): string {
if (this.data) {
- return this.data.rootPath;
+ return this.data.rootFolderId;
}
return null;
}
@@ -127,21 +132,11 @@ export class DocumentList implements OnInit, AfterContentInit {
@ViewChild(DataTableComponent)
dataTable: DataTableComponent;
- private _path = this.DEFAULT_ROOT_FOLDER;
+ private _path = this.DEFAULT_FOLDER_PATH;
@Input()
set currentFolderPath(value: string) {
- if (value !== this._path) {
- const path = value || this.DEFAULT_ROOT_FOLDER;
- this.displayFolderContent(path)
- .then(() => {
- this._path = path;
- this.folderChange.emit({ path: path });
- })
- .catch(err => {
- this.error.emit(err);
- });
- }
+ this._path = value;
}
get currentFolderPath(): string {
@@ -220,6 +215,8 @@ export class DocumentList implements OnInit, AfterContentInit {
if (this.isMobile()) {
this.navigationMode = DocumentList.SINGLE_CLICK_NAVIGATION;
}
+
+ this.loadFolder();
}
ngAfterContentInit() {
@@ -229,6 +226,40 @@ export class DocumentList implements OnInit, AfterContentInit {
}
}
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes['currentFolderId'] && changes['currentFolderId'].currentValue) {
+ let folderId = changes['currentFolderId'].currentValue;
+ this.loadFolderById(folderId)
+ .then(() => {
+ this._path = null;
+ })
+ .catch(err => {
+ this.error.emit(err);
+ });
+ } else if (changes['currentFolderPath']) {
+ const path = changes['currentFolderPath'].currentValue || this.DEFAULT_FOLDER_PATH;
+ this.currentFolderPath = path;
+ this.loadFolderByPath(path)
+ .then(() => {
+ this._path = path;
+ this.folderChange.emit({ path: path });
+ })
+ .catch(err => {
+ this.error.emit(err);
+ });
+ } else if (changes['rootFolderId']) {
+ // this.currentFolderPath = this.DEFAULT_FOLDER_PATH;
+ this.loadFolderByPath(this.currentFolderPath)
+ .then(() => {
+ this._path = this.currentFolderPath;
+ this.folderChange.emit({ path: this.currentFolderPath });
+ })
+ .catch(err => {
+ this.error.emit(err);
+ });
+ }
+ }
+
isEmptyTemplateDefined() {
if (this.dataTable) {
if (this.emptyFolderTemplate) {
@@ -277,6 +308,9 @@ export class DocumentList implements OnInit, AfterContentInit {
performNavigation(node: MinimalNodeEntity): boolean {
if (node && node.entry && node.entry.isFolder) {
this.currentFolderPath = this.getNodePath(node);
+ this.currentFolderId = null;
+ this.loadFolder();
+ this.folderChange.emit({ path: this.currentFolderPath });
return true;
}
return false;
@@ -293,21 +327,34 @@ export class DocumentList implements OnInit, AfterContentInit {
}
}
- displayFolderContent(path: string): Promise {
+ loadFolderByPath(path: string): Promise {
return this.data.loadPath(path);
}
+ loadFolderById(id: string): Promise {
+ return this.data.loadById(id);
+ }
+
reload() {
this.ngZone.run(() => {
- if (this.currentFolderPath) {
- this.displayFolderContent(this.currentFolderPath)
- .catch(err => {
- this.error.emit(err);
- });
- }
+ this.loadFolder();
});
}
+ public loadFolder() {
+ if (this.currentFolderId) {
+ this.loadFolderById(this.currentFolderId)
+ .catch(err => {
+ this.error.emit(err);
+ });
+ } else if (this.currentFolderPath) {
+ this.loadFolderByPath(this.currentFolderPath)
+ .catch(err => {
+ this.error.emit(err);
+ });
+ }
+ }
+
/**
* Gets a path for a given node.
* @param node
diff --git a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
index 04b3e73205..4eda393c4b 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
@@ -31,7 +31,7 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
ERR_ROW_NOT_FOUND: string = 'Row not found';
ERR_COL_NOT_FOUND: string = 'Column not found';
- DEFAULT_ROOT_PATH: string = '-root-';
+ DEFAULT_ROOT_ID: string = '-root-';
DEFAULT_DATE_FORMAT: string = 'medium';
DEFAULT_PAGE_SIZE: number = 20;
MIN_PAGE_SIZE: number = 5;
@@ -53,7 +53,7 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
thumbnails: boolean = false;
dataLoaded: DataLoadedEventEmitter;
- rootPath: string = this.DEFAULT_ROOT_PATH;
+ rootFolderId: string = this.DEFAULT_ROOT_ID;
constructor(private documentListService: DocumentListService,
private basePath: string,
@@ -210,7 +210,7 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
.getFolder(path, {
maxItems: this._maxItems,
skipCount: this._skipCount,
- rootPath: this.rootPath
+ rootFolderId: this.rootFolderId
})
.subscribe(val => {
this.currentPath = path;
@@ -228,6 +228,30 @@ export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvid
}
+ loadById(id: string): Promise {
+ return new Promise((resolve, reject) => {
+ if (id && this.documentListService) {
+ this.documentListService
+ .getFolder(null, {
+ maxItems: this._maxItems,
+ skipCount: this._skipCount,
+ rootFolderId: id
+ })
+ .subscribe(val => {
+ this.loadPage(val);
+ this.dataLoaded.emit(null);
+ resolve(true);
+ },
+ error => {
+ reject(error);
+ });
+ } else {
+ resolve(false);
+ }
+ });
+
+ }
+
setFilter(filter: RowFilter) {
this.filter = filter;
diff --git a/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.ts b/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.ts
index 93dc0f2e84..2d51adad1c 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.ts
@@ -30,6 +30,8 @@ export class DocumentListService {
static DEFAULT_MIME_TYPE_ICON: string = 'ft_ic_miscellaneous.svg';
+ static ROOT_ID = '-root-';
+
mimeTypeIcons: any = {
'image/png': 'ft_ic_raster_image.svg',
'image/jpeg': 'ft_ic_raster_image.svg',
@@ -63,17 +65,21 @@ export class DocumentListService {
}
private getNodesPromise(folder: string, opts?: any): Promise {
- let rootPath = '-root-';
- if (opts && opts.rootPath) {
- rootPath = opts.rootPath;
+ let rootNodeId = DocumentListService.ROOT_ID;
+ if (opts && opts.rootFolderId) {
+ rootNodeId = opts.rootFolderId;
}
let params: any = {
- relativePath: folder,
+ includeSource: true,
include: ['path', 'properties']
};
+ if (folder) {
+ params.relativePath = folder;
+ }
+
if (opts) {
if (opts.maxItems) {
params.maxItems = opts.maxItems;
@@ -83,7 +89,7 @@ export class DocumentListService {
}
}
- return this.apiService.getInstance().nodes.getNodeChildren(rootPath, params);
+ return this.apiService.getInstance().nodes.getNodeChildren(rootNodeId, params);
}
deleteNode(nodeId: string): Observable {
@@ -105,7 +111,7 @@ export class DocumentListService {
}
/**
- * Gets the folder node with the content.
+ * Gets the folder node with the specified relative name path below the root node.
* @param folder Path to folder.
* @param opts Options.
* @returns {Observable} Folder entity.
diff --git a/ng2-components/ng2-alfresco-search/README.md b/ng2-components/ng2-alfresco-search/README.md
index 4092139241..c19bc899eb 100644
--- a/ng2-components/ng2-alfresco-search/README.md
+++ b/ng2-components/ng2-alfresco-search/README.md
@@ -225,7 +225,7 @@ platformBrowserDynamic().bootstrapModule(AppModule);
| Name | Description |
| --- | --- |
-| `preview` | Emitted when a file result is clicked/selected |
+| `navigate` | Emitted when a search result is clicked or double-clicked |
| `resultsLoad` | Emitted when search results have fully loaded |
#### Options
@@ -237,6 +237,7 @@ platformBrowserDynamic().bootstrapModule(AppModule);
| `resultType` | {boolean} | (optional) | (none) | Node type to filter search results by, e.g. 'cm:content'. |
| `maxResults` | {boolean} | (optional) | 20 | Maximum number of results to show in the search. |
| `resultSort` | {boolean} | (optional) | (none) | Criteria to sort search results by, must be one of "name" , "modifiedAt" or "createdAt" |
+| `navigationMode` | {string} | (optional) | "dblclick" | Event used to initiate a navigation action to a specific result, one of "click" or "dblclick" |
### Build from sources
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts
index 686a79fe3f..736f6ab511 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.spec.ts
@@ -214,7 +214,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
});
- it('should emit file select when file item clicked', (done) => {
+ it('should emit fileSelect event when file item clicked', (done) => {
spyOn(searchService, 'getQueryNodesPromise')
.and.returnValue(Promise.resolve(result));
@@ -231,7 +231,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
});
});
- it('should not emit preview if a non-file item is clicked', (done) => {
+ it('should emit fileSelect event if when folder item clicked', (done) => {
spyOn(searchService, 'getQueryNodesPromise')
.and.returnValue(Promise.resolve(folderResult));
@@ -240,7 +240,7 @@ describe('AlfrescoSearchAutocompleteComponent', () => {
component.resultsLoad.subscribe(() => {
fixture.detectChanges();
( element.querySelector('#result_row_0')).click();
- expect(component.fileSelect.emit).not.toHaveBeenCalled();
+ expect(component.fileSelect.emit).toHaveBeenCalled();
done();
});
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts
index 94d156879d..bda5221ece 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-autocomplete.component.ts
@@ -19,6 +19,7 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, OnChanges, Output,
import { AlfrescoSearchService, SearchOptions } from './../services/alfresco-search.service';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
+import { MinimalNodeEntity } from 'alfresco-js-api';
@Component({
moduleId: module.id,
@@ -121,10 +122,12 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
* @param node Node to get URL for.
* @returns {string} URL address.
*/
- getMimeTypeIcon(node: any): string {
+ getMimeTypeIcon(node: MinimalNodeEntity): string {
if (node.entry.content && node.entry.content.mimeType) {
let icon = this.alfrescoThumbnailService.getMimeTypeIcon(node.entry.content.mimeType);
return this.resolveIconPath(icon);
+ } else if (node.entry.isFolder) {
+ return 'ft_ic_folder.svg';
}
}
@@ -148,7 +151,7 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
* @param node Node to get URL for.
* @returns {string} URL address.
*/
- getMimeTypeKey(node: any): string {
+ getMimeTypeKey(node: MinimalNodeEntity): string {
if (node.entry.content && node.entry.content.mimeType) {
return 'SEARCH.ICONS.' + this.alfrescoThumbnailService.getMimeTypeKey(node.entry.content.mimeType);
} else {
@@ -161,13 +164,9 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
firstResult.focus();
}
- onItemClick(node): void {
+ onItemClick(node: MinimalNodeEntity): void {
if (node && node.entry) {
- if (node.entry.isFile) {
- this.fileSelect.emit({
- value: node
- });
- }
+ this.fileSelect.emit(node);
}
}
@@ -179,12 +178,10 @@ export class AlfrescoSearchAutocompleteComponent implements OnInit, OnChanges {
this.searchFocus.emit($event);
}
- onRowEnter(node): void {
+ onRowEnter(node: MinimalNodeEntity): void {
if (node && node.entry) {
if (node.entry.isFile) {
- this.fileSelect.emit({
- value: node
- });
+ this.fileSelect.emit(node);
}
}
}
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts
index c858990197..5dd0de6e0e 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search-control.component.ts
@@ -72,7 +72,7 @@ export class AlfrescoSearchControlComponent implements OnInit, OnDestroy {
liveSearchRoot: string = '-root-';
@Input()
- liveSearchResultType: string = 'cm:content';
+ liveSearchResultType: string = null;
@Input()
liveSearchResultSort: string = null;
@@ -171,9 +171,7 @@ export class AlfrescoSearchControlComponent implements OnInit, OnDestroy {
}
onFileClicked(event): void {
- this.fileSelect.emit({
- value: event.value
- });
+ this.fileSelect.emit(event);
}
onSearchFocus($event): void {
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html
index 75cfea1fb4..4b023fbfbe 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.html
@@ -16,7 +16,7 @@
-
+
}}) |
{{result.entry.name}} |
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts
index 48c7ddfb24..039abc5865 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.spec.ts
@@ -15,7 +15,8 @@
* limitations under the License.
*/
-import { ReflectiveInjector, SimpleChange } from '@angular/core';
+import { DebugElement, ReflectiveInjector, SimpleChange } from '@angular/core';
+import { By } from '@angular/platform-browser';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Rx';
@@ -256,44 +257,91 @@ describe('AlfrescoSearchComponent', () => {
});
});
- describe('search result actions', () => {
+ describe('search result interactions', () => {
- it('should emit preview when file item clicked', (done) => {
+ let debugElement: DebugElement;
+ let searchService: AlfrescoSearchService;
+ let querySpy: jasmine.Spy;
+ let emitSpy: jasmine.Spy;
+ const rowSelector = '[data-automation-id="search_result_table"] tbody tr';
- let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
- spyOn(searchService, 'getQueryNodesPromise')
- .and.returnValue(Promise.resolve(result));
+ beforeEach(() => {
+ debugElement = fixture.debugElement;
+ searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
+ querySpy = spyOn(searchService, 'getQueryNodesPromise').and.returnValue(Promise.resolve(result));
+ emitSpy = spyOn(component.navigate, 'emit');
+ });
- component.resultsLoad.subscribe(() => {
- fixture.detectChanges();
- ( element.querySelector('#result_row_0')).click();
+ describe('click results', () => {
+
+ beforeEach(() => {
+ component.navigationMode = AlfrescoSearchComponent.SINGLE_CLICK_NAVIGATION;
});
- component.searchTerm = 'searchTerm';
- component.ngOnInit();
+ it('should emit navigation event when file item clicked', (done) => {
- component.preview.subscribe(() => {
- done();
+ component.resultsLoad.subscribe(() => {
+ fixture.detectChanges();
+ debugElement.query(By.css(rowSelector)).triggerEventHandler('click', {});
+ expect(emitSpy).toHaveBeenCalled();
+ done();
+ });
+
+ component.searchTerm = 'searchTerm';
+ component.ngOnInit();
+ });
+
+ it('should emit navigation event when non-file item is clicked', (done) => {
+
+ querySpy.and.returnValue(Promise.resolve(folderResult));
+
+ component.resultsLoad.subscribe(() => {
+ fixture.detectChanges();
+ debugElement.query(By.css(rowSelector)).triggerEventHandler('click', {});
+ expect(emitSpy).toHaveBeenCalled();
+ done();
+ });
+
+ component.searchTerm = 'searchTerm';
+ component.ngOnInit();
});
});
- it('should not emit preview when non-file item is clicked', (done) => {
+ describe('double click results', () => {
- let searchService = fixture.debugElement.injector.get(AlfrescoSearchService);
- spyOn(searchService, 'getQueryNodesPromise')
- .and.returnValue(Promise.resolve(folderResult));
-
- spyOn(component.preview, 'emit');
- component.resultsLoad.subscribe(() => {
- fixture.detectChanges();
- ( element.querySelector('#result_row_0')).click();
- expect(component.preview.emit).not.toHaveBeenCalled();
- done();
+ beforeEach(() => {
+ component.navigationMode = AlfrescoSearchComponent.DOUBLE_CLICK_NAVIGATION;
});
- component.searchTerm = 'searchTerm';
- component.ngOnInit();
+ it('should emit navigation event when file item clicked', (done) => {
+
+ component.resultsLoad.subscribe(() => {
+ fixture.detectChanges();
+ debugElement.query(By.css(rowSelector)).triggerEventHandler('dblclick', {});
+ expect(emitSpy).toHaveBeenCalled();
+ done();
+ });
+
+ component.searchTerm = 'searchTerm';
+ component.ngOnInit();
+ });
+
+ it('should emit navigation event when non-file item is clicked', (done) => {
+
+ querySpy.and.returnValue(Promise.resolve(folderResult));
+
+ component.resultsLoad.subscribe(() => {
+ fixture.detectChanges();
+ debugElement.query(By.css(rowSelector)).triggerEventHandler('dblclick', {});
+ expect(emitSpy).toHaveBeenCalled();
+ done();
+ });
+
+ component.searchTerm = 'searchTerm';
+ component.ngOnInit();
+ });
});
+
});
});
diff --git a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts
index 7acfc5d29e..53db492bfd 100644
--- a/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts
+++ b/ng2-components/ng2-alfresco-search/src/components/alfresco-search.component.ts
@@ -20,6 +20,7 @@ import { ActivatedRoute, Params } from '@angular/router';
import { AlfrescoSearchService, SearchOptions } from './../services/alfresco-search.service';
import { AlfrescoThumbnailService } from './../services/alfresco-thumbnail.service';
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
+import { MinimalNodeEntity } from 'alfresco-js-api';
@Component({
moduleId: module.id,
@@ -29,6 +30,9 @@ import { AlfrescoTranslationService } from 'ng2-alfresco-core';
})
export class AlfrescoSearchComponent implements OnChanges, OnInit {
+ static SINGLE_CLICK_NAVIGATION: string = 'click';
+ static DOUBLE_CLICK_NAVIGATION: string = 'dblclick';
+
@Input()
searchTerm: string = '';
@@ -44,8 +48,11 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
@Input()
resultType: string = null;
+ @Input()
+ navigationMode: string = AlfrescoSearchComponent.DOUBLE_CLICK_NAVIGATION; // click|dblclick
+
@Output()
- preview: EventEmitter = new EventEmitter();
+ navigate: EventEmitter = new EventEmitter();
@Output()
resultsLoad = new EventEmitter();
@@ -92,6 +99,8 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
if (node.entry.content && node.entry.content.mimeType) {
let icon = this._alfrescoThumbnailService.getMimeTypeIcon(node.entry.content.mimeType);
return this.resolveIconPath(icon);
+ } else if (node.entry.isFolder) {
+ return 'ft_ic_folder.svg';
}
}
@@ -154,14 +163,17 @@ export class AlfrescoSearchComponent implements OnChanges, OnInit {
}
onItemClick(node, event?: Event): void {
- if (event) {
- event.preventDefault();
+ if (this.navigate && this.navigationMode === AlfrescoSearchComponent.SINGLE_CLICK_NAVIGATION) {
+ if (node && node.entry) {
+ this.navigate.emit(node);
+ }
}
- if (node && node.entry) {
- if (node.entry.isFile) {
- this.preview.emit({
- value: node
- });
+ }
+
+ onItemDblClick(node: MinimalNodeEntity) {
+ if (this.navigate && this.navigationMode === AlfrescoSearchComponent.DOUBLE_CLICK_NAVIGATION) {
+ if (node && node.entry) {
+ this.navigate.emit(node);
}
}
}