diff --git a/ng2-components/ng2-activiti-processlist/karma.conf.js b/ng2-components/ng2-activiti-processlist/karma.conf.js index dac47d48bb..1cdd488ff6 100644 --- a/ng2-components/ng2-activiti-processlist/karma.conf.js +++ b/ng2-components/ng2-activiti-processlist/karma.conf.js @@ -34,7 +34,6 @@ module.exports = function (config) { 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', {pattern: 'node_modules/ng2-translate/**/*.js', included: false, watched: false}, - {pattern: 'node_modules/ng2-translate/**/*.js.map', included: false, watched: false}, 'karma-test-shim.js', @@ -47,6 +46,7 @@ module.exports = function (config) { { pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.*', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.js', included: false, served: true, watched: false }, + { pattern: 'node_modules/ng2-activiti-form/dist/**/*.js', included: false, served: true, watched: false }, // paths to support debugging with source maps in dev tools {pattern: 'src/**/*.ts', included: false, watched: false}, diff --git a/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.service.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.service.mock.ts new file mode 100644 index 0000000000..e8890a20c7 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.service.mock.ts @@ -0,0 +1,48 @@ +/*! + * @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 { UserProcessInstanceFilterRepresentationModel } from '../models/filter.model'; + +export var fakeFilters = { + size: 0, total: 0, start: 0, + data: [new UserProcessInstanceFilterRepresentationModel({ + 'name': 'Running', + 'appId': '22', + 'recent': true, + 'icon': 'glyphicon-random', + 'filter': {'sort': 'created-desc', 'name': '', 'state': 'running'} + })] +}; + +export var fakeEmptyFilters = { + size: 0, total: 0, start: 0, + data: [ ] +}; + +export var fakeApi = { + activiti: { + userFiltersApi: { + getUserProcessInstanceFilters: (filterOpts) => Promise.resolve({}), + createUserProcessInstanceFilter: (filter: UserProcessInstanceFilterRepresentationModel) => Promise.resolve(filter) + } + } +}; + +export var fakeError = { + message: null, + messageKey: 'GENERAL.ERROR.FORBIDDEN' +}; diff --git a/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.spec.ts b/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.spec.ts index 1888e6dbad..ed93bdbbe2 100644 --- a/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.spec.ts +++ b/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.spec.ts @@ -21,28 +21,97 @@ import { AlfrescoSettingsService, AlfrescoApiService } from 'ng2-alfresco-core'; +import { fakeApi, fakeEmptyFilters, fakeFilters, fakeError } from '../assets/activiti-process.service.mock'; import { ActivitiProcessService } from './activiti-process.service'; describe('ActivitiProcessService', () => { - let service, injector; + let service: ActivitiProcessService; + let injector: ReflectiveInjector; beforeEach(() => { injector = ReflectiveInjector.resolveAndCreate([ ActivitiProcessService, - AlfrescoSettingsService, AlfrescoApiService, - AlfrescoAuthenticationService + AlfrescoAuthenticationService, + AlfrescoSettingsService ]); - }); - - beforeEach(() => { service = injector.get(ActivitiProcessService); + let authenticationService: AlfrescoAuthenticationService = injector.get(AlfrescoAuthenticationService); + spyOn(authenticationService, 'getAlfrescoApi').and.returnValue(fakeApi); }); - it('should get process instances', (done) => { + xit('should get process instances', (done) => { expect(true).toBe(true); done(); }); + + describe('filters', () => { + + let userFiltersApi = fakeApi.activiti.userFiltersApi; + let getFilters: any, createFilter: any; + + beforeEach(() => { + getFilters = spyOn(userFiltersApi, 'getUserProcessInstanceFilters'); + createFilter = spyOn(userFiltersApi, 'createUserProcessInstanceFilter'); + }); + + it('should call the API without an appId defined by default', () => { + getFilters = getFilters.and.returnValue(Promise.resolve(fakeFilters)); + service.getProcessFilters(null); + expect(getFilters).toHaveBeenCalledWith({}); + }); + + it('should call the API with the correct appId when specified', () => { + getFilters = getFilters.and.returnValue(Promise.resolve(fakeFilters)); + service.getProcessFilters('226'); + expect(getFilters).toHaveBeenCalledWith({appId: '226'}); + }); + + it('should return the non-empty filter list that is returned by the API', (done) => { + getFilters = getFilters.and.returnValue(Promise.resolve(fakeFilters)); + service.getProcessFilters(null).subscribe( + (res) => { + expect(res.length).toBe(1); + done(); + } + ); + }); + + it('should return the default filters when none are returned by the API', (done) => { + getFilters = getFilters.and.returnValue(Promise.resolve(fakeEmptyFilters)); + + service.getProcessFilters(null).subscribe( + (res) => { + expect(res.length).toBe(3); + done(); + } + ); + }); + + it('should create the default filters when none are returned by the API', (done) => { + getFilters = getFilters.and.returnValue(Promise.resolve(fakeEmptyFilters)); + createFilter = createFilter.and.returnValue(Promise.resolve({})); + + service.getProcessFilters(null).subscribe( + (res) => { + expect(createFilter).toHaveBeenCalledTimes(3); + done(); + } + ); + }); + + it('should pass on any error that is returned by the API', (done) => { + getFilters = getFilters.and.returnValue(Promise.reject(fakeError)); + + service.getProcessFilters(null).subscribe( + () => {}, + (res) => { + expect(res).toBe(fakeError); + done(); + } + ); + }); + }); }); diff --git a/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.ts b/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.ts index f0e0a2a1d9..ec301c890e 100644 --- a/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.ts +++ b/ng2-components/ng2-activiti-processlist/src/services/activiti-process.service.ts @@ -17,7 +17,7 @@ import {AlfrescoAuthenticationService} from 'ng2-alfresco-core'; import {ProcessInstance} from '../models/process-instance'; -import {TaskQueryRequestRepresentationModel} from '../models/filter.model'; +import {TaskQueryRequestRepresentationModel, UserProcessInstanceFilterRepresentationModel} from '../models/filter.model'; import {User} from '../models/user.model'; import {Comment} from '../models/comment.model'; import {Injectable} from '@angular/core'; @@ -59,11 +59,102 @@ export class ActivitiProcessService { let filterOpts = appId ? { appId: appId } : {}; - return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.userFiltersApi.getUserProcessInstanceFilters(filterOpts)) - .map(this.extractData) + return Observable.fromPromise(this.callApiGetUserProcessInstanceFilters(filterOpts)) + .map((response: any) => { + let filters: UserProcessInstanceFilterRepresentationModel[] = []; + response.data.forEach((filter: UserProcessInstanceFilterRepresentationModel) => { + let filterModel = new UserProcessInstanceFilterRepresentationModel(filter); + filters.push(filterModel); + }); + if (response && response.data && response.data.length === 0) { + return this.createDefaultFilters(appId); + } + return filters; + }) .catch(this.handleError); } + /** + * Create and return the default filters + * @param appId + * @returns {UserProcessInstanceFilterRepresentationModel[]} + */ + private createDefaultFilters(appId: string): UserProcessInstanceFilterRepresentationModel[] { + let filters: UserProcessInstanceFilterRepresentationModel[] = []; + + let involvedTasksFilter = this.getRunningFilterInstance(appId); + this.addFilter(involvedTasksFilter); + filters.push(involvedTasksFilter); + + let myTasksFilter = this.getCompletedFilterInstance(appId); + this.addFilter(myTasksFilter); + filters.push(myTasksFilter); + + let queuedTasksFilter = this.getAllFilterInstance(appId); + this.addFilter(queuedTasksFilter); + filters.push(queuedTasksFilter); + + return filters; + } + + /** + * Return a static Running filter instance + * @param appId + * @returns {UserProcessInstanceFilterRepresentationModel} + */ + private getRunningFilterInstance(appId: string): UserProcessInstanceFilterRepresentationModel { + return new UserProcessInstanceFilterRepresentationModel({ + 'name': 'Running', + 'appId': appId, + 'recent': true, + 'icon': 'glyphicon-random', + 'filter': {'sort': 'created-desc', 'name': '', 'state': 'running'} + }); + } + + /** + * Return a static Completed filter instance + * @param appId + * @returns {UserProcessInstanceFilterRepresentationModel} + */ + private getCompletedFilterInstance(appId: string): UserProcessInstanceFilterRepresentationModel { + return new UserProcessInstanceFilterRepresentationModel({ + 'name': 'Completed', + 'appId': appId, + 'recent': false, + 'icon': 'glyphicon-ok-sign', + 'filter': {'sort': 'created-desc', 'name': '', 'state': 'completed'} + }); + } + + /** + * Return a static All filter instance + * @param appId + * @returns {UserProcessInstanceFilterRepresentationModel} + */ + private getAllFilterInstance(appId: string): UserProcessInstanceFilterRepresentationModel { + return new UserProcessInstanceFilterRepresentationModel({ + 'name': 'All', + 'appId': appId, + 'recent': true, + 'icon': 'glyphicon-th', + 'filter': {'sort': 'created-desc', 'name': '', 'state': 'all'} + }); + } + + /** + * Add a filter + * @param filter - UserProcessInstanceFilterRepresentationModel + * @returns {UserProcessInstanceFilterRepresentationModel} + */ + addFilter(filter: UserProcessInstanceFilterRepresentationModel): Observable { + return Observable.fromPromise(this.callApiAddFilter(filter)) + .map(res => res) + .map((response: UserProcessInstanceFilterRepresentationModel) => { + return response; + }).catch(this.handleError); + } + getProcess(id: string): Observable { return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessInstance(id)) .catch(this.handleError); @@ -152,12 +243,19 @@ export class ActivitiProcessService { .catch(this.handleError); } + private callApiGetUserProcessInstanceFilters(filterOpts) { + return this.authService.getAlfrescoApi().activiti.userFiltersApi.getUserProcessInstanceFilters(filterOpts); + } + + private callApiAddFilter(filter: UserProcessInstanceFilterRepresentationModel) { + return this.authService.getAlfrescoApi().activiti.userFiltersApi.createUserProcessInstanceFilter(filter); + } + private extractData(res: any) { return res.data || {}; } private handleError(error: any) { - console.error(error); return Observable.throw(error || 'Server error'); } }