diff --git a/ng2-components/ng2-alfresco-documentlist/index.ts b/ng2-components/ng2-alfresco-documentlist/index.ts
index 5178390abc..4469842654 100644
--- a/ng2-components/ng2-alfresco-documentlist/index.ts
+++ b/ng2-components/ng2-alfresco-documentlist/index.ts
@@ -20,6 +20,7 @@ import { CoreModule } from 'ng2-alfresco-core';
import { DataTableModule } from 'ng2-alfresco-datatable';
import { DocumentList } from './src/components/document-list';
+import { DocumentMenuAction } from './src/components/document-menu-action';
import { ContentColumn } from './src/components/content-column';
import { ContentColumnList } from './src/components/content-column-list';
import { ContentAction } from './src/components/content-action';
@@ -54,6 +55,7 @@ export * from './src/models/document-library.model';
export const DOCUMENT_LIST_DIRECTIVES: any[] = [
DocumentList,
+ DocumentMenuAction,
ContentColumn,
ContentColumnList,
ContentAction,
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.html b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.html
index 33da972d56..d1bbf32cb0 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.html
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.html
@@ -1,3 +1,7 @@
+
+
+
+
+
+
+ {{message}}
+
+
+
\ No newline at end of file
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.ts
new file mode 100644
index 0000000000..7209e3973b
--- /dev/null
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.ts
@@ -0,0 +1,130 @@
+/*!
+ * @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 {
+ Component,
+ OnInit,
+ Input,
+ Output,
+ EventEmitter,
+ ViewChild
+} from '@angular/core';
+import { DocumentListService } from './../services/document-list.service';
+import { AlfrescoTranslationService } from 'ng2-alfresco-core';
+import { ContentActionModel } from './../models/content-action.model';
+
+declare let dialogPolyfill: any;
+
+const ERROR_FOLDER_ALREADY_EXIST = 409;
+
+@Component({
+ moduleId: module.id,
+ selector: 'alfresco-document-menu-action',
+ styleUrls: ['./document-menu-action.css'],
+ templateUrl: './document-menu-action.html'
+})
+export class DocumentMenuAction implements OnInit {
+
+ @Input()
+ currentFolderPath: string;
+
+ @Output()
+ onSuccess = new EventEmitter();
+
+ @Output()
+ onError = new EventEmitter();
+
+ @ViewChild('dialog')
+ dialog: any;
+
+ actions: ContentActionModel[] = [];
+
+ message: string;
+
+ constructor(
+ private documentListService: DocumentListService,
+ private translate: AlfrescoTranslationService) {
+
+ if (translate) {
+ translate.addTranslationFolder('ng2-alfresco-documentlist', 'node_modules/ng2-alfresco-documentlist/dist/src');
+ }
+ }
+
+ ngOnInit() {}
+
+ public createFolder(name: string) {
+ this.cancel();
+ this.documentListService.createFolder(name, this.currentFolderPath)
+ .subscribe(
+ res => {
+ let relativeDir = this.currentFolderPath;
+ console.log(relativeDir);
+ this.onSuccess.emit({value: relativeDir});
+ },
+ error => {
+ let errorMessagePlaceholder = this.getErrorMessage(error.response);
+ if (errorMessagePlaceholder) {
+ this.onError.emit({value: errorMessagePlaceholder});
+ this.message = this.formatString(errorMessagePlaceholder, [name]);
+ console.log(this.message);
+ } else {
+ console.log(error);
+ }
+ }
+ );
+ }
+
+ public showDialog() {
+ if (!this.dialog.nativeElement.showModal) {
+ dialogPolyfill.registerDialog(this.dialog.nativeElement);
+ }
+ this.dialog.nativeElement.showModal();
+ }
+
+ public cancel() {
+ if (this.dialog) {
+ this.dialog.nativeElement.close();
+ }
+ }
+
+ /**
+ * Retrive the error message using the error status code
+ * @param response - object that contain the HTTP response
+ * @returns {string}
+ */
+ private getErrorMessage(response: any): string {
+ if (response.body && response.body.error.statusCode === ERROR_FOLDER_ALREADY_EXIST) {
+ let errorMessage: any;
+ errorMessage = this.translate.get('FILE_UPLOAD.MESSAGES.FOLDER_ALREADY_EXIST');
+ return errorMessage.value;
+ }
+ }
+
+ /**
+ * Replace a placeholder {0} in a message with the input keys
+ * @param message - the message that conains the placeholder
+ * @param keys - array of value
+ * @returns {string} - The message without placeholder
+ */
+ private formatString(message: string, keys: any []) {
+ let i = keys.length;
+ while (i--) {
+ message = message.replace(new RegExp('\\{' + i + '\\}', 'gm'), keys[i]);
+ }
+ return message;
+ }
+}
diff --git a/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.spec.ts
index d70373af6e..74df4cf5c0 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.spec.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/services/document-list.service.spec.ts
@@ -30,6 +30,67 @@ describe('DocumentListService', () => {
let authService: AlfrescoAuthenticationService;
let alfrescoApiService: AlfrescoApiService;
+ let fakeEntryNode = {
+ 'entry': {
+ 'aspectNames': ['cm:auditable'],
+ 'createdAt': '2016-12-06T15:58:32.408+0000',
+ 'isFolder': true,
+ 'isFile': false,
+ 'createdByUser': {'id': 'admin', 'displayName': 'Administrator'},
+ 'modifiedAt': '2016-12-06T15:58:32.408+0000',
+ 'modifiedByUser': {'id': 'admin', 'displayName': 'Administrator'},
+ 'name': 'fake-name',
+ 'id': '2214733d-a920-4dbe-af95-4230345fae82',
+ 'nodeType': 'cm:folder',
+ 'parentId': 'ed7ab80e-b398-4bed-b38d-139ae4cc592a'
+ }
+ };
+
+ let fakeAlreadyExist = {
+ 'error': {
+ 'errorKey': 'Duplicate child name not allowed: empty',
+ 'statusCode': 409,
+ 'briefSummary': '11060002 Duplicate child name not' +
+ ' allowed: empty',
+ 'stackTrace': 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.',
+ 'descriptionURL': 'https://api-explorer.alfresco.com'
+ }
+ };
+
+ let fakeFolder = {
+ 'list': {
+ 'pagination': {'count': 1, 'hasMoreItems': false, 'totalItems': 1, 'skipCount': 0, 'maxItems': 20},
+ 'entries': [{
+ 'entry': {
+ 'createdAt': '2016-12-06T13:03:14.880+0000',
+ 'path': {
+ 'name': '/Company Home/Sites/swsdp/documentLibrary/empty',
+ 'isComplete': true,
+ 'elements': [{
+ 'id': 'ed7ab80e-b398-4bed-b38d-139ae4cc592a',
+ 'name': 'Company Home'
+ }, {'id': '99e1368f-e816-47fc-a8bf-3b358feaf31e', 'name': 'Sites'}, {
+ 'id': 'b4cff62a-664d-4d45-9302-98723eac1319',
+ 'name': 'swsdp'
+ }, {
+ 'id': '8f2105b4-daaf-4874-9e8a-2152569d109b',
+ 'name': 'documentLibrary'
+ }, {'id': '17fa78d2-4d6b-4a46-876b-4b0ea07f7f32', 'name': 'empty'}]
+ },
+ 'isFolder': true,
+ 'isFile': false,
+ 'createdByUser': {'id': 'admin', 'displayName': 'Administrator'},
+ 'modifiedAt': '2016-12-06T13:03:14.880+0000',
+ 'modifiedByUser': {'id': 'admin', 'displayName': 'Administrator'},
+ 'name': 'fake-name',
+ 'id': 'aac546f6-1525-46ff-bf6b-51cb85f3cda7',
+ 'nodeType': 'cm:folder',
+ 'parentId': '17fa78d2-4d6b-4a46-876b-4b0ea07f7f32'
+ }
+ }]
+ }
+ };
+
beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([
AlfrescoApiService,
@@ -71,4 +132,73 @@ describe('DocumentListService', () => {
expect(service.getMimeTypeIcon('')).toBe(DocumentListService.DEFAULT_MIME_TYPE_ICON);
expect(service.getMimeTypeIcon('missing/type')).toBe(DocumentListService.DEFAULT_MIME_TYPE_ICON);
});
+
+ it('should create a folder in the path', () => {
+ service.createFolder('fake-name', 'fake-path').subscribe(
+ res => {
+ expect(res).toBeDefined();
+ expect(res.entry).toBeDefined();
+ expect(res.entry.isFolder).toBeTruthy();
+ expect(res.entry.name).toEqual('fake-name');
+ expect(res.entry.nodeType).toEqual('cm:folder');
+ }
+ );
+
+ jasmine.Ajax.requests.mostRecent().respondWith({
+ status: 200,
+ contentType: 'json',
+ responseText: fakeEntryNode
+ });
+ });
+
+ it('should emit an error when the folder already exist', () => {
+ service.createFolder('fake-name', 'fake-path').subscribe(
+ res => {
+
+ },
+ err => {
+ expect(err).toBeDefined();
+ expect(err.status).toEqual(409);
+ expect(err.response).toBeDefined();
+ }
+ );
+
+ jasmine.Ajax.requests.mostRecent().respondWith({
+ status: 409,
+ contentType: 'json',
+ responseText: fakeAlreadyExist
+ });
+ });
+
+ it('should return the folder info', () => {
+ service.getFolder('/fake-root/fake-name').subscribe(
+ res => {
+ expect(res).toBeDefined();
+ expect(res.list).toBeDefined();
+ expect(res.list.entries).toBeDefined();
+ expect(res.list.entries.length).toBe(1);
+ expect(res.list.entries[0].entry.isFolder).toBeTruthy();
+ expect(res.list.entries[0].entry.name).toEqual('fake-name');
+ }
+ );
+
+ jasmine.Ajax.requests.mostRecent().respondWith({
+ status: 200,
+ contentType: 'json',
+ responseText: fakeFolder
+ });
+ });
+
+ it('should delete the folder', () => {
+ service.deleteNode('fake-id').subscribe(
+ res => {
+ expect(res).toBeNull();
+ }
+ );
+
+ jasmine.Ajax.requests.mostRecent().respondWith({
+ status: 204,
+ contentType: 'json'
+ });
+ });
});
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 632f597a19..93dc0f2e84 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
@@ -90,6 +90,20 @@ export class DocumentListService {
return Observable.fromPromise(this.apiService.getInstance().nodes.deleteNode(nodeId));
}
+ /**
+ * Create a new folder in the path.
+ * @param name
+ * @param path
+ * @returns {any}
+ */
+ createFolder(name: string, path: string): Observable {
+ return Observable.fromPromise(this.apiService.getInstance().nodes.createFolder(name, path))
+ .map(res => {
+ return res;
+ })
+ .catch(this.handleError);
+ }
+
/**
* Gets the folder node with the content.
* @param folder Path to folder.