From b96dcb7bb0d1508a4366e25405e7a409ab3e1819 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Tue, 26 Jul 2016 10:36:19 +0100 Subject: [PATCH 01/15] Basic single page with activiti task list and form render --- .../app/components/tasks/activiti.service.ts | 85 -------------- .../tasks/tasks-demo.component.html | 24 ++++ .../components/tasks/tasks-demo.component.ts | 66 +++++++++-- .../ng2-activiti-tasklist/i18n/en.json | 17 +++ .../ng2-activiti-tasklist/i18n/it.json | 17 +++ ng2-components/ng2-activiti-tasklist/index.ts | 4 +- .../ng2-activiti-tasklist/package.json | 3 +- .../activiti-task-details.component.css | 3 + .../activiti-task-details.component.html | 13 +++ .../activiti-task-details.component.ts | 92 +++++++++++++++ .../activiti-tasklist.component.html | 25 +++-- .../components/activiti-tasklist.component.ts | 17 ++- .../src/models/task-details.model.ts | 105 ++++++++++++++++++ .../src/services/activiti-tasklist.service.ts | 55 ++++++++- 14 files changed, 416 insertions(+), 110 deletions(-) delete mode 100644 demo-shell-ng2/app/components/tasks/activiti.service.ts create mode 100644 demo-shell-ng2/app/components/tasks/tasks-demo.component.html create mode 100644 ng2-components/ng2-activiti-tasklist/i18n/en.json create mode 100644 ng2-components/ng2-activiti-tasklist/i18n/it.json create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts create mode 100644 ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts diff --git a/demo-shell-ng2/app/components/tasks/activiti.service.ts b/demo-shell-ng2/app/components/tasks/activiti.service.ts deleted file mode 100644 index 9b8b5d95dc..0000000000 --- a/demo-shell-ng2/app/components/tasks/activiti.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -/*! - * @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 { Injectable } from '@angular/core'; -import { Http, Headers, RequestOptions, Response } from '@angular/http'; -// import { Observable } from 'rxjs/Rx'; - -@Injectable() -export class ActivitiService { - - constructor(private http: Http) {} - - login(username: string, password: string) { - let url = 'http://localhost:9999/activiti-app/app/authentication'; - let headers = new Headers({ - 'Content-Type': 'application/x-www-form-urlencoded', - 'Cache-Control': 'no-cache' - }); - let options = new RequestOptions({ headers: headers }); - let data = 'j_username=' - + encodeURIComponent(username) - + '&j_password=' - + encodeURIComponent(password) - + '&_spring_security_remember_me=true&submit=Login'; - - return this.http - .post(url, data, options) - .toPromise() - // .then(res => console.log(res)) - .catch(this.handleError); - } - - getTasks() { - // emulate filter value - let data = JSON.stringify({ - 'page': 0, - 'filterId': 3, - 'filter': { - 'sort': 'created-desc', - 'name': '', - 'state': 'open', - 'assignment': 'involved' - }, - 'appDefinitionId': null - }); - - let url = 'http://localhost:9999/activiti-app/app/rest/filter/tasks'; - let headers = new Headers({ - 'Content-Type': 'application/json', - 'Cache-Control': 'no-cache' - }); - let options = new RequestOptions({ headers: headers }); - - return this.http - .post(url, data, options) - .toPromise() - .then(this.parseJSON) - .catch(this.handleError); - } - - private parseJSON(res: Response) { - let body = res.json(); - return body.data || { }; - } - - private handleError(error: any) { - console.error('An error occurred', error); - return Promise.reject(error.message || error); - } - -} diff --git a/demo-shell-ng2/app/components/tasks/tasks-demo.component.html b/demo-shell-ng2/app/components/tasks/tasks-demo.component.html new file mode 100644 index 0000000000..87fa1b0ab7 --- /dev/null +++ b/demo-shell-ng2/app/components/tasks/tasks-demo.component.html @@ -0,0 +1,24 @@ +
+
+
    +
  • + + + +
  • +
  • + +
  • +
+
+
+ +
+
Task Details
+
\ No newline at end of file diff --git a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts b/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts index 2d608bc846..f5063fd608 100644 --- a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts +++ b/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts @@ -16,36 +16,84 @@ */ import { Component, OnInit } from '@angular/core'; -import { ActivitiTaskList } from 'ng2-activiti-tasklist'; +import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist'; +import { ActivitiForm } from 'ng2-activiti-form'; + import { ObjectDataTableAdapter, ObjectDataColumn } from 'ng2-alfresco-datatable'; @Component({ selector: 'tasks-demo', template: ` -
- -
+
+
+
    +
  • + + + +
  • +
  • + +
  • +
