From 8775ec7c314f1a2f1106feaca26a2a7b1e61f16b Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Tue, 6 Dec 2016 16:55:58 +0000 Subject: [PATCH] #384 Provide Create Folder button --- .../ng2-alfresco-documentlist/index.ts | 2 + .../src/components/document-list.html | 4 + .../src/components/document-list.ts | 3 + .../src/components/document-menu-action.css | 74 ++++++++++ .../src/components/document-menu-action.html | 36 +++++ .../src/components/document-menu-action.ts | 130 ++++++++++++++++++ .../services/document-list.service.spec.ts | 130 ++++++++++++++++++ .../src/services/document-list.service.ts | 14 ++ 8 files changed, 393 insertions(+) create mode 100644 ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.css create mode 100644 ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.html create mode 100644 ng2-components/ng2-alfresco-documentlist/src/components/document-menu-action.ts 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 @@ + + +
+ +
    +
  • + folder + New Folder +
  • +
+
+
{{message}}
+ + + +

New folder

+
+
+ +
+
+
+ + +
+
\ 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.