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..92fe2b717e --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process-service.mock.ts @@ -0,0 +1,49 @@ +/*! + * @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 { Observable } from 'rxjs/Observable'; +import { + ProcessList, + SingleProcessList +} from './activiti-process.model.mock'; +import { ActivitiProcessService } from './../services/activiti-process-service.service'; +import { AlfrescoSettingsService } from 'ng2-alfresco-core'; + +export class ActivitiProcessServiceMock extends ActivitiProcessService { + + getProcessesResult: ProcessList = new SingleProcessList('Example process 1'); + getProcessesReject: boolean = false; + getProcessesRejectError: string = 'Error'; + + constructor( + settings?: AlfrescoSettingsService + ) { + super(settings, null); + } + + getProcesses() { + if (this.getProcessesReject) { + return Observable.throw(this.getProcessesRejectError); + } + return Observable.create(observer => { + observer.next(this.getProcessesResult); + observer.complete(); + }).map((json) => { + return json.data; + }); + } +} diff --git a/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts new file mode 100644 index 0000000000..6eba34a88e --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts @@ -0,0 +1,39 @@ +/*! + * @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 { ProcessInstance } from '../models/process-instance'; + +export class ProcessList { + + data: ProcessInstance[]; + size: number; + start: number; + total: number; + + constructor(data?: ProcessInstance[]) { + this.data = data || []; + } +} + +export class SingleProcessList extends ProcessList { + constructor(name?: string) { + let instance = new ProcessInstance(); + instance.id = '123'; + instance.name = name; + super([instance]); + } +} diff --git a/ng2-components/ng2-activiti-processlist/src/assets/translation.service.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/translation.service.mock.ts new file mode 100644 index 0000000000..023104944a --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/assets/translation.service.mock.ts @@ -0,0 +1,37 @@ +/*! + * @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 { Observable } from 'rxjs/Rx'; +import { EventEmitter } from '@angular/core'; + +export interface LangChangeEvent { + lang: string; + translations: any; +} + +export class TranslationMock { + + public onLangChange: EventEmitter = new EventEmitter(); + + public get(key: string|Array, interpolateParams?: Object): Observable { + return Observable.of(key); + } + + addTranslationFolder() { + + } +} diff --git a/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.html b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.html new file mode 100644 index 0000000000..75a078b75f --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.html @@ -0,0 +1,20 @@ +

My Activiti Processes

+ +

{{ 'PROCESSLIST.NONE' | translate }}

+ + + + + + + + + + + + + + +
{{ 'PROCESSLIST.SUMMARY' | translate:{total: processInstances.length} }}
{{ 'PROCESSLIST.COLUMN.NAME' | translate }}
{{instance.name}}
+

{{ 'PROCESSLIST.ERROR' | translate:{errorMessage: errorMessage} }}

+ diff --git a/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.spec.ts index 0e8b8e50b8..a63caed2e4 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.spec.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.spec.ts @@ -15,19 +15,49 @@ * limitations under the License. */ -import {describe, expect, it, inject} from '@angular/core/testing'; +import { HTTP_PROVIDERS } from '@angular/http'; +import {describe, expect, it, inject, beforeEachProviders} from '@angular/core/testing'; import { TestComponentBuilder } from '@angular/compiler/testing'; -import {Ng2ActivitiProcesslistComponent} from '../../src/components/ng2-activiti-processlist.component'; +import { + AlfrescoSettingsService, + AlfrescoTranslationService +} from 'ng2-alfresco-core'; +import { Ng2ActivitiProcesslistComponent } from '../../src/components/ng2-activiti-processlist.component'; +import { ActivitiProcessServiceMock } from '../assets/activiti-process-service.mock'; +import { TranslationMock } from './../assets/translation.service.mock'; +import { ActivitiProcessService } from '../services/activiti-process-service.service'; -describe('Basic Example test ng2-activiti-processlist', () => { +describe('ActivitiProcesslistComponent', () => { - it('Test hello world', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - return tcb - .createAsync(Ng2ActivitiProcesslistComponent) - .then((fixture) => { - let element = fixture.nativeElement; - expect(element.querySelector('h1')).toBeDefined(); - expect(element.getElementsByTagName('h1')[0].innerHTML).toEqual('Hello World Angular 2 ng2-activiti-processlist'); - }); - })); + beforeEachProviders(() => { + + return [ + { provide: AlfrescoSettingsService }, + { provide: AlfrescoTranslationService, useClass: TranslationMock }, + { provide: ActivitiProcessService, useClass: ActivitiProcessServiceMock }, + HTTP_PROVIDERS + ]; + }); + + it('should have a valid title', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + return tcb + .createAsync(Ng2ActivitiProcesslistComponent) + .then((fixture) => { + let element = fixture.nativeElement; + expect(element.querySelector('h1')).toBeDefined(); + expect(element.getElementsByTagName('h1')[0].innerHTML).toEqual('My Activiti Processes'); + }); + })); + + it('should contain a list of processes', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + return tcb + .createAsync(Ng2ActivitiProcesslistComponent) + .then((fixture) => { + let element = fixture.nativeElement, component = fixture.componentInstance; + component.ngOnInit(); + fixture.detectChanges(); + expect(element.querySelector('table')).toBeDefined(); + expect(element.querySelectorAll('table tbody tr').length).toEqual(1); + }); + })); }); diff --git a/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.ts b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.ts index 4a202cd78a..7b514af4e7 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/ng2-activiti-processlist.component.ts @@ -15,10 +15,19 @@ * limitations under the License. */ -import { Component } from '@angular/core'; +import { + Component, + OnInit +} from '@angular/core'; +import { AlfrescoPipeTranslate, AlfrescoTranslationService } from 'ng2-alfresco-core'; +import { ActivitiProcessService } from '../services/activiti-process-service.service'; +import { ProcessInstance } from '../models/process-instance'; + +declare let __moduleName: string; @Component({ - selector: 'ng-2-activiti-processlist', + moduleId: __moduleName, + selector: 'ng2-activiti-processlist', styles: [ ` :host h1 { @@ -26,6 +35,36 @@ import { Component } from '@angular/core'; } ` ], - template: `

Hello World Angular 2 ng2-activiti-processlist

` + templateUrl: './ng2-activiti-processlist.component.html', + pipes: [ AlfrescoPipeTranslate ] }) -export class Ng2ActivitiProcesslistComponent {} +export class Ng2ActivitiProcesslistComponent implements OnInit { + + errorMessage: string; + processInstances: ProcessInstance[]; + + constructor ( + private processService: ActivitiProcessService, + private translate: AlfrescoTranslationService + ) { + if (translate !== null) { + translate.addTranslationFolder('node_modules/ng2-activiti-processlist'); + } + } + + ngOnInit() { + this.getProcesses(); + } + + getProcesses() { + this.processService.getProcesses() + .subscribe( + processInstances => this.processInstances = processInstances, + error => this.errorMessage = error); + } + + onItemClick(processInstance: ProcessInstance, event: any) { + console.log(processInstance, event); + } + +} diff --git a/ng2-components/ng2-activiti-processlist/src/i18n/en.json b/ng2-components/ng2-activiti-processlist/src/i18n/en.json new file mode 100644 index 0000000000..8706fab794 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/i18n/en.json @@ -0,0 +1,10 @@ +{ + "PROCESSLIST": { + "NONE": "No active processes were found", + "SUMMARY": "Found {{total}} active process instances", + "ERROR": "An error occurred while loading the processes: {{errorMessage}}", + "COLUMN": { + "NAME": "Name" + } + } +} diff --git a/ng2-components/ng2-activiti-processlist/src/models/process-instance.ts b/ng2-components/ng2-activiti-processlist/src/models/process-instance.ts new file mode 100644 index 0000000000..1511e557be --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/models/process-instance.ts @@ -0,0 +1,39 @@ +/*! + * @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. + */ + +export class ProcessInstance { + + public businessKey: string; + public ended: any; + public graphicalNotationDefined: boolean; + public id: string; + public name: string; + public processDefinitionCategory: string; + public processDefinitionDeploymentId: string; + public processDefinitionDescription: string; + public processDefinitionId: string; + public processDefinitionKey: string; + public processDefinitionName: string; + public processDefinitionVersion: number; + public startFormDefined: boolean; + public started: string; + public startedBy: any; + public suspended: boolean; + public tenantId: string; + public variables: any; + +} diff --git a/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.spec.ts b/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.spec.ts index d1dad7c702..94b6b660f2 100644 --- a/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.spec.ts +++ b/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.spec.ts @@ -15,37 +15,60 @@ * limitations under the License. */ -import { ReflectiveInjector } from '@angular/core'; import { it, describe, expect, - beforeEach + beforeEachProviders, + inject } from '@angular/core/testing'; import { - AlfrescoSettingsService -} from 'ng2-alfresco-core'; + Response, + ResponseOptions, + HTTP_PROVIDERS, + XHRBackend +} from '@angular/http'; +import { MockBackend, MockConnection } from '@angular/http/testing'; +import { AlfrescoSettingsService } from 'ng2-alfresco-core'; import { ActivitiProcessService } from './activiti-process-service.service'; -import { HTTP_PROVIDERS } from '@angular/http'; +import { ProcessInstance } from '../models/process-instance'; describe('ActivitiProcessService', () => { - let injector; - let service: ActivitiProcessService; - let settingsService: AlfrescoSettingsService; - - beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ + beforeEachProviders(() => { + return [ HTTP_PROVIDERS, + { provide: XHRBackend, useClass: MockBackend }, + ActivitiProcessService, AlfrescoSettingsService - ]); - - settingsService = injector.get(AlfrescoSettingsService); - service = new ActivitiProcessService(settingsService); + ]; }); - it('should require node to get thumbnail url', () => { - expect(null).toBeNull(); - }); + it('should be there', inject([ActivitiProcessService], (processService: ActivitiProcessService) => { + expect(typeof processService.getProcesses).toBe('function'); + })); + + it('should get process instances', + inject([ActivitiProcessService, XHRBackend], (processService: ActivitiProcessService, mockBackend: MockBackend) => { + mockBackend.connections.subscribe( + (connection: MockConnection) => { + connection.mockRespond(new Response( + new ResponseOptions({ + body: { + data: [{ + id: 'myprocess:1', + name: 'my process' + }] + } + }))); + }); + + processService.getProcesses().subscribe((instances: ProcessInstance[]) => { + expect(instances.length).toBe(1); + expect(instances[0].id).toBe('myprocess:1'); + expect(instances[0].name).toBe('my process'); + }); + + })); }); diff --git a/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.ts b/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.ts index 1dffbf2728..89e5402c29 100644 --- a/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.ts +++ b/ng2-components/ng2-activiti-processlist/src/services/activiti-process-service.service.ts @@ -18,9 +18,36 @@ import { AlfrescoSettingsService } from 'ng2-alfresco-core'; +import { ProcessInstance } from '../models/process-instance'; +import { Injectable } from '@angular/core'; +import { Http, Response } from '@angular/http'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/catch'; +@Injectable() export class ActivitiProcessService { - constructor(private alfrescoSettingsService: AlfrescoSettingsService) { + private processesUrl = 'http://localhost:9999/activiti-app/app/rest/filter/process-instances'; + + constructor(private alfrescoSettingsService: AlfrescoSettingsService, private http: Http) { + } + + getProcesses(): Observable { + return this.http.get(this.processesUrl) + .map(this.extractData) + .catch(this.handleError); + } + + private extractData(res: Response) { + let body = res.json(); + return body.data || { }; + } + + private handleError(error: any) { + let errMsg = (error.message) ? error.message : + error.status ? `${error.status} - ${error.statusText}` : 'Server error'; + console.error(errMsg); // log to console instead + return Observable.throw(errMsg); } }