+
+
+ +
+
+ +
+
+ `, - directives: [ActivitiTaskList], + directives: [ALFRESCO_TASKLIST_DIRECTIVES, ActivitiForm], styles: [':host > .container { padding: 10px; }'] }) export class TasksDemoComponent implements OnInit { + currentChoice: string = 'task-list'; + + currentTaskId: string; + data: ObjectDataTableAdapter; constructor() { this.data = new ObjectDataTableAdapter([], []); } + setChoice($event) { + this.currentChoice = $event.target.value; + } + + isProcessListSelected() { + return this.currentChoice === 'process-list'; + } + + isTaskListSelected() { + return this.currentChoice === 'task-list'; + } + ngOnInit() { let schema = [ - {type: 'text', key: 'id', title: 'Id'}, - {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, - {type: 'text', key: 'formKey', title: 'Form Key', sortable: true}, - {type: 'text', key: 'created', title: 'Created', sortable: true} + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true} ]; let columns = schema.map(col => new ObjectDataColumn(col)); this.data.setColumns(columns); } + onRowClick(taskId) { + this.currentTaskId = taskId; + } + } diff --git a/ng2-components/ng2-activiti-tasklist/i18n/en.json b/ng2-components/ng2-activiti-tasklist/i18n/en.json new file mode 100644 index 0000000000..1333cd2e5d --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/i18n/en.json @@ -0,0 +1,17 @@ +{ + "TASK_LIST": { + "MESSAGES": { + "NONE": "No tasks list found." + } + }, + "TASK_DETAILS": { + "MESSAGES": { + "NONE": "No task details found." + } + }, + "TASK_FILTERS": { + "MESSAGES": { + "NONE": "No task filter selected." + } + } +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/i18n/it.json b/ng2-components/ng2-activiti-tasklist/i18n/it.json new file mode 100644 index 0000000000..d7fd51d6d0 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/i18n/it.json @@ -0,0 +1,17 @@ +{ + "TASK_LIST": { + "MESSAGES": { + "NONE": "Nessuna lista tasks trovata." + } + }, + "TASK_DETAILS": { + "MESSAGES": { + "NONE": "Nessun dettaglio task trovato." + } + }, + "TASK_FILTERS": { + "MESSAGES": { + "NONE": "Nessun filtro task selezionato." + } + } +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index f9c4e4a420..b2dd93d5a1 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -16,7 +16,9 @@ */ import { ActivitiTaskList } from './src/components/activiti-tasklist.component'; +import { ActivitiTaskDetails } from './src/components/activiti-task-details.component'; + export * from './src/components/activiti-tasklist.component'; -export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ActivitiTaskList]; +export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ActivitiTaskList, ActivitiTaskDetails]; diff --git a/ng2-components/ng2-activiti-tasklist/package.json b/ng2-components/ng2-activiti-tasklist/package.json index 8e172fb1d6..dda05ee92a 100644 --- a/ng2-components/ng2-activiti-tasklist/package.json +++ b/ng2-components/ng2-activiti-tasklist/package.json @@ -70,7 +70,8 @@ "zone.js": "0.6.12", "ng2-translate": "2.2.2", "ng2-alfresco-core": "0.2.0", - "ng2-alfresco-datatable": "0.2.0", + "ng2-alfresco-datatable": "0.2.0", + "ng2-activiti-form": "0.2.0", "alfresco-js-api": "^0.1.0" }, "peerDependencies": { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css new file mode 100644 index 0000000000..07eaf92d80 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css @@ -0,0 +1,3 @@ +:host { + width: 100%; +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html new file mode 100644 index 0000000000..b415d64a64 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html @@ -0,0 +1,13 @@ +
+

{{ 'TASK_DETAILS.MESSAGES.NONE' | translate }}

+
+
+

{{taskDetails.name}}

+
+
Email: {{taskDetails.assignee.email}}
+
FirstName: {{taskDetails.assignee.firstName}}
+
LastName: {{taskDetails.assignee.lastName}}
+
+ + +
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts new file mode 100644 index 0000000000..7bacb64ec3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts @@ -0,0 +1,92 @@ +/*! + * @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, Input, OnInit, OnChanges } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { TaskDetailsModel } from '../models/task-details.model'; +import { ActivitiForm } from 'ng2-activiti-form'; + + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-task-details', + moduleId: __moduleName, + templateUrl: './activiti-task-details.component.html', + styleUrls: ['./activiti-task-details.component.css'], + providers: [ActivitiTaskListService], + directives: [ActivitiForm], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiTaskDetails implements OnInit, OnChanges { + + @Input() + taskId: string; + + taskDetails: TaskDetailsModel; + + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + public activiti: ActivitiTaskListService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + } + + ngOnInit() { + if (this.taskId) { + this.activiti.getTaskDetails(this.taskId).subscribe( + (res: TaskDetailsModel) => { + this.taskDetails = res; + console.log(this.taskDetails); + } + ); + } + } + + ngOnChanges(change) { + this.loadDetails(this.taskId); + } + + loadDetails(id: string) { + if (id) { + this.activiti.getTaskDetails(id).subscribe( + (res: TaskDetailsModel) => { + this.taskDetails = res; + console.log(this.taskDetails); + } + ); + } + } + + onComplete() { + this.activiti.completeTask(this.taskId).subscribe( + (res) => { + console.log(res); + } + ); + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html index d3d2c96d0c..3176503aee 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html @@ -1,12 +1,23 @@ -
{{ 'TASK_DETAILS.CHECKLIST.NONE' | translate }} -
\ No newline at end of file + + + +

New Task

+
+
+ + +
+
+
+ + +
+
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts index 57f66571fc..e958e993a1 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts @@ -15,10 +15,12 @@ * limitations under the License. */ -import { Component, Input, OnInit, OnChanges } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { TaskDetailsModel } from '../models/task-details.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; declare let componentHandler: any; declare let __moduleName: string; @@ -29,16 +31,24 @@ declare let __moduleName: string; templateUrl: './activiti-checklist.component.html', styleUrls: ['./activiti-checklist.component.css'], providers: [ActivitiTaskListService], - pipes: [ AlfrescoPipeTranslate ] + pipes: [AlfrescoPipeTranslate] }) -export class ActivitiChecklist implements OnInit, OnChanges { +export class ActivitiChecklist implements OnInit { @Input() taskId: string; + @ViewChild('dialog') + dialog: any; + + taskName: string; + checklist: TaskDetailsModel [] = []; + private taskObserver: Observer; + task$: Observable; + /** * Constructor * @param auth @@ -51,31 +61,60 @@ export class ActivitiChecklist implements OnInit, OnChanges { if (translate) { translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); } + this.task$ = new Observable(observer => this.taskObserver = observer).share(); } ngOnInit() { + this.task$.subscribe((task: TaskDetailsModel) => { + this.checklist.push(task); + }); + if (this.taskId) { this.load(this.taskId); } } - ngOnChanges(change) { - this.load(this.taskId); - } - - public add() { - alert('Add CheckList'); - } - public load(taskId: string) { + this.checklist = []; if (this.taskId) { this.activitiTaskList.getTaskChecklist(this.taskId).subscribe( (res: TaskDetailsModel[]) => { - this.checklist = res; + res.forEach((task) => { + this.taskObserver.next(task); + }); + }, + (err) => { + console.log(err); } ); } else { this.checklist = []; } } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + public add() { + let newTask = new TaskDetailsModel({name: this.taskName, parentTaskId: this.taskId, assignee: {id: '1'}}); + this.activitiTaskList.addTask(newTask).subscribe( + (res: TaskDetailsModel) => { + this.checklist.push(res); + }, + (err) => { + console.log(err); + } + ); + + this.cancel(); + } + + public cancel() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css index 6979275ee7..7e9e64291f 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css @@ -3,7 +3,7 @@ } .activiti-label { - color: rgb(255,152,0); + font-weight: bolder; } .material-icons:hover { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html index bb12d2fde4..50fb144e73 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html @@ -20,12 +20,12 @@ - +

New comment

- - + +
diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts index 55a93c9de2..1ae99929c2 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts @@ -15,10 +15,12 @@ * limitations under the License. */ -import { Component, Input, OnInit, OnChanges, ViewChild } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { Comment } from '../models/comment.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; declare let componentHandler: any; declare let __moduleName: string; @@ -32,7 +34,7 @@ declare let __moduleName: string; pipes: [ AlfrescoPipeTranslate ] }) -export class ActivitiComments implements OnInit, OnChanges { +export class ActivitiComments implements OnInit { @Input() taskId: string; @@ -42,6 +44,11 @@ export class ActivitiComments implements OnInit, OnChanges { comments: Comment [] = []; + private commentObserver: Observer; + comment$: Observable; + + message: string; + /** * Constructor * @param auth @@ -54,23 +61,32 @@ export class ActivitiComments implements OnInit, OnChanges { if (translate) { translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); } + + this.comment$ = new Observable(observer => this.commentObserver = observer).share(); + } ngOnInit() { + this.comment$.subscribe((comment: Comment) => { + this.comments.push(comment); + }); + if (this.taskId) { this.load(this.taskId); } } - ngOnChanges(change) { - this.load(this.taskId); - } - public load(taskId: string) { + this.comments = []; if (this.taskId) { this.activitiTaskList.getTaskComments(this.taskId).subscribe( (res: Comment[]) => { - this.comments = res; + res.forEach((comment) => { + this.commentObserver.next(comment); + }); + }, + (err) => { + console.log(err); } ); } else { @@ -85,14 +101,15 @@ export class ActivitiComments implements OnInit, OnChanges { } public add() { - alert('add comment'); - if (this.taskId) { - this.activitiTaskList.addTaskComment(this.taskId, 'test comment').subscribe( - (res: Comment[]) => { - this.comments = res; - } - ); - } + this.activitiTaskList.addTaskComment(this.taskId, this.message).subscribe( + (res: Comment) => { + this.comments.push(res); + this.message = ''; + }, + (err) => { + console.log(err); + } + ); this.cancel(); } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html new file mode 100644 index 0000000000..580798c6a3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts new file mode 100644 index 0000000000..26d625e513 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts @@ -0,0 +1,94 @@ +/*! + * @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, Output, EventEmitter, OnInit} from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { FilterModel } from '../models/filter.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-filters', + moduleId: __moduleName, + templateUrl: './activiti-filters.component.html', + providers: [ActivitiTaskListService], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiFilters implements OnInit { + + @Output() + filterClick: EventEmitter = new EventEmitter(); + + private filterObserver: Observer; + filter$: Observable; + + currentFilter: FilterModel; + + filters: FilterModel [] = []; + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + public activiti: ActivitiTaskListService) { + this.filter$ = new Observable(observer => this.filterObserver = observer).share(); + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + } + + ngOnInit() { + this.filter$.subscribe((filter: FilterModel) => { + this.filters.push(filter); + }); + + this.load(); + } + + /** + * The method call the adapter data table component for render the task list + * @param tasks + */ + private load() { + this.activiti.getTaskListFilters().subscribe( + (res: FilterModel[]) => { + res.forEach((filter) => { + this.filterObserver.next(filter); + }); + }, + (err) => { + console.log(err); + } + ); + } + + /** + * Pass the selected filter as next + * @param filter + */ + public selectFilter(filter: FilterModel) { + this.filterClick.emit(filter); + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css index 6979275ee7..7e9e64291f 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css @@ -3,7 +3,7 @@ } .activiti-label { - color: rgb(255,152,0); + font-weight: bolder; } .material-icons:hover { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html index f5fe224419..b6d28fa4d5 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html @@ -1,6 +1,6 @@ {{ 'TASK_DETAILS.LABELS.PEOPLE' | translate }} -
add
+
add
Add a people
@@ -16,4 +16,18 @@
{{ 'TASK_DETAILS.PEOPLE.NONE' | translate }} -
\ No newline at end of file + + + +

New User

+
+
+ + +
+
+
+ + +
+
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts index 46bcc4a2c6..c4e472b3b3 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts @@ -15,9 +15,11 @@ * limitations under the License. */ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; import { User } from '../models/user.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; declare let componentHandler: any; declare let __moduleName: string; @@ -35,6 +37,12 @@ export class ActivitiPeople implements OnInit { @Input() people: User [] = []; + @ViewChild('dialog') + dialog: any; + + private peopleObserver: Observer; + people$: Observable; + /** * Constructor * @param auth @@ -46,10 +54,31 @@ export class ActivitiPeople implements OnInit { if (translate) { translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); } + this.people$ = new Observable(observer => this.peopleObserver = observer).share(); } ngOnInit() { + this.people$.subscribe((user: User) => { + this.people.push(user); + }); + } + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + public add() { + alert('add people'); + + this.cancel(); + } + + public cancel() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } } } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html index 8963833316..fd7fdc6d62 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html @@ -1,19 +1,17 @@ -
-

{{ 'TASK_DETAILS.MESSAGES.NONE' | translate }}

-
+
{{ 'TASK_DETAILS.MESSAGES.NONE' | translate }}

{{taskDetails.name}}

- +
- +
- +
- +
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts index 7acaf89fb4..fff24fdde3 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnInit, OnChanges } from '@angular/core'; +import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { ActivitiTaskHeader } from './activiti-task-header.component'; @@ -35,16 +35,22 @@ declare let __moduleName: string; moduleId: __moduleName, templateUrl: './activiti-task-details.component.html', styleUrls: ['./activiti-task-details.component.css'], - providers: [ ActivitiTaskListService, FormService ], - directives: [ ActivitiTaskHeader, ActivitiPeople, ActivitiComments, ActivitiChecklist, ActivitiForm ], - pipes: [ AlfrescoPipeTranslate ] + providers: [ActivitiTaskListService, FormService], + directives: [ActivitiTaskHeader, ActivitiPeople, ActivitiComments, ActivitiChecklist, ActivitiForm], + pipes: [AlfrescoPipeTranslate] }) -export class ActivitiTaskDetails implements OnInit, OnChanges { +export class ActivitiTaskDetails implements OnInit { @Input() taskId: string; + @ViewChild('activiticomments') + activiticomments: any; + + @ViewChild('activitichecklist') + activitichecklist: any; + taskDetails: TaskDetailsModel; taskForm: FormModel; @@ -68,30 +74,29 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { ngOnInit() { if (this.taskId) { - this.activitiTaskList.getTaskDetails(this.taskId).subscribe( - (res: TaskDetailsModel) => { - this.taskDetails = res; - console.log(this.taskDetails); - } - ); + this.loadDetails(this.taskId); } } - ngOnChanges(change) { - this.loadDetails(this.taskId); - } - - loadDetails(id: string) { + loadDetails(taskId: string) { this.taskForm = null; this.taskPeople = []; - if (id) { - this.activitiTaskList.getTaskDetails(id).subscribe( + if (taskId) { + this.activitiTaskList.getTaskDetails(taskId).subscribe( (res: TaskDetailsModel) => { this.taskDetails = res; if (this.taskDetails && this.taskDetails.involvedPeople) { this.taskDetails.involvedPeople.forEach((user) => { this.taskPeople.push(new User(user.id, user.email, user.firstName, user.lastName)); }); + + if (this.activiticomments) { + this.activiticomments.load(this.taskDetails.id); + } + + if (this.activitichecklist) { + this.activitichecklist.load(this.taskDetails.id); + } } console.log(this.taskDetails); } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css index 61bded3cfd..20fbab0626 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css @@ -3,5 +3,5 @@ } .activiti-label { - color: rgb(255,152,0); + font-weight: bolder; } \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html index 3176503aee..4f932db173 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html @@ -1,15 +1,5 @@ - - -
+
{{ 'TASK_FILTERS.MESSAGES.NONE' | translate }}
+
-
{{ 'TASK_FILTERS.MESSAGES.NONE' | translate }}
diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts index 754196fdf5..e487dc46d8 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts @@ -32,6 +32,7 @@ describe('ActivitiTaskList', () => { let taskList: ActivitiTaskList; + /* let fakeGlobalFilter = { size: 2, total: 2, start: 0, data: [ @@ -45,6 +46,7 @@ describe('ActivitiTaskList', () => { } ] }; + */ let fakeGlobalTask = { size: 1, total: 12, start: 0, @@ -64,27 +66,49 @@ describe('ActivitiTaskList', () => { ] }; + /* + let fakeErrorTaskList = { error: 'wrong request' }; - - let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { - resolve(fakeGlobalFilter); - }); + */ let fakeGlobalTaskPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalTask); }); + /* + + let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalFilter); + }); + let fakeErrorTaskPromise = new Promise(function (resolve, reject) { reject(fakeErrorTaskList); - }); + });*/ beforeEach(() => { let activitiSerevice = new ActivitiTaskListService(null, null); taskList = new ActivitiTaskList(null, null, activitiSerevice); }); + it('should return the task list when the taskFilter is passed', (done) => { + spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + // spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.taskFilter = new FilterModel('name', false, 'icon', '', 'open', 'fake-assignee'); + + taskList.onSuccess.subscribe( () => { + expect(taskList.tasks).toBeDefined(); + expect(taskList.tasks.getRows().length).toEqual(2); + expect(taskList.tasks.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(taskList.tasks.getRows()[1].getValue('name')).toEqual('Nameless task'); + done(); + }); + + taskList.ngOnInit(); + }); + + /* it('should return the default filters', (done) => { spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); taskList.ngOnInit(); @@ -156,5 +180,6 @@ describe('ActivitiTaskList', () => { done(); }); }); + */ }); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts index 73f243e8ed..e7a84dd43f 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts @@ -20,8 +20,6 @@ import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipe import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { FilterModel } from '../models/filter.model'; -import { Observer } from 'rxjs/Observer'; -import { Observable } from 'rxjs/Observable'; declare let componentHandler: any; declare let __moduleName: string; @@ -38,20 +36,28 @@ declare let __moduleName: string; export class ActivitiTaskList implements OnInit { @Input() - data: DataTableAdapter; + taskFilter: FilterModel; + + @Input() + schemaColumn: any[] = [ + {type: 'text', key: 'id', title: 'Id'}, + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, + {type: 'text', key: 'formKey', title: 'Form Key', sortable: true}, + {type: 'text', key: 'created', title: 'Created', sortable: true} + ]; @Output() rowClick: EventEmitter = new EventEmitter(); - private filterObserver: Observer; + @Output() + onSuccess: EventEmitter = new EventEmitter(); - filter$: Observable; + data: DataTableAdapter; tasks: ObjectDataTableAdapter; - currentFilter: FilterModel; + currentTaskId: string; - filtersList: Observable; /** * Constructor * @param auth @@ -60,7 +66,6 @@ export class ActivitiTaskList implements OnInit { constructor(private auth: AlfrescoAuthenticationService, private translate: AlfrescoTranslationService, public activiti: ActivitiTaskListService) { - this.filter$ = new Observable(observer => this.filterObserver = observer).share(); if (translate) { translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); @@ -68,40 +73,47 @@ export class ActivitiTaskList implements OnInit { } ngOnInit() { - this.filtersList = this.activiti.getTaskListFilters().map(res => (res.data)); + this.data = new ObjectDataTableAdapter( + [], + this.schemaColumn + ); - this.filter$.subscribe((filter: FilterModel) => { - this.activiti.getTasks(filter).subscribe( - (res) => { - this.loadTasks(res.data); - }, (err) => { - console.error(err); - }); - }); + if (this.taskFilter) { + this.load(this.taskFilter); + } + } + + public load(filter: FilterModel) { + this.activiti.getTasks(filter).subscribe( + (res) => { + this.renderTasks(res.data); + this.onSuccess.emit('Task List loaded'); + }, (err) => { + console.error(err); + }); } /** * The method call the adapter data table component for render the task list * @param tasks */ - private loadTasks(tasks: any[]) { + private renderTasks(tasks: any[]) { tasks = this.optimizeTaskName(tasks); this.tasks = new ObjectDataTableAdapter(tasks, this.data.getColumns()); } /** - * Pass the selected filter as next - * @param filter + * Check if the tasks list is empty + * @returns {ObjectDataTableAdapter|boolean} */ - public selectFilter(filter: FilterModel) { - this.currentFilter = filter; - this.filterObserver.next(filter); - } - isTaskListEmpty(): boolean { return this.tasks && this.tasks.getRows().length === 0; } + /** + * Emit the event rowClick passing the current task id when the row is clicked + * @param event + */ onRowClick(event: DataRowEvent) { let item = event; this.currentTaskId = item.value.getValue('id'); diff --git a/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts index 5aa422c1a3..c7c4053d4a 100644 --- a/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts +++ b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts @@ -29,11 +29,11 @@ export class FilterModel { icon: string; filter: FilterParamsModel; - constructor(name: string, recent: boolean, icon: string, state: string, assignment: string) { + constructor(name: string, recent: boolean, icon: string, query: string, state: string, assignment: string) { this.name = name; this.recent = recent; this.icon = icon; - this.filter = new FilterParamsModel(name, state, assignment); + this.filter = new FilterParamsModel(query, state, assignment); } } @@ -49,8 +49,8 @@ export class FilterParamsModel { state: string; assignment: string; - constructor(name: string, state: string, assignment: string) { - this.name = name; + constructor(query: string, state: string, assignment: string) { + this.name = query; this.state = state; this.assignment = assignment; } diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts index 159fbf8b98..0a52b56b39 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts @@ -23,7 +23,7 @@ import { HTTP_PROVIDERS } from '@angular/http'; declare let AlfrescoApi: any; declare let jasmine: any; -describe('AlfrescoUploadService', () => { +describe('ActivitiTaskListService', () => { let service, options: any; options = { @@ -72,11 +72,9 @@ describe('AlfrescoUploadService', () => { let filters = service.getTaskListFilters(); filters.subscribe(res => { expect(res).toBeDefined(); - expect(res.size).toEqual(2); - expect(res.total).toEqual(2); - expect(res.data.length).toEqual(2); - expect(res.data[0].name).toEqual('FakeInvolvedTasks'); - expect(res.data[1].name).toEqual('FakeMyTasks'); + expect(res.length).toEqual(2); + expect(res[0].name).toEqual('FakeInvolvedTasks'); + expect(res[1].name).toEqual('FakeMyTasks'); done(); }); diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts index eb9ba7ea3d..96f5f08eda 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -37,8 +37,15 @@ export class ActivitiTaskListService { */ getTaskListFilters(): Observable { return Observable.fromPromise(this.callApiTaskFilters()) - .map((res: Response) => { - return res.json(); + .map(res => res.json()) + .map((response: any) => { + let filters: FilterModel[] = []; + response.data.forEach((filter) => { + let filterModel = new FilterModel(filter.name, filter.recent, filter.icon, + filter.filter.name, filter.filter.state, filter.filter.assignment); + filters.push(filterModel); + }); + return filters; }) .catch(this.handleError); } @@ -52,7 +59,7 @@ export class ActivitiTaskListService { // data.filterId = filter.id; // data.filter = filter.filter; data = filter.filter; - data.text = filter.filter.name; + // data.text = filter.filter.name; data = JSON.stringify(data); @@ -87,17 +94,20 @@ export class ActivitiTaskListService { .catch(this.handleError); } - addTaskComment(id: string, message: string): Observable { + addTaskComment(id: string, message: string): Observable { return Observable.fromPromise(this.callApiAddTaskComment(id, message)) .map(res => res.json()) - .map((response: any) => { - let comments: Comment[] = []; - response.data.forEach((comment) => { - let user = new User( - comment.createdBy.id, comment.createdBy.email, comment.createdBy.firstName, comment.createdBy.lastName); - comments.push(new Comment(comment.id, comment.message, comment.created, user)); - }); - return comments; + .map((response: Comment) => { + return new Comment(response.id, response.message, response.created, response.createdBy); + }) + .catch(this.handleError); + } + + addTask(task: TaskDetailsModel): Observable { + return Observable.fromPromise(this.callApiAddTask(task)) + .map(res => res.json()) + .map((response: TaskDetailsModel) => { + return new TaskDetailsModel(response); }) .catch(this.handleError); } @@ -185,6 +195,19 @@ export class ActivitiTaskListService { .post(url, body, options).toPromise(); } + private callApiAddTask(task: TaskDetailsModel) { + let url = `${this.basePath}/api/enterprise/tasks/${task.parentTaskId}/checklist`; + let headers = new Headers({ + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache' + }); + let body = JSON.stringify(task); + let options = new RequestOptions({headers: headers}); + + return this.http + .post(url, body, options).toPromise(); + } + private callApiTaskChecklist(id: string) { let url = `${this.basePath}/api/enterprise/tasks/${id}/checklist`; let headers = new Headers({ From 48a2a4c1fd651a0be8ace1666075299c37094577 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 10:03:12 +0100 Subject: [PATCH 06/15] Basic documentation --- .../ng2-activiti-tasklist/README.md | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/ng2-components/ng2-activiti-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md index b2226ddc09..6f6d8a2a15 100644 --- a/ng2-components/ng2-activiti-tasklist/README.md +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -1 +1,150 @@ # Activiti Task List Component for Angular 2 + +## Prerequisites + +Before you start using this development framework, make sure you have installed all required software and done all the +necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng2-components/blob/master/PREREQUISITES.md). + +## Install + +```sh +npm install --save ng2-activiti-tasklist +``` + +### Dependencies + +You must separately install the following libraries for your application: + +- [ng2-translate](https://github.com/ocombe/ng2-translate) +- [ng2-alfresco-core](https://www.npmjs.com/package/ng2-alfresco-core) +- [ng2-alfresco-datatable](https://www.npmjs.com/package/ng2-alfresco-datatable) + + +```sh +npm install --save ng2-translate ng2-alfresco-core ng2-alfresco-datatable +``` + +#### Material Design Lite + +The style of this component is based on [material design](https://getmdl.io/), so if you want to visualize it correctly you have to add the material +design dependency to your project: + +```sh +npm install --save material-design-icons material-design-lite +``` + +Also make sure you include these dependencies in your `index.html` file: + +```html + + + + +``` + +## Basic usage example Activiti Task List +The component shows the list of all the tasks filter by the +FilterModel passed in input. +```html + +``` + +#### Events +**onSuccess**: The event is emitted when the task list is loaded +**rowClick**: The event is emitted when the task in the list is +clicked
+ +#### Options + +**taskFilter**: { FilterModel } required) FilterModel object that +is passed to the task list API to filter the task list. +Example: +```json +{ + "id": 4, + "name": "Involved Tasks", + "recent": false, + "icon": "glyphicon-align-left", + "filter": { + "sort": "created-desc", + "name": "", + "state": "open", + "assignment": "involved" + } +} +``` +**schemaColumn**: { any[] } optional) JSON object that represent +the number and the type of the columns that you want show +Example: +```json +[ + {type: 'text', key: 'id', title: 'Id'}, + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, + {type: 'text', key: 'formKey', title: 'Form Key', sortable: true}, + {type: 'text', key: 'created', title: 'Created', sortable: true} +] +``` + +## Basic usage example Activiti Task Details +The component shows the details of the task id passed in input +```html + +``` + +#### Events +No events + +#### Options + +**taskId**: { string } required) The id of the task details that we +are asking for. + +## Basic usage example Activiti Filter +The component shows all the available filters. + +```html + +``` + +#### Events +**filterClick**: The event is emitted when the filter in the list is + clicked + +#### Options +No options + +## Build from sources + +Alternatively you can build component from sources with the following commands: + +```sh +npm install +npm run build +``` + +### Build the files and keep watching for changes + +```sh +$ npm run build:w +``` + +### Running unit tests + +```sh +npm test +``` + +### Running unit tests in browser + +```sh +npm test-browser +``` + +This task rebuilds all the code, runs tslint, license checks and other quality check tools +before performing unit testing. + +### Code coverage + +```sh +npm run coverage +``` From 421b21017a183774720aa5d84a753c377a9f41f3 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 11:11:58 +0100 Subject: [PATCH 07/15] Fix unused variable --- .../app/components/activiti/activiti-demo.component.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts index 0ac5478bd0..fd62028105 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -19,9 +19,6 @@ import { Component, OnInit, AfterViewChecked, ViewChild } from '@angular/core'; import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist'; import { ActivitiForm } from 'ng2-activiti-form'; -import { ObjectDataTableAdapter, ObjectDataColumn } from 'ng2-alfresco-datatable'; - - declare let __moduleName: string; declare var componentHandler; @@ -48,9 +45,6 @@ export class ActivitiDemoComponent implements OnInit, AfterViewChecked { taskFilter: any; - constructor() { - } - setChoice($event) { this.currentChoice = $event.target.value; } From 16eec259c57d08b9eb627f60a031faf94dcc6bea Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 11:12:28 +0100 Subject: [PATCH 08/15] Unit test tasklist --- .../activiti-tasklist.component.spec.ts | 147 ++++++------------ .../components/activiti-tasklist.component.ts | 6 +- 2 files changed, 55 insertions(+), 98 deletions(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts index e487dc46d8..a03bfce057 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts @@ -26,28 +26,13 @@ import { ActivitiTaskList } from './activiti-tasklist.component'; import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; import { FilterModel } from '../models/filter.model'; import { Observable } from 'rxjs/Rx'; +import { ObjectDataRow, DataRowEvent } from 'ng2-alfresco-datatable'; describe('ActivitiTaskList', () => { let taskList: ActivitiTaskList; - /* - let fakeGlobalFilter = { - size: 2, total: 2, start: 0, - data: [ - { - id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} - }, - { - id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} - } - ] - }; - */ - let fakeGlobalTask = { size: 1, total: 12, start: 0, data: [ @@ -66,39 +51,54 @@ describe('ActivitiTaskList', () => { ] }; - /* - - let fakeErrorTaskList = { - error: 'wrong request' - }; - */ - let fakeGlobalTaskPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalTask); }); - /* - - let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { - resolve(fakeGlobalFilter); - }); + let fakeErrorTaskList = { + error: 'wrong request' + }; let fakeErrorTaskPromise = new Promise(function (resolve, reject) { reject(fakeErrorTaskList); - });*/ + }); beforeEach(() => { let activitiSerevice = new ActivitiTaskListService(null, null); taskList = new ActivitiTaskList(null, null, activitiSerevice); }); - it('should return the task list when the taskFilter is passed', (done) => { + it('should use the default schemaColumn as default', () => { + taskList.ngOnInit(); + expect(taskList.schemaColumn).toBeDefined(); + expect(taskList.schemaColumn.length).toEqual(4); + }); + + it('should use the schemaColumn passed in input', () => { + taskList.schemaColumn = [ + {type: 'text', key: 'fake-id', title: 'Name'} + ]; + + taskList.ngOnInit(); + expect(taskList.schemaColumn).toBeDefined(); + expect(taskList.schemaColumn.length).toEqual(1); + }); + + it('should return an empty task list when the taskFilter is not passed', () => { + taskList.ngOnInit(); + expect(taskList.tasks).toBeUndefined(); + expect(taskList.isTaskListEmpty()).toBeTruthy(); + }); + + it('should return the filtered task list when the taskFilter is passed', (done) => { spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - // spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); taskList.taskFilter = new FilterModel('name', false, 'icon', '', 'open', 'fake-assignee'); - taskList.onSuccess.subscribe( () => { + taskList.onSuccess.subscribe( (res) => { + expect(res).toBeDefined(); + expect(res).toEqual('Task List loaded'); expect(taskList.tasks).toBeDefined(); + expect(taskList.isTaskListEmpty()).not.toBeTruthy(); expect(taskList.tasks.getRows().length).toEqual(2); expect(taskList.tasks.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); expect(taskList.tasks.getRows()[1].getValue('name')).toEqual('Nameless task'); @@ -108,78 +108,31 @@ describe('ActivitiTaskList', () => { taskList.ngOnInit(); }); - /* - it('should return the default filters', (done) => { - spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); - taskList.ngOnInit(); - - taskList.filtersList.subscribe((res: any) => { - expect(res).toBeDefined(); - expect(res.length).toEqual(2); - expect(res[0].name).toEqual('FakeInvolvedTasks'); - expect(res[1].name).toEqual('FakeMyTasks'); - done(); - }); - }); - - it('should subscribe to Filter when a filter is selected', (done) => { - let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); - taskList.filter$.subscribe((filter: FilterModel) => { - expect(filter).toBe(filterModel); - done(); - }); - taskList.selectFilter(filterModel); - }); - - it('should return the tasks when a filter is selected', (done) => { - spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); - taskList.ngOnInit(); - - let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); - taskList.selectFilter(filterModel); - - taskList.activiti.getTasks(filterModel).subscribe( - (res) => { - expect(res).toBeDefined(); - done(); - }); - }); - it('should throw an exception when the response is wrong', (done) => { spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeErrorTaskPromise)); - spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.taskFilter = new FilterModel('name', false, 'icon', '', 'open', 'fake-assignee'); + + taskList.onError.subscribe( (err) => { + expect(err).toBeDefined(); + expect(err).toEqual('Error to load a tasks list'); + done(); + }); + taskList.ngOnInit(); - - let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); - taskList.selectFilter(filterModel); - - taskList.activiti.getTasks(filterModel).subscribe( - (res) => { - expect(res).toBeUndefined(); - }, - (err: any) => { - expect(err).toBeDefined(); - expect(err.error).toEqual('wrong request'); - done(); - }); }); - it('should optimize the task name when are empty or exceed 50 characters', (done) => { - spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); - taskList.ngOnInit(); + it('should emit row click event', (done) => { + let row = new ObjectDataRow({ + id: 999 + }); + let rowEvent = {value: row}; - let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); - taskList.selectFilter(filterModel); + taskList.rowClick.subscribe(taskId => { + expect(taskId).toEqual(999); + done(); + }); - taskList.activiti.getTasks(filterModel).subscribe( - (res) => { - expect(res.data[0].name).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); - expect(res.data[1].name).toEqual('Nameless task'); - done(); - }); + taskList.onRowClick(rowEvent); }); - */ }); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts index e7a84dd43f..7e6dc87b7c 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts @@ -52,6 +52,9 @@ export class ActivitiTaskList implements OnInit { @Output() onSuccess: EventEmitter = new EventEmitter(); + @Output() + onError: EventEmitter = new EventEmitter(); + data: DataTableAdapter; tasks: ObjectDataTableAdapter; @@ -90,6 +93,7 @@ export class ActivitiTaskList implements OnInit { this.onSuccess.emit('Task List loaded'); }, (err) => { console.error(err); + this.onError.emit('Error to load a tasks list'); }); } @@ -107,7 +111,7 @@ export class ActivitiTaskList implements OnInit { * @returns {ObjectDataTableAdapter|boolean} */ isTaskListEmpty(): boolean { - return this.tasks && this.tasks.getRows().length === 0; + return this.tasks === undefined || (this.tasks && this.tasks.getRows() && this.tasks.getRows().length === 0); } /** From e94c0b0e411278f7a3d1678880a0d806404a6270 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 11:12:41 +0100 Subject: [PATCH 09/15] Unit test task filters --- .../activiti-filters.component.spec.ts | 96 +++++++++++++++++++ .../components/activiti-filters.component.ts | 9 ++ 2 files changed, 105 insertions(+) create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts new file mode 100644 index 0000000000..0de606f054 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts @@ -0,0 +1,96 @@ +/*! + * @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 { + it, + describe, + expect, + beforeEach +} from '@angular/core/testing'; + +import { ActivitiFilters } from './activiti-filters.component'; +import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; +import { Observable } from 'rxjs/Rx'; +import { FilterModel } from '../models/filter.model'; + +describe('ActivitiFilters', () => { + + let filterList: ActivitiFilters; + + let fakeGlobalFilter = []; + fakeGlobalFilter.push(new FilterModel('FakeInvolvedTasks', false, 'glyphicon-align-left', '', 'open', 'fake-involved')); + fakeGlobalFilter.push(new FilterModel('FakeMyTasks', false, 'glyphicon-align-left', '', 'open', 'fake-assignee')); + + let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalFilter); + }); + + let fakeErrorFilterList = { + error: 'wrong request' + }; + + let fakeErrorFilterPromise = new Promise(function (resolve, reject) { + reject(fakeErrorFilterList); + }); + + beforeEach(() => { + let activitiService = new ActivitiTaskListService(null); + filterList = new ActivitiFilters(null, null, activitiService); + }); + + it('should return the filter task list', (done) => { + spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + + filterList.onSuccess.subscribe( (res) => { + expect(res).toBeDefined(); + expect(res).toEqual('Filter task list loaded'); + expect(filterList.filters).toBeDefined(); + expect(filterList.filters.length).toEqual(2); + expect(filterList.filters[0].name).toEqual('FakeInvolvedTasks'); + expect(filterList.filters[1].name).toEqual('FakeMyTasks'); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an error with a bad response', (done) => { + spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); + + filterList.onError.subscribe( (err) => { + expect(err).toBeDefined(); + expect(err).toEqual('Error to load a task filter list'); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an event when a filter is selected', (done) => { + let currentFilter = new FilterModel('FakeInvolvedTasks', false, 'glyphicon-align-left', '', 'open', 'fake-involved'); + + filterList.filterClick.subscribe((filter: FilterModel) => { + expect(filter).toBeDefined(); + expect(filter).toEqual(currentFilter); + expect(filterList.currentFilter).toEqual(currentFilter); + done(); + }); + + filterList.selectFilter(currentFilter); + }); + +}); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts index 26d625e513..68228880b8 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts @@ -38,6 +38,12 @@ export class ActivitiFilters implements OnInit { @Output() filterClick: EventEmitter = new EventEmitter(); + @Output() + onSuccess: EventEmitter = new EventEmitter(); + + @Output() + onError: EventEmitter = new EventEmitter(); + private filterObserver: Observer; filter$: Observable; @@ -77,9 +83,11 @@ export class ActivitiFilters implements OnInit { res.forEach((filter) => { this.filterObserver.next(filter); }); + this.onSuccess.emit('Filter task list loaded'); }, (err) => { console.log(err); + this.onError.emit('Error to load a task filter list'); } ); } @@ -89,6 +97,7 @@ export class ActivitiFilters implements OnInit { * @param filter */ public selectFilter(filter: FilterModel) { + this.currentFilter = filter; this.filterClick.emit(filter); } } From ff95dd57cd03dd7cb8a296f6c9e3b1e7f02d62cf Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 11:12:48 +0100 Subject: [PATCH 10/15] Unit test task list service --- .../activiti-tasklist.service.spec.ts | 309 +++++++++++++----- .../src/services/activiti-tasklist.service.ts | 92 ++++-- 2 files changed, 278 insertions(+), 123 deletions(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts index 0a52b56b39..357ff8d23d 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts @@ -19,21 +19,79 @@ import { it, describe, inject, beforeEach, beforeEachProviders } from '@angular/ import { ActivitiTaskListService } from './activiti-tasklist.service'; import { AlfrescoSettingsService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; import { HTTP_PROVIDERS } from '@angular/http'; +import { TaskDetailsModel } from '../models/task-details.model'; +import { Comment } from '../models/comment.model'; declare let AlfrescoApi: any; declare let jasmine: any; describe('ActivitiTaskListService', () => { - let service, options: any; + let service: any; - options = { - host: 'fakehost', - url: '/some/cool/url', - baseUrlPath: 'fakebasepath', - formFields: { - siteid: 'fakeSite', - containerid: 'fakeFolder' - } + let fakeFilters = { + size: 2, total: 2, start: 0, + data: [ + { + id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} + }, + { + id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} + } + ] + }; + + let fakeFilter = { + page: 2, filterId: 2, appDefinitionId: null, + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee' } + }; + + let fakeUser = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' }; + + let fakeTaskList = { + size: 1, total: 1, start: 0, + data: [ + { + id: 1, name: 'FakeNameTask', description: null, category: null, + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + } + ] + }; + + let fakeErrorTaskList = { + error: 'wrong request' + }; + + let fakeTaskDetails = {id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser }; + + let fakeTasksComment = { + size: 2, total: 2, start: 0, + data: [ + { + id: 1, message: 'fake-message-1', created: '', createdBy: fakeUser + }, + { + id: 2, message: 'fake-message-2', created: '', createdBy: fakeUser + } + ] + }; + + let fakeTasksChecklist = { + size: 1, total: 1, start: 0, + data: [ + { + id: 1, name: 'FakeCheckTask1', description: null, category: null, + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + }, + { + id: 2, name: 'FakeCheckTask2', description: null, category: null, + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + } + ] }; beforeEachProviders(() => { @@ -55,67 +113,37 @@ describe('ActivitiTaskListService', () => { }); it('should return the task list filters', (done) => { - let fakeFilter = { - size: 2, total: 2, start: 0, - data: [ - { - id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} - }, - { - id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} - } - ] - }; - - let filters = service.getTaskListFilters(); - filters.subscribe(res => { - expect(res).toBeDefined(); - expect(res.length).toEqual(2); - expect(res[0].name).toEqual('FakeInvolvedTasks'); - expect(res[1].name).toEqual('FakeMyTasks'); - done(); - }); + service.getTaskListFilters().subscribe( + (res) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(2); + expect(res[0].name).toEqual('FakeInvolvedTasks'); + expect(res[1].name).toEqual('FakeMyTasks'); + done(); + } + ); jasmine.Ajax.requests.mostRecent().respondWith({ 'status': 200, contentType: 'application/json', - responseText: JSON.stringify(fakeFilter) + responseText: JSON.stringify(fakeFilters) }); }); it('should return the task list filtered', (done) => { - let fakeTaskList = { - size: 1, total: 1, start: 0, - data: [ - { - id: 1, name: 'FakeNameTask', description: null, category: null, - assignee: { - id: 1, - firstName: null, - lastName: 'Fake Admin', - email: 'fake-admin' - }, - created: '2016-07-15T11:19:17.440+0000' - } - ] - }; - - let fakeFilter = { - page: 2, filterId: 2, appDefinitionId: null, - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} - }; - - let taskList = service.getTasks(fakeFilter); - taskList.subscribe(res => { - expect(res).toBeDefined(); - expect(res.size).toEqual(1); - expect(res.total).toEqual(1); - expect(res.data.length).toEqual(1); - expect(res.data[0].name).toEqual('FakeNameTask'); - done(); - }); + service.getTasks(fakeFilter).subscribe( + res => { + expect(res).toBeDefined(); + expect(res.size).toEqual(1); + expect(res.total).toEqual(1); + expect(res.data.length).toEqual(1); + expect(res.data[0].name).toEqual('FakeNameTask'); + expect(res.data[0].assignee.email).toEqual('fake-email@dom.com'); + expect(res.data[0].assignee.firstName).toEqual('firstName'); + expect(res.data[0].assignee.lastName).toEqual('lastName'); + done(); + } + ); jasmine.Ajax.requests.mostRecent().respondWith({ 'status': 200, @@ -124,36 +152,141 @@ describe('ActivitiTaskListService', () => { }); }); - it('should throw an exception when the response is wrong', (done) => { - let fakeTaskList = { - error: 'wrong request' - }; - - let fakeFilter = { - page: 2, filterId: 2, appDefinitionId: null, - wrongfilter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} - }; - - let fakePromise = new Promise(function (resolve, reject) { - reject(fakeTaskList); - }); - spyOn(service, 'callApiTasksFiltered').and.returnValue(fakePromise); - - let taskList = service.getTasks(fakeFilter); - - service.getTasks(fakeFilter).subscribe((res) => { - let tasks = res.data; - service.loadTasks(tasks); - }); - taskList.subscribe( + it('should throw an exception when the response is wrong', () => { + service.getTasks(fakeFilter).subscribe( (res) => { - }, (err: any) => { expect(err).toBeDefined(); - expect(err.error).toEqual('wrong request'); - done(); - }); + expect(err._body).toEqual('{"error":"wrong request"}'); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 404, + contentType: 'application/json', + responseText: JSON.stringify(fakeErrorTaskList) + }); }); + it('should return the task details ', (done) => { + service.getTaskDetails(999).subscribe( + (res: TaskDetailsModel) => { + expect(res).toBeDefined(); + expect(res.id).toEqual('999'); + expect(res.name).toEqual('fake-task-name'); + expect(res.formKey).toEqual('99'); + expect(res.assignee).toBeDefined(); + expect(res.assignee.email).toEqual('fake-email@dom.com'); + expect(res.assignee.firstName).toEqual('firstName'); + expect(res.assignee.lastName).toEqual('lastName'); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTaskDetails) + }); + }); + + it('should return the tasks comments ', (done) => { + service.getTaskComments(999).subscribe( + (res: Comment[]) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(2); + expect(res[0].message).toEqual('fake-message-1'); + expect(res[1].message).toEqual('fake-message-2'); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTasksComment) + }); + }); + + it('should return the tasks checklists ', (done) => { + service.getTaskChecklist(999).subscribe( + (res: TaskDetailsModel[]) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(2); + expect(res[0].name).toEqual('FakeCheckTask1'); + expect(res[0].assignee.email).toEqual('fake-email@dom.com'); + expect(res[0].assignee.firstName).toEqual('firstName'); + expect(res[0].assignee.lastName).toEqual('lastName'); + expect(res[1].name).toEqual('FakeCheckTask2'); + expect(res[1].assignee.email).toEqual('fake-email@dom.com'); + expect(res[1].assignee.firstName).toEqual('firstName'); + expect(res[0].assignee.lastName).toEqual('lastName'); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTasksChecklist) + }); + }); + + it('should add a task ', (done) => { + let taskFake = new TaskDetailsModel({ + id: '', name: 'FakeNameTask', description: null, category: null, + assignee: fakeUser, + created: '' + }); + + service.addTask(taskFake).subscribe( + (res: TaskDetailsModel) => { + expect(res).toBeDefined(); + expect(res.id).not.toEqual(''); + expect(res.name).toEqual('FakeNameTask'); + expect(res.created).not.toEqual(''); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify({ + id: '777', name: 'FakeNameTask', description: null, category: null, + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + }) + }); + }); + + it('should add a comment task ', (done) => { + + service.addTaskComment(999, 'fake-comment-message').subscribe( + (res: Comment) => { + expect(res).toBeDefined(); + expect(res.id).not.toEqual(''); + expect(res.message).toEqual('fake-comment-message'); + expect(res.created).not.toEqual(''); + expect(res.createdBy.email).toEqual('fake-email@dom.com'); + expect(res.createdBy.firstName).toEqual('firstName'); + expect(res.createdBy.lastName).toEqual('lastName'); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify({ + id: '111', message: 'fake-comment-message', + createdBy: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + }) + }); + }); + + + }); diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts index 96f5f08eda..5f9e4bb6fa 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -20,6 +20,7 @@ import { AlfrescoSettingsService } from 'ng2-alfresco-core'; import { Http, Headers, RequestOptions, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { FilterModel } from '../models/filter.model'; +import { FilterParamsModel } from '../models/filter.model'; import { Comment } from '../models/comment.model'; import { User } from '../models/user.model'; @@ -51,25 +52,24 @@ export class ActivitiTaskListService { } /** - * Retrive all the tasks created in activiti + * Retrive all the tasks filtered by filterModel + * @param filter - FilterModel * @returns {any} */ getTasks(filter: FilterModel): Observable { - let data: any = {}; - // data.filterId = filter.id; - // data.filter = filter.filter; - data = filter.filter; - // data.text = filter.filter.name; - data = JSON.stringify(data); - - return Observable.fromPromise(this.callApiTasksFiltered(data)) + return Observable.fromPromise(this.callApiTasksFiltered(filter.filter)) .map((res: Response) => { return res.json(); }) .catch(this.handleError); } + /** + * Retrive all the task details + * @param id - taskId + * @returns {} + */ getTaskDetails(id: string): Observable { return Observable.fromPromise(this.callApiTaskDetails(id)) .map(res => res.json()) @@ -79,6 +79,11 @@ export class ActivitiTaskListService { .catch(this.handleError); } + /** + * Retrive all the task's comments + * @param id - taskId + * @returns {} + */ getTaskComments(id: string): Observable { return Observable.fromPromise(this.callApiTaskComments(id)) .map(res => res.json()) @@ -94,24 +99,11 @@ export class ActivitiTaskListService { .catch(this.handleError); } - addTaskComment(id: string, message: string): Observable { - return Observable.fromPromise(this.callApiAddTaskComment(id, message)) - .map(res => res.json()) - .map((response: Comment) => { - return new Comment(response.id, response.message, response.created, response.createdBy); - }) - .catch(this.handleError); - } - - addTask(task: TaskDetailsModel): Observable { - return Observable.fromPromise(this.callApiAddTask(task)) - .map(res => res.json()) - .map((response: TaskDetailsModel) => { - return new TaskDetailsModel(response); - }) - .catch(this.handleError); - } - + /** + * Retrive all the task's checklist + * @param id - taskId + * @returns {TaskDetailsModel} + */ getTaskChecklist(id: string): Observable { return Observable.fromPromise(this.callApiTaskChecklist(id)) .map(res => res.json()) @@ -125,19 +117,52 @@ export class ActivitiTaskListService { .catch(this.handleError); } + /** + * Add a task + * @param task - TaskDetailsModel + * @returns {TaskDetailsModel} + */ + addTask(task: TaskDetailsModel): Observable { + return Observable.fromPromise(this.callApiAddTask(task)) + .map(res => res.json()) + .map((response: TaskDetailsModel) => { + return new TaskDetailsModel(response); + }) + .catch(this.handleError); + } + + /** + * Add a comment to a task + * @param id - taskId + * @param message - content of the comment + * @returns {Comment} + */ + addTaskComment(id: string, message: string): Observable { + return Observable.fromPromise(this.callApiAddTaskComment(id, message)) + .map(res => res.json()) + .map((response: Comment) => { + return new Comment(response.id, response.message, response.created, response.createdBy); + }) + .catch(this.handleError); + } + + /** + * Make the task completed + * @param id - taskId + * @returns {TaskDetailsModel} + */ completeTask(id: string): Observable { return Observable.fromPromise(this.callApiCompleteTask(id)) .catch(this.handleError); } - private callApiTasksFiltered(data: Object) { - let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/api/enterprise/tasks/query'; - // let url = 'http://localhost:9999/activiti-app/app/rest/filter/tasks'; + private callApiTasksFiltered(filter: FilterParamsModel) { + let data = JSON.stringify(filter); + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/query`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' }); - // let body = JSON.stringify(data); let options = new RequestOptions({headers: headers}); return this.http @@ -145,8 +170,7 @@ export class ActivitiTaskListService { } private callApiTaskFilters() { - let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/api/enterprise/filters/tasks'; - // let url = 'http://localhost:9999/activiti-app/app/rest/filters/tasks'; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/filters/tasks`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' @@ -159,7 +183,6 @@ export class ActivitiTaskListService { private callApiTaskDetails(id: string) { let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${id}`; - // let url = 'http://localhost:9999/activiti-app/app/rest/tasks/' + id; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' @@ -222,7 +245,6 @@ export class ActivitiTaskListService { private callApiCompleteTask(id: string) { let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${id}/action/complete`; - // let url = `http://localhost:9999/activiti-app/app/rest/tasks/${id}/action/complete`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' From 15e1a33be1ed9f28e7d147abb9634ca3d4c918ce Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 11:38:23 +0100 Subject: [PATCH 11/15] Add complete API unit test --- .../activiti-tasklist.service.spec.ts | 19 ++++++++++++++++++- .../src/services/activiti-tasklist.service.ts | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts index 357ff8d23d..eb5c154dd1 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts @@ -158,7 +158,7 @@ describe('ActivitiTaskListService', () => { }, (err: any) => { expect(err).toBeDefined(); - expect(err._body).toEqual('{"error":"wrong request"}'); + expect(err.json().error).toEqual('wrong request'); } ); @@ -288,5 +288,22 @@ describe('ActivitiTaskListService', () => { }); + it('should complete the task ', (done) => { + + service.completeTask(999).subscribe( + (res: any) => { + expect(res).toBeDefined(); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify({}) + }); + }); + + }); diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts index 5f9e4bb6fa..8d646dddae 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -153,6 +153,7 @@ export class ActivitiTaskListService { */ completeTask(id: string): Observable { return Observable.fromPromise(this.callApiCompleteTask(id)) + .map(res => res.json()) .catch(this.handleError); } From 74c205ec115abf6ee338e3d2dc51a2aaad35ac8c Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 12:03:37 +0100 Subject: [PATCH 12/15] Fixed problem after rebase --- .../src/components/activiti-filters.component.spec.ts | 2 +- .../src/services/activiti-tasklist.service.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts index 0de606f054..41528c026d 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts @@ -48,7 +48,7 @@ describe('ActivitiFilters', () => { }); beforeEach(() => { - let activitiService = new ActivitiTaskListService(null); + let activitiService = new ActivitiTaskListService(null, null); filterList = new ActivitiFilters(null, null, activitiService); }); diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts index 8d646dddae..9ac14799b3 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -195,7 +195,7 @@ export class ActivitiTaskListService { } private callApiTaskComments(id: string) { - let url = `${this.basePath}/api/enterprise/tasks/${id}/comments`; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${id}/comments`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' @@ -207,7 +207,7 @@ export class ActivitiTaskListService { } private callApiAddTaskComment(id: string, message: string) { - let url = `${this.basePath}/api/enterprise/tasks/${id}/comments`; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${id}/comments`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' @@ -220,7 +220,7 @@ export class ActivitiTaskListService { } private callApiAddTask(task: TaskDetailsModel) { - let url = `${this.basePath}/api/enterprise/tasks/${task.parentTaskId}/checklist`; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${task.parentTaskId}/checklist`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' @@ -233,7 +233,7 @@ export class ActivitiTaskListService { } private callApiTaskChecklist(id: string) { - let url = `${this.basePath}/api/enterprise/tasks/${id}/checklist`; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + `/api/enterprise/tasks/${id}/checklist`; let headers = new Headers({ 'Content-Type': 'application/json', 'Cache-Control': 'no-cache' From 186032afb47eb9c6d0782503ee61cfe8fc8f038a Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 14:09:57 +0100 Subject: [PATCH 13/15] Fixed BPM path to using the real API --- .../src/services/AlfrescoSettingsService.service.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts index 918734a735..d606e8c27a 100644 --- a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts @@ -27,7 +27,6 @@ export class AlfrescoSettingsService { static DEFAULT_BPM_CONTEXT_PATH: string = '/activiti-app'; static DEFAULT_ECM_BASE_API_PATH: string = '/api/-default-/public/alfresco/versions/1'; - static DEFAULT_BPM_BASE_API_PATH: string = '/app'; private _ecmHost: string = AlfrescoSettingsService.DEFAULT_ECM_ADDRESS; private _bpmHost: string = AlfrescoSettingsService.DEFAULT_BPM_ADDRESS; @@ -36,7 +35,6 @@ export class AlfrescoSettingsService { private _bpmContextPath = AlfrescoSettingsService.DEFAULT_BPM_CONTEXT_PATH; private _apiECMBasePath: string = AlfrescoSettingsService.DEFAULT_ECM_BASE_API_PATH; - private _apiBPMBasePath: string = AlfrescoSettingsService.DEFAULT_BPM_BASE_API_PATH; private providers: string[] = ['ECM', 'BPM']; @@ -57,7 +55,7 @@ export class AlfrescoSettingsService { } public getBPMApiBaseUrl(): string { - return this._bpmHost + this._bpmContextPath + this._apiBPMBasePath; + return this._bpmHost + this._bpmContextPath; } public getECMApiBaseUrl(): string { From e35b04802251c19e3c9220c7df15467983e79c6d Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 14:43:13 +0100 Subject: [PATCH 14/15] Hard coded path for the web activiti API --- .../src/services/AlfrescoAuthenticationBPM.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthenticationBPM.service.ts b/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthenticationBPM.service.ts index 5c5a316fc6..efce19319c 100644 --- a/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthenticationBPM.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthenticationBPM.service.ts @@ -75,7 +75,7 @@ export class AlfrescoAuthenticationBPM extends AlfrescoAuthenticationBase implem } private apiActivitiLogin(username: string, password: string) { - let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/authentication'; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/app/authentication'; let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }); @@ -91,7 +91,7 @@ export class AlfrescoAuthenticationBPM extends AlfrescoAuthenticationBase implem } private apiActivitiLogout() { - let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/logout'; + let url = this.alfrescoSettingsService.getBPMApiBaseUrl() + '/app/logout'; return this.http.get(url).toPromise(); } From 4c2f12f821eb36e8a230ca0d38c3183412d223b0 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Fri, 29 Jul 2016 14:43:32 +0100 Subject: [PATCH 15/15] Fixed onInit problem --- .../app/components/activiti/activiti-demo.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts index fd62028105..f14d1565ad 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -57,7 +57,8 @@ export class ActivitiDemoComponent implements OnInit, AfterViewChecked { return this.currentChoice === 'task-list'; } - ngOnInit() { + constructor() { + console.log('Activiti demo component'); this.schemaColumn = [ {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true} // {type: 'text', key: 'created', title: 'Created', sortable: true}