From 016f0b3c0915a2c498dc6b0aed91de8fb04c28d8 Mon Sep 17 00:00:00 2001 From: Vito Date: Mon, 27 Mar 2017 06:32:22 -0700 Subject: [PATCH] #1517 - Added new behaviour when user create a new task (#1769) * #1517 - added search task into filters by id feature * #1517 - added test for tasklist service * #1517 - Added test for filter component --- .../activiti/activiti-demo.component.ts | 3 +- .../activiti-filters.component.spec.ts | 43 +++++- .../components/activiti-filters.component.ts | 18 +++ .../activiti-tasklist.service.spec.ts | 136 ++++++++++++++++-- .../src/services/activiti-tasklist.service.ts | 61 ++++++-- 5 files changed, 234 insertions(+), 27 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 0e130888dc..f883fe09c5 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -162,8 +162,9 @@ export class ActivitiDemoComponent implements AfterViewInit { } onStartTaskSuccess(event: any) { - this.activitifilter.selectFirstFilter(); + this.activitifilter.selectFilterWithTask(event.id); this.taskFilter = this.activitifilter.getCurrentFilter(); + this.activititasklist.landingTaskId = event.id; this.activititasklist.reload(); } 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 1346f309ca..b7cc0f7c4a 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 @@ -16,6 +16,7 @@ */ import { SimpleChange } from '@angular/core'; +import { async } from '@angular/core/testing'; import { Observable } from 'rxjs/Rx'; import { LogServiceMock } from 'ng2-alfresco-core'; import { ActivitiFilters } from './activiti-filters.component'; @@ -29,8 +30,18 @@ describe('ActivitiFilters', () => { let logService: LogServiceMock; let fakeGlobalFilter = []; - fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeInvolvedTasks', filter: { state: 'open', assignment: 'fake-involved'}})); - fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}})); + fakeGlobalFilter.push(new FilterRepresentationModel({ + name: 'FakeInvolvedTasks', + filter: { state: 'open', assignment: 'fake-involved' } + })); + fakeGlobalFilter.push(new FilterRepresentationModel({ + name: 'FakeMyTasks', + filter: { state: 'open', assignment: 'fake-assignee' } + })); + let fakeFilter = new FilterRepresentationModel({ + name: 'FakeMyTasks', + filter: { state: 'open', assignment: 'fake-assignee' } + }); let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalFilter); @@ -121,7 +132,7 @@ describe('ActivitiFilters', () => { }); it('should emit an event when a filter is selected', (done) => { - let currentFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-involved'}}); + let currentFilter = new FilterRepresentationModel({ filter: { state: 'open', assignment: 'fake-involved' } }); filterList.filterClick.subscribe((filter: FilterRepresentationModel) => { expect(filter).toBeDefined(); @@ -164,7 +175,10 @@ describe('ActivitiFilters', () => { }); it('should return the current filter after one is selected', () => { - let filter = new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}}); + let filter = new FilterRepresentationModel({ + name: 'FakeMyTasks', + filter: { state: 'open', assignment: 'fake-assignee' } + }); expect(filterList.currentFilter).toBeUndefined(); filterList.selectFilter(filter); expect(filterList.getCurrentFilter()).toBe(filter); @@ -178,4 +192,25 @@ describe('ActivitiFilters', () => { expect(filterList.getFiltersByAppId).toHaveBeenCalled(); }); + + it('should change the current filter if a filter with taskid is found', async(() => { + spyOn(activitiService, 'isTaskRelatedToFilter').and.returnValue(Observable.of(fakeFilter)); + filterList.filters = fakeGlobalFilter; + filterList.selectFilterWithTask('111'); + + expect(filterList.currentFilter).toBe(fakeFilter); + })); + + it('should not change the current filter if no filter with taskid is found', async(() => { + let filter = new FilterRepresentationModel({ + name: 'FakeMyTasks', + filter: { state: 'open', assignment: 'fake-assignee' } + }); + filterList.filters = fakeGlobalFilter; + filterList.currentFilter = filter; + spyOn(activitiService, 'isTaskRelatedToFilter').and.returnValue(Observable.of(null)); + filterList.selectFilterWithTask('111'); + + expect(filterList.currentFilter).toBe(filter); + })); }); 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 38ae8a34c7..f0cf9a2410 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 @@ -144,6 +144,24 @@ export class ActivitiFilters implements OnInit, OnChanges { this.filterClick.emit(filter); } + public selectFilterWithTask(taskId: string) { + let filteredFilterList: FilterRepresentationModel[] = []; + this.activiti.getFilterForTaskById(taskId, this.filters).subscribe( + (filter: FilterRepresentationModel) => { + filteredFilterList.push(filter); + }, + (err) => { + this.logService.error(err); + this.onError.emit(err); + }, + () => { + if (filteredFilterList.length > 0) { + let myTaskFilter = filteredFilterList.find(filter => filter.name === 'My Tasks'); + this.currentFilter = myTaskFilter ? myTaskFilter : filteredFilterList[0]; + } + }); + } + /** * Select the first filter of a list if present */ 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 7dcecddd6e..ae46e1d5f1 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 @@ -15,11 +15,15 @@ * limitations under the License. */ -import { TestBed } from '@angular/core/testing'; +import { TestBed, async } from '@angular/core/testing'; import { CoreModule } from 'ng2-alfresco-core'; import { ActivitiTaskListService } from './activiti-tasklist.service'; import { TaskDetailsModel } from '../models/task-details.model'; -import { FilterRepresentationModel, AppDefinitionRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model'; +import { + FilterRepresentationModel, + AppDefinitionRepresentationModel, + TaskQueryRequestRepresentationModel +} from '../models/filter.model'; import { Comment } from '../models/comment.model'; declare let AlfrescoApi: any; @@ -28,7 +32,7 @@ declare let jasmine: any; describe('ActivitiTaskListService', () => { let fakeEmptyFilters = { size: 0, total: 0, start: 0, - data: [ ] + data: [] }; let fakeFilters = { @@ -36,13 +40,13 @@ describe('ActivitiTaskListService', () => { data: [ new AppDefinitionRepresentationModel( { - id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} + 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'} + id: '2', name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', + filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee' } } ] }; @@ -52,7 +56,7 @@ describe('ActivitiTaskListService', () => { data: [ { id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', - filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} + filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved' } } ] }; @@ -75,13 +79,24 @@ describe('ActivitiTaskListService', () => { sort: 'created-desc', text: '', state: 'open', assignment: 'fake-assignee' }; - let fakeUser = {id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName'}; + 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, + id: '1', name: 'FakeNameTask', description: null, category: null, + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + } + ] + }; + + let secondFakeTaskList = { + size: 1, total: 1, start: 0, + data: [ + { + id: '200', name: 'FakeNameTask', description: null, category: null, assignee: fakeUser, created: '2016-07-15T11:19:17.440+0000' } @@ -92,7 +107,7 @@ describe('ActivitiTaskListService', () => { error: 'wrong request' }; - let fakeTaskDetails = {id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser}; + let fakeTaskDetails = { id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser }; let fakeTasksComment = { size: 2, total: 2, start: 0, @@ -122,6 +137,40 @@ describe('ActivitiTaskListService', () => { ] }; + let fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepresentationModel({ + appId: 1, + name: 'CONTAIN FILTER', + recent: true, + icon: 'glyphicon-align-left', + filter: { + processDefinitionId: null, + processDefinitionKey: null, + name: null, + state: 'open', + sort: 'created-desc', + assignment: 'involved', + dueAfter: null, + dueBefore: null + } + }); + + let fakeRepresentationFilter2: FilterRepresentationModel = new FilterRepresentationModel({ + appId: 2, + name: 'NO TASK FILTER', + recent: false, + icon: 'glyphicon-inbox', + filter: { + processDefinitionId: null, + processDefinitionKey: null, + name: null, + state: 'open', + sort: 'created-desc', + assignment: 'assignee', + dueAfter: null, + dueBefore: null + } + }); + let fakeAppPromise = new Promise(function (resolve, reject) { resolve(fakeAppFilter); }); @@ -195,7 +244,7 @@ describe('ActivitiTaskListService', () => { it('should return the task list filtered', (done) => { service.getTasks(fakeFilter).subscribe( - res => { + res => { expect(res).toBeDefined(); expect(res.length).toEqual(1); expect(res[0].name).toEqual('FakeNameTask'); @@ -367,7 +416,7 @@ describe('ActivitiTaskListService', () => { it('should return the total number of tasks', (done) => { service.getTotalTasks(fakeFilter).subscribe( - res => { + res => { expect(res).toBeDefined(); expect(res.size).toEqual(1); expect(res.total).toEqual(1); @@ -427,7 +476,7 @@ describe('ActivitiTaskListService', () => { 'status': 200, contentType: 'application/json', responseText: JSON.stringify({ - id: '2233', name: 'FakeNameFilter', filter: {assignment: 'fake-assignement'} + id: '2233', name: 'FakeNameFilter', filter: { assignment: 'fake-assignement' } }) }); }); @@ -522,4 +571,63 @@ describe('ActivitiTaskListService', () => { }); }); + it('should return the filter if it contains task id', (done) => { + let taskId = '1'; + let filterFake = new FilterRepresentationModel({ + name: 'FakeNameFilter', + assignment: 'fake-assignement', + filter: { + processDefinitionKey: '1', + assignment: 'fake', + state: 'none', + sort: 'asc' + } + }); + + service.isTaskRelatedToFilter(taskId, filterFake).subscribe( + (res: any) => { + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTaskList) + }); + }); + + it('should return the filters if it contains task id', async(() => { + let taskId = '1'; + + let fakeFilterList: FilterRepresentationModel[] = []; + fakeFilterList.push(fakeRepresentationFilter1, fakeRepresentationFilter2); + let resultFilter = null; + service.getFilterForTaskById(taskId, fakeFilterList).subscribe( + (res: FilterRepresentationModel) => { + resultFilter = res; + }, + () => { + }, + () => { + expect(resultFilter).toBeDefined(); + expect(resultFilter).not.toBeNull(); + expect(resultFilter.name).toBe('CONTAIN FILTER'); + }); + + jasmine.Ajax.requests.at(0).respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTaskList) + }); + + jasmine.Ajax.requests.at(1).respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(secondFakeTaskList) + }); + })); + }); 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 eb884cee79..51b58f4fae 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 @@ -18,7 +18,10 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Rx'; import { AlfrescoApiService, LogService } from 'ng2-alfresco-core'; -import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model'; +import { + FilterRepresentationModel, + TaskQueryRequestRepresentationModel +} from '../models/filter.model'; import { Comment } from '../models/comment.model'; import { User } from '../models/user.model'; import { TaskDetailsModel } from '../models/task-details.model'; @@ -65,6 +68,48 @@ export class ActivitiTaskListService { }).catch(err => this.handleError(err)); } + /** + * Return all the filters in the list where the task id belong + * @param taskId - string + * @param filter - FilterRepresentationModel [] + * @returns {FilterRepresentationModel} + */ + getFilterForTaskById(taskId: string, filterList: FilterRepresentationModel[]): Observable { + return Observable.from(filterList) + .flatMap((filter: FilterRepresentationModel) => this.isTaskRelatedToFilter(taskId, filter)) + .filter((filter: FilterRepresentationModel) => filter != null); + } + + /** + * Return the search node for query task based on the given filter + * @param filter - FilterRepresentationModel + * @returns {TaskQueryRequestRepresentationModel} + */ + private generateTaskRequestNodeFromFilter(filter: FilterRepresentationModel): TaskQueryRequestRepresentationModel { + let requestNode = { + appDefinitionId: filter.appId, + processDefinitionKey: filter.filter.processDefinitionKey, + assignment: filter.filter.assignment, + state: filter.filter.state, + sort: filter.filter.sort + }; + return new TaskQueryRequestRepresentationModel(requestNode); + } + + /** + * Check if a taskId is filtered with the given filter + * @param taskId - string + * @param filter - FilterRepresentationModel + * @returns {FilterRepresentationModel} + */ + isTaskRelatedToFilter(taskId: string, filter: FilterRepresentationModel): Observable { + let requestNodeForFilter = this.generateTaskRequestNodeFromFilter(filter); + return Observable.fromPromise(this.callApiTasksFiltered(requestNodeForFilter)) + .map((res: any) => { + return res.data.find(element => element.id === taskId) ? filter : null; + }).catch(err => this.handleError(err)); + } + /** * Retrive all the tasks filtered by filterModel * @param filter - TaskFilterRepresentationModel @@ -151,7 +196,7 @@ export class ActivitiTaskListService { } attachFormToATask(taskId: string, formId: number): Observable { - return Observable.fromPromise(this.apiService.getInstance().activiti.taskApi.attachForm(taskId, {'formId': formId})); + return Observable.fromPromise(this.apiService.getInstance().activiti.taskApi.attachForm(taskId, { 'formId': formId })); } /** @@ -273,7 +318,7 @@ export class ActivitiTaskListService { callApiTaskFilters(appId?: string) { if (appId) { - return this.apiService.getInstance().activiti.userFiltersApi.getUserTaskFilters({appId: appId}); + return this.apiService.getInstance().activiti.userFiltersApi.getUserTaskFilters({ appId: appId }); } else { return this.apiService.getInstance().activiti.userFiltersApi.getUserTaskFilters(); } @@ -288,7 +333,7 @@ export class ActivitiTaskListService { } private callApiAddTaskComment(id: string, message: string) { - return this.apiService.getInstance().activiti.taskApi.addTaskComment({message: message}, id); + return this.apiService.getInstance().activiti.taskApi.addTaskComment({ message: message }, id); } private callApiAddTask(task: TaskDetailsModel) { @@ -327,7 +372,7 @@ export class ActivitiTaskListService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-align-left', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'involved'} + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'involved' } }); } @@ -342,7 +387,7 @@ export class ActivitiTaskListService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-inbox', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'assignee'} + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'assignee' } }); } @@ -357,7 +402,7 @@ export class ActivitiTaskListService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-record', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'candidate'} + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'candidate' } }); } @@ -372,7 +417,7 @@ export class ActivitiTaskListService { 'appId': appId, 'recent': true, 'icon': 'glyphicon-ok-sign', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'completed', 'assignment': 'involved'} + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'completed', 'assignment': 'involved' } }); } }