From d3d67c593475b728e01627c7a90b16b8db608c14 Mon Sep 17 00:00:00 2001 From: Maurizio Vitale Date: Mon, 6 Feb 2017 19:40:49 +0000 Subject: [PATCH] Create a new activiti content component that provide the file preview (#1516) * #1236 Add activiti content component * fix wrong name * Fix unit test import * Rollback api changes * #1236 fix preview using blob * Fix after review --- ng2-components/ng2-activiti-form/README.md | 26 ++++ ng2-components/ng2-activiti-form/index.ts | 3 + .../components/activiti-content.component.css | 42 +++++++ .../activiti-content.component.html | 22 ++++ .../components/activiti-content.component.ts | 117 ++++++++++++++++++ .../activiti-start-form.component.spec.ts | 2 + .../container/container.widget.spec.ts | 3 +- .../widgets/core/content-link.model.ts | 71 +++++++++++ .../src/components/widgets/core/index.ts | 1 + .../display-value/display-value.widget.css | 29 ----- .../display-value/display-value.widget.html | 13 +- .../display-value.widget.spec.ts | 3 +- .../widgets/tabs/tabs.widget.spec.ts | 3 +- .../ng2-activiti-form/src/i18n/en.json | 3 + .../ng2-activiti-form/src/i18n/it.json | 10 ++ .../src/services/form.service.spec.ts | 77 ++++++++++++ .../src/services/form.service.ts | 20 +++ 17 files changed, 403 insertions(+), 42 deletions(-) create mode 100644 ng2-components/ng2-activiti-form/src/components/activiti-content.component.css create mode 100644 ng2-components/ng2-activiti-form/src/components/activiti-content.component.html create mode 100644 ng2-components/ng2-activiti-form/src/components/activiti-content.component.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/core/content-link.model.ts create mode 100644 ng2-components/ng2-activiti-form/src/i18n/it.json diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md index 0a75888091..253c5ba75a 100644 --- a/ng2-components/ng2-activiti-form/README.md +++ b/ng2-components/ng2-activiti-form/README.md @@ -351,6 +351,32 @@ There are two additional functions that can be of a great value when controlling **Please note that if `event.preventDefault()` is not called then default outcome behaviour will also be executed after your custom code.** +## Activiti Content Component + +### Basic usage + +The component shows the content preview. + +```html + +``` + +### Configuration + +#### Properties + +The recommended set of properties can be found in the following table: + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `contentId` | string | | The content id to show. | + +#### Events + +| Name | Description | +| --- | --- | +| `contentClick` | Invoked when the content is clicked. | + ## FormService ```ts diff --git a/ng2-components/ng2-activiti-form/index.ts b/ng2-components/ng2-activiti-form/index.ts index 110d843dfc..8c680e935b 100644 --- a/ng2-components/ng2-activiti-form/index.ts +++ b/ng2-components/ng2-activiti-form/index.ts @@ -19,6 +19,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CoreModule } from 'ng2-alfresco-core'; import { ActivitiForm } from './src/components/activiti-form.component'; +import { ActivitiContent } from './src/components/activiti-content.component'; import { FormFieldComponent } from './src/components/form-field/form-field.component'; import { ActivitiStartForm } from './src/components/activiti-start-form.component'; import { FormService } from './src/services/form.service'; @@ -31,6 +32,7 @@ import { HttpModule } from '@angular/http'; import { WIDGET_DIRECTIVES } from './src/components/widgets/index'; export * from './src/components/activiti-form.component'; +export * from './src/components/activiti-content.component'; export * from './src/components/activiti-start-form.component'; export * from './src/services/form.service'; export * from './src/components/widgets/index'; @@ -41,6 +43,7 @@ export * from './src/events/index'; export const ACTIVITI_FORM_DIRECTIVES: any[] = [ ActivitiForm, + ActivitiContent, ActivitiStartForm, FormFieldComponent, ...WIDGET_DIRECTIVES diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-content.component.css b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.css new file mode 100644 index 0000000000..219afdd91a --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.css @@ -0,0 +1,42 @@ +.upload-widget { + width: 100%; + word-break: break-all; +} + +.upload-widget__icon { + float: left; + color: rgba(0, 0, 0, .26); +} + +.upload-widget__file { + float: left; + margin-top: 4px; + color: rgba(0, 0, 0, .26); +} + +.upload-widget__label { + color: rgba(0, 0, 0, .26); +} + +.img-upload-widget { + width: 100%; + height: 100%; + border: 1px solid rgba(117, 117, 117, 0.57); + box-shadow: 1px 1px 2px #dddddd; + background-color: #ffffff; +} + +.nothing-to-see { + box-shadow: 1px 1px 2px #dddddd; + background-color: #ffffff; + width: 100%; + height: 100%; + padding: 50px 0 50px 0; + text-align: center; +} + +.previewTxt { + word-wrap: break-word; + word-break: break-all; + text-align: center; +} diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-content.component.html b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.html new file mode 100644 index 0000000000..b47019dd21 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.html @@ -0,0 +1,22 @@ +
+
+
+
+ +
+
+ image +
{{ 'FORM.PREVIEW.IMAGE_NOT_AVAILABLE' | translate }}
+
+
+
{{content.name}}
+
+ + + file_download + +
+
+
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-content.component.ts b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.ts new file mode 100644 index 0000000000..6055fcc37c --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/activiti-content.component.ts @@ -0,0 +1,117 @@ +/*! + * @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, + OnChanges, + SimpleChanges, + Input, + Output, + EventEmitter +} from '@angular/core'; +import { AlfrescoTranslationService, LogService } from 'ng2-alfresco-core'; +import { FormService } from './../services/form.service'; +import { ContentLinkModel } from './widgets/core/content-link.model'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + moduleId: module.id, + selector: 'activiti-content', + templateUrl: './activiti-content.component.html', + styleUrls: ['./activiti-content.component.css'] +}) +export class ActivitiContent implements OnChanges { + + @Input() + id: string; + + @Output() + contentClick = new EventEmitter(); + + content: ContentLinkModel; + + constructor(private translate: AlfrescoTranslationService, + protected formService: FormService, + private logService: LogService, + private sanitizer: DomSanitizer ) { + + if (this.translate) { + this.translate.addTranslationFolder('ng2-activiti-form', 'node_modules/ng2-activiti-form/src'); + } + + } + + ngOnChanges(changes: SimpleChanges) { + let contentId = changes['id']; + if (contentId && contentId.currentValue) { + this.loadContent(contentId.currentValue); + return; + } + } + + loadContent(id: number) { + this.formService + .getFileContent(id) + .subscribe( + (response: ContentLinkModel) => { + this.content = new ContentLinkModel(response); + this.loadThumbnailUrl(this.content); + }, + error => { + this.logService.error(error); + } + ); + } + + loadThumbnailUrl(content: ContentLinkModel) { + if (this.content.isTypeImage()) { + this.formService.getFileRawContent(content.id).subscribe( + (response: Blob) => { + this.content.thumbnailUrl = this.createUrlPreview(response); + }, + error => { + this.logService.error(error); + } + ); + } else if (this.content.isThumbnailSupported()) { + this.content.contentRawUrl = this.formService.getFileRawContentUrl(content.id); + this.content.thumbnailUrl = this.formService.getContentThumbnailUrl(content.id); + } + } + + openViewer(content: ContentLinkModel) { + this.contentClick.emit(content); + this.logService.info('Content clicked' + content.id); + } + + /** + * Download file opening it in a new window + */ + download($event) { + $event.stopPropagation(); + } + + private sanitizeUrl(url: string) { + return this.sanitizer.bypassSecurityTrustUrl(url); + } + + private createUrlPreview(blob: Blob) { + let imageUrl = window.URL.createObjectURL(blob); + let sanitize: any = this.sanitizeUrl(imageUrl); + return sanitize.changingThisBreaksApplicationSecurity; + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts index 7fff2105c5..0b1f6ad44b 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts @@ -21,6 +21,7 @@ import { Observable } from 'rxjs/Rx'; import { ActivitiStartForm } from './activiti-start-form.component'; import { FormFieldComponent } from './form-field/form-field.component'; +import { ActivitiContent } from './activiti-content.component'; import { WIDGET_DIRECTIVES } from './widgets/index'; import { FormService } from './../services/form.service'; import { EcmModelService } from './../services/ecm-model.service'; @@ -45,6 +46,7 @@ describe('ActivitiStartForm', () => { declarations: [ ActivitiStartForm, FormFieldComponent, + ActivitiContent, ...WIDGET_DIRECTIVES ], providers: [ diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts index f1967abee5..130d6d5417 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts @@ -24,6 +24,7 @@ import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { CoreModule } from 'ng2-alfresco-core'; import { WIDGET_DIRECTIVES } from '../index'; import { FormFieldComponent } from './../../form-field/form-field.component'; +import { ActivitiContent } from './../../activiti-content.component'; import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock'; describe('ContainerWidget', () => { @@ -132,7 +133,7 @@ describe('ContainerWidget', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [FormFieldComponent, WIDGET_DIRECTIVES] + declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES] }).compileComponents().then(() => { fixture = TestBed.createComponent(ContainerWidget); containerWidgetComponent = fixture.componentInstance; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/content-link.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/content-link.model.ts new file mode 100644 index 0000000000..0e8e47c0e7 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/content-link.model.ts @@ -0,0 +1,71 @@ +/*! + * @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 ContentLinkModel { + + contentAvailable: boolean; + created: string; + createdBy: any; + id: number; + link: boolean; + mimeType: string; + name: string; + previewStatus: string; + relatedContent: boolean; + simpleType: string; + thumbnailUrl: string; + contentRawUrl: string; + thumbnailStatus: string; + + constructor(obj?: any) { + this.contentAvailable = obj && obj.contentAvailable; + this.created = obj && obj.created; + this.createdBy = obj && obj.createdBy || {}; + this.id = obj && obj.id; + this.link = obj && obj.link; + this.mimeType = obj && obj.mimeType; + this.name = obj && obj.name; + this.previewStatus = obj && obj.previewStatus; + this.relatedContent = obj && obj.relatedContent; + this.simpleType = obj && obj.simpleType; + this.thumbnailStatus = obj && obj.thumbnailStatus; + } + + hasPreviewStatus(): boolean { + return this.previewStatus === 'supported' ? true : false; + } + + isTypeImage(): boolean { + return this.simpleType === 'image' ? true : false; + } + + isTypePdf(): boolean { + return this.simpleType === 'pdf' ? true : false; + } + + isTypeDoc(): boolean { + return this.simpleType === 'word' || this.simpleType === 'content' ? true : false; + } + + isThumbnailReady(): boolean { + return this.thumbnailStatus === 'created'; + } + + isThumbnailSupported(): boolean { + return this.isTypeImage() || ((this.isTypePdf() || this.isTypeDoc()) && this.isThumbnailReady()); + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts index 6c62f0963f..2c018a4e0d 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts @@ -29,3 +29,4 @@ export * from './tab.model'; export * from './form-outcome.model'; export * from './form-outcome-event.model'; export * from './form-field-validator'; +export * from './content-link.model'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.css b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.css index 43ebf44d05..b06bf90c3f 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.css +++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.css @@ -21,32 +21,3 @@ width: 100%; } - -.upload-widget { - width: 100%; - word-break: break-all; -} - -.upload-widget__icon { - float: left; - color: rgba(0, 0, 0, .26); -} - -.upload-widget__file { - float: left; - margin-top: 4px; - color: rgba(0, 0, 0, .26); -} - -.upload-widget__label { - color: rgba(0, 0, 0, .26); -} - -.img-upload-widget { - width: 100px; - height: 100px; - padding: 2px; - border: 1px solid rgba(117, 117, 117, 0.57); - box-shadow: 1px 1px 2px #dddddd; - background-color: #ffffff; -} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html index 6f39f72256..ec5fbe4669 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html +++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html @@ -68,16 +68,9 @@
-
-
- -
-
- -
-
- attachment - {{value}} +
+
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts index 17e3b896ef..207e51f4a1 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts @@ -20,6 +20,7 @@ import { CoreModule, LogServiceMock } from 'ng2-alfresco-core'; import { Observable } from 'rxjs/Rx'; import { DisplayValueWidget } from './display-value.widget'; import { FormService } from '../../../services/form.service'; +import { ActivitiContent } from '../../activiti-content.component'; import { EcmModelService } from '../../../services/ecm-model.service'; import { FormFieldModel } from './../core/form-field.model'; import { FormFieldTypes } from '../core/form-field-types'; @@ -688,7 +689,7 @@ describe('DisplayValueWidget', () => { window['componentHandler'] = componentHandler; TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [DisplayValueWidget], + declarations: [DisplayValueWidget, ActivitiContent], providers: [ EcmModelService, FormService, diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts index 510b4c5b1f..1ffd67bebf 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts @@ -23,6 +23,7 @@ import { TabsWidget } from './tabs.widget'; import { TabModel } from '../core/tab.model'; import { WIDGET_DIRECTIVES } from '../index'; import { FormFieldComponent } from './../../form-field/form-field.component'; +import { ActivitiContent } from './../../activiti-content.component'; import { CoreModule } from 'ng2-alfresco-core'; describe('TabsWidget', () => { @@ -103,7 +104,7 @@ describe('TabsWidget', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [FormFieldComponent, WIDGET_DIRECTIVES] + declarations: [FormFieldComponent, ActivitiContent, WIDGET_DIRECTIVES] }).compileComponents().then(() => { fixture = TestBed.createComponent(TabsWidget); tabWidgetComponent = fixture.componentInstance; diff --git a/ng2-components/ng2-activiti-form/src/i18n/en.json b/ng2-components/ng2-activiti-form/src/i18n/en.json index 701b687e00..c05017b260 100644 --- a/ng2-components/ng2-activiti-form/src/i18n/en.json +++ b/ng2-components/ng2-activiti-form/src/i18n/en.json @@ -2,6 +2,9 @@ "FORM": { "START_FORM": { "TITLE": "Start Form" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "The preview image is not available." } } } diff --git a/ng2-components/ng2-activiti-form/src/i18n/it.json b/ng2-components/ng2-activiti-form/src/i18n/it.json new file mode 100644 index 0000000000..58d9aa460c --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/i18n/it.json @@ -0,0 +1,10 @@ +{ + "FORM": { + "START_FORM": { + "TITLE": "Inizia" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Anteprima immagine non disponibile." + } + } +} diff --git a/ng2-components/ng2-activiti-form/src/services/form.service.spec.ts b/ng2-components/ng2-activiti-form/src/services/form.service.spec.ts index 28339b0ded..1e042a453f 100644 --- a/ng2-components/ng2-activiti-form/src/services/form.service.spec.ts +++ b/ng2-components/ng2-activiti-form/src/services/form.service.spec.ts @@ -30,6 +30,7 @@ describe('FormService', () => { let service: FormService; let apiService: AlfrescoApiService; let logService: LogService; + let bpmCli: any; beforeEach(() => { TestBed.configureTestingModule({ @@ -44,6 +45,7 @@ describe('FormService', () => { }); service = TestBed.get(FormService); apiService = TestBed.get(AlfrescoApiService); + bpmCli = apiService.getInstance().bpmAuth; logService = TestBed.get(LogService); }); @@ -374,6 +376,81 @@ describe('FormService', () => { }); }); + it('should return the unsupported content when the file is an image', (done) => { + let contentId: number = 999; + responseBody = { + id: contentId, + name: 'fake-name.jpg', + created: '2017-01-23T12:12:53.219+0000', + createdBy: {id: 2, firstName: 'fake-admin', lastName: 'fake-last', 'email': 'fake-admin'}, + relatedContent: false, + contentAvailable: true, + link: false, + mimeType: 'image/jpeg', + simpleType: 'image', + previewStatus: 'unsupported', + thumbnailStatus: 'unsupported' + }; + + service.getFileContent(contentId).subscribe(result => { + expect(result.id).toEqual(contentId); + expect(result.name).toEqual('fake-name.jpg'); + expect(result.simpleType).toEqual('image'); + expect(result.thumbnailStatus).toEqual('unsupported'); + done(); + }); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(responseBody) + }); + }); + + it('should return the supported content when the file is a pdf', (done) => { + let contentId: number = 888; + responseBody = { + id: contentId, + name: 'fake-name.pdf', + created: '2017-01-23T12:12:53.219+0000', + createdBy: {id: 2, firstName: 'fake-admin', lastName: 'fake-last', 'email': 'fake-admin'}, + relatedContent: false, + contentAvailable: true, + link: false, + mimeType: 'application/pdf', + simpleType: 'pdf', + previewStatus: 'created', + thumbnailStatus: 'created' + }; + + service.getFileContent(contentId).subscribe(result => { + expect(result.id).toEqual(contentId); + expect(result.name).toEqual('fake-name.pdf'); + expect(result.simpleType).toEqual('pdf'); + expect(result.thumbnailStatus).toEqual('created'); + done(); + }); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(responseBody) + }); + }); + + it('should return the raw content URL', () => { + let contentId: number = 999; + let contentRawUrl = service.getFileRawContentUrl(contentId); + expect(contentRawUrl).toEqual(`${bpmCli.basePath}/api/enterprise/content/${contentId}/raw`); + }); + + it('should return the thumbnail URL', () => { + let contentId: number = 999; + + let contentRawUrl = service.getContentThumbnailUrl(contentId); + expect(contentRawUrl).toEqual(`${bpmCli.basePath}/app/rest/content/${contentId}/rendition/thumbnail`); + }); + it('should create a Form form a Node', (done) => { let nameForm = 'testNode'; diff --git a/ng2-components/ng2-activiti-form/src/services/form.service.ts b/ng2-components/ng2-activiti-form/src/services/form.service.ts index 0ffc0156d3..a142f492ad 100644 --- a/ng2-components/ng2-activiti-form/src/services/form.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/form.service.ts @@ -252,6 +252,26 @@ export class FormService { return Observable.fromPromise(this.apiService.getInstance().activiti.contentApi.createTemporaryRawRelatedContent(file)); } + getFileContent(contentId: number): Observable { + let alfrescoApi = this.apiService.getInstance(); + return Observable.fromPromise(alfrescoApi.activiti.contentApi.getContent(contentId)); + } + + getFileRawContent(contentId: number): Observable { + let alfrescoApi = this.apiService.getInstance(); + return Observable.fromPromise(alfrescoApi.activiti.contentApi.getRawContent(contentId)); + } + + getFileRawContentUrl(contentId: number): string { + let alfrescoApi = this.apiService.getInstance(); + return alfrescoApi.activiti.contentApi.getRawContentUrl(contentId); + } + + getContentThumbnailUrl(contentId: number): string { + let alfrescoApi = this.apiService.getInstance(); + return alfrescoApi.activiti.contentApi.getContentThumbnailUrl(contentId); + } + getRestFieldValues(taskId: string, field: string): Observable { let alfrescoApi = this.apiService.getInstance(); return Observable.fromPromise(alfrescoApi.activiti.taskApi.getRestFieldValues(taskId, field));