diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html index 08cf0aca94..fd462fa8bd 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -19,6 +19,7 @@
Task Filters +
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 27dc8394a4..cc89a8e2b8 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -20,7 +20,8 @@ import { ALFRESCO_TASKLIST_DIRECTIVES, AppDefinitionRepresentationModel, FilterRepresentationModel, UserTaskFilterRepresentationModel, - ActivitiApps + ActivitiApps, + ActivitiTaskList } from 'ng2-activiti-tasklist'; import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist'; import { ActivitiForm } from 'ng2-activiti-form'; @@ -53,7 +54,7 @@ export class ActivitiDemoComponent implements AfterViewChecked { activitidetails: any; @ViewChild('activititasklist') - activititasklist: any; + activititasklist: ActivitiTaskList; @ViewChild('activitiprocessfilter') activitiprocessfilter: any; @@ -146,6 +147,10 @@ export class ActivitiDemoComponent implements AfterViewChecked { this.taskFilter = this.activitifilter.getCurrentFilter(); } + onStartTaskSuccess(event: any) { + this.activititasklist.reload(); + } + onSuccessTaskList(event: UserTaskFilterRepresentationModel) { this.currentTaskId = this.activititasklist.getCurrentTaskId(); } diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html index e5ca33e2be..f33ad4fb17 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html @@ -12,7 +12,7 @@
- +
diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index edc055d35d..47b081f70c 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -16,6 +16,7 @@ */ import { ActivitiApps } from './src/components/activiti-apps.component'; +import { ActivitiStartProcessButton } from './src/components/activiti-start-task.component'; import { ActivitiTaskList } from './src/components/activiti-tasklist.component'; import { ActivitiTaskDetails } from './src/components/activiti-task-details.component'; import { ActivitiFilters } from './src/components/activiti-filters.component'; @@ -23,6 +24,7 @@ import { NoTaskDetailsTemplateComponent } from './src/components/no-task-detail- export * from './src/components/activiti-apps.component'; export * from './src/components/activiti-tasklist.component'; +export * from './src/components/activiti-start-task.component'; export * from './src/services/activiti-tasklist.service'; export * from './src/models/filter.model'; @@ -30,6 +32,7 @@ export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ NoTaskDetailsTemplateComponent, ActivitiApps, ActivitiFilters, + ActivitiStartProcessButton, ActivitiTaskList, ActivitiTaskDetails ]; diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css new file mode 100644 index 0000000000..ff0f8dd865 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css @@ -0,0 +1,7 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html new file mode 100644 index 0000000000..837e1730fb --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html @@ -0,0 +1,19 @@ + + + +

{{'START_TASK.DIALOG.TITLE'|translate}}

+
+
+ + +
+
+ + +
+
+
+ + +
+
diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts new file mode 100644 index 0000000000..5340d5ac8c --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts @@ -0,0 +1,105 @@ +/*! + * @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, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { TaskDetailsModel } from '../models/task-details.model'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-start-task', + moduleId: __moduleName, + templateUrl: './activiti-start-task.component.html', + styleUrls: ['./activiti-start-task.component.css'], + providers: [ActivitiTaskListService] +}) +export class ActivitiStartProcessButton implements OnInit { + + @Input() + appId: string; + + @Output() + onSuccess: EventEmitter = new EventEmitter(); + + @ViewChild('dialog') + dialog: any; + + name: string; + description: string; + + /** + * Constructor + * @param auth + * @param translate + * @param taskService + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + private taskService: ActivitiTaskListService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src'); + } + } + + ngOnInit() { + } + + public start() { + if (this.name) { + this.taskService.createNewTask(new TaskDetailsModel({ + name: this.name, + description: this.description, + category: this.appId ? '' + this.appId : null + })).subscribe( + (res: any) => { + this.onSuccess.emit(res); + this.closeDialog(); + this.resetForm(); + }, + (err) => { + window.alert('An error occurred while trying to add the task'); + console.log(err); + } + ); + } + } + + public cancel() { + this.closeDialog(); + } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + private closeDialog() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } + + private resetForm() { + this.name = ''; + this.description = ''; + } +} 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 6e91517b49..836781bbaf 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 @@ -33,6 +33,8 @@ (onError)='onErrorEmitter($event)' (executeOutcome)='executeOutcomeEmitter($event)' #activitiForm> - + 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 c6449a6149..67b15c1cc4 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 @@ -133,6 +133,10 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { && this.taskDetails.formKey !== 'null'; } + isTaskActive() { + return this.taskDetails && this.taskDetails.duration === null; + } + /** * Load the activiti task details * @param taskId @@ -160,7 +164,6 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { if (this.activitichecklist) { this.activitichecklist.load(this.taskDetails.id); } - console.log(this.taskDetails); } ); @@ -176,6 +179,7 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { this.activitiTaskList.completeTask(this.taskId).subscribe( (res) => { console.log(res); + this.formCompleted.emit(res); } ); } 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 bea68053ea..7c1f093df0 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 @@ -132,6 +132,23 @@ describe('ActivitiTaskList', () => { taskList.ngOnInit(); }); + it('should reload tasks when reload() is called', (done) => { + spyOn(taskList.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); + spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + taskList.taskFilter = new UserTaskFilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); + taskList.ngOnInit(); + taskList.onSuccess.subscribe( (res) => { + expect(res).toBeDefined(); + expect(taskList.data).toBeDefined(); + expect(taskList.isTaskListEmpty()).not.toBeTruthy(); + expect(taskList.data.getRows().length).toEqual(2); + expect(taskList.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(taskList.data.getRows()[1].getValue('name')).toEqual('Nameless task'); + done(); + }); + taskList.reload(); + }); + it('should emit row click event', (done) => { let row = new ObjectDataRow({ id: 999 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 ae8da9b896..39ecb41b38 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 @@ -96,6 +96,13 @@ export class ActivitiTaskList implements OnInit, OnChanges { } } + public reload() { + if (this.taskFilter) { + let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter); + this.load(new TaskQueryRequestRepresentationModel(requestNode)); + } + } + public load(requestNode: TaskQueryRequestRepresentationModel) { this.activiti.getTotalTasks(requestNode).subscribe( (res) => { diff --git a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json index d83089f9f6..f55ebd1fb9 100644 --- a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json +++ b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json @@ -13,6 +13,9 @@ "COMMENTS": "Comments", "CHECKLIST": "Checklist" }, + "BUTTON": { + "COMPLETE": "Complete" + }, "MESSAGES": { "NONE": "No task details found." }, @@ -36,5 +39,19 @@ "MESSAGES": { "NONE": "No task filter selected." } + }, + "START_TASK": { + "BUTTON": "Start Task", + "DIALOG": { + "TITLE": "Start Task", + "LABEL": { + "NAME": "Name", + "DESCRIPTION": "Description" + }, + "ACTION": { + "START": "Start", + "CANCEL": "Cancel" + } + } } -} \ No newline at end of file +} diff --git a/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts b/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts index 7fdc4d37a6..e9408e7c6d 100644 --- a/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts +++ b/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts @@ -64,6 +64,7 @@ export class TaskDetailsModel { this.priority = obj && obj.priority; this.assignee = new User(obj.assignee); this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned; + this.category = obj && obj.category || null; this.created = obj && obj.created || null; this.description = obj && obj.description || null; this.dueDate = obj && obj.dueDate || null; 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 f472d08e8a..0262585cb5 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 @@ -477,5 +477,38 @@ describe('ActivitiTaskListService', () => { }); }); + it('should create a new standalone task ', (done) => { + let taskFake = new TaskDetailsModel({ + name: 'FakeNameTask', + description: 'FakeDescription', + category: '3' + }); + + service.createNewTask(taskFake).subscribe( + (res: TaskDetailsModel) => { + expect(res).toBeDefined(); + expect(res.id).not.toEqual(''); + expect(res.name).toEqual('FakeNameTask'); + expect(res.description).toEqual('FakeDescription'); + expect(res.category).toEqual('3'); + expect(res.created).not.toEqual(''); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify({ + id: '777', + name: 'FakeNameTask', + description: 'FakeDescription', + category: '3', + assignee: 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 c6c86e0db7..8bc00c94d6 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 @@ -216,6 +216,19 @@ export class ActivitiTaskListService { }).catch(this.handleError); } + /** + * Create a new standalone task + * @param task - TaskDetailsModel + * @returns {TaskDetailsModel} + */ + createNewTask(task: TaskDetailsModel): Observable { + return Observable.fromPromise(this.callApiCreateTask(task)) + .map(res => res) + .map((response: TaskDetailsModel) => { + return new TaskDetailsModel(response); + }).catch(this.handleError); + } + private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) { return this.authService.getAlfrescoApi().activiti.taskApi.listTasks(requestNode); } @@ -256,6 +269,10 @@ export class ActivitiTaskListService { return this.authService.getAlfrescoApi().activiti.taskApi.completeTask(id); } + private callApiCreateTask(task: TaskDetailsModel) { + return this.authService.getAlfrescoApi().activiti.taskApi.createNewTask(task); + } + private handleError(error: any) { console.error(error); return Observable.throw(error || 'Server error');