From 3644ba8b7c565bbb3678c418e02944e0c8fe6a80 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Thu, 14 Nov 2019 14:04:21 +0000 Subject: [PATCH] [DW-1486] form versioning and cloud service enhancements (#5248) * support form versions retrieval * rework cloud services, reduce code duplication * revert app config changes * fix api spelling error * support task form versioning * turn TaskDetailsCloudModel into interface * remove commented code * fix test * update tests * remove useless provider declarations --- .../start-task-form-cloud.e2e.ts | 4 +- .../task-list-properties.e2e.ts | 6 +- .../forms/checkbox-visibility-condition.ts | 4 +- e2e/resources/forms/custom-date-form.ts | 2 +- .../forms/tab-visibility-conditions.ts | 14 +- .../content-metadata-config.factory.spec.ts | 7 +- ...property-groups-translator.service.spec.ts | 3 +- .../content-node-share.dialog.spec.ts | 2 - .../content-node-share.directive.spec.ts | 5 +- .../directives/node-lock.directive.spec.ts | 7 - .../node-permission-dialog.service.spec.ts | 3 +- .../widget-visibility-cloud.service.mock.ts | 2 +- .../form/widget-visibility.service.mock.ts | 2 +- .../components/form-cloud.component.spec.ts | 17 +- .../form/components/form-cloud.component.ts | 67 +++--- ...efinition-selector-cloud.component.spec.ts | 3 +- .../form-definition-selector-cloud.model.ts | 2 +- .../form/services/form-cloud.service.spec.ts | 5 +- .../lib/form/services/form-cloud.service.ts | 205 ++++++------------ ...-definition-selector-cloud.service.spec.ts | 6 +- .../form-definition-selector-cloud.service.ts | 50 +---- .../src/lib/process-services-cloud.module.ts | 2 - .../services/process-header-cloud.service.ts | 35 +-- .../services/process-list-cloud.service.ts | 29 +-- .../start-process-cloud.component.html | 11 +- .../services/start-process-cloud.service.ts | 53 ++--- .../src/lib/services/base-cloud.service.ts | 101 ++++++++- .../user-preference-cloud.service.spec.ts | 4 +- .../services/user-preference-cloud.service.ts | 72 ++---- .../task/services/start-task-cloud.service.ts | 52 ++--- .../lib/task/services/task-cloud.service.ts | 178 ++++----------- .../models/task-details-cloud.model.ts | 123 +++-------- .../components/task-form-cloud.component.html | 1 + .../task-form-cloud.component.spec.ts | 22 +- .../components/task-form-cloud.component.ts | 37 ++-- .../components/task-header-cloud.component.ts | 12 +- .../mocks/task-details-cloud.mock.ts | 144 ++++++------ .../services/task-list-cloud.service.ts | 29 +-- .../src/lib/form/form.component.ts | 1 - .../pages/task-list-cloud-component.page.ts | 4 +- 40 files changed, 502 insertions(+), 824 deletions(-) diff --git a/e2e/process-services-cloud/start-task-form-cloud.e2e.ts b/e2e/process-services-cloud/start-task-form-cloud.e2e.ts index f670a113e2..5a27aaa1cc 100644 --- a/e2e/process-services-cloud/start-task-form-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-form-cloud.e2e.ts @@ -170,8 +170,8 @@ describe('Start Task Form', () => { await uploadActions.deleteFileOrFolder(uploadedFolder.entry.id); await apiService.login(testUser.email, testUser.password); const tasksService = new TasksService(apiService); - const standAloneTaskId = await tasksService.getTaskId(standaloneTaskName, candidateBaseApp); - await tasksService.deleteTask(standAloneTaskId, candidateBaseApp); + const standaloneTaskId = await tasksService.getTaskId(standaloneTaskName, candidateBaseApp); + await tasksService.deleteTask(standaloneTaskId, candidateBaseApp); await apiService.login(browser.params.identityAdmin.email, browser.params.identityAdmin.password); await identityService.deleteIdentityUser(testUser.idIdentityService); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 228452f778..d9d6dba5a8 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -103,7 +103,7 @@ describe('Edit task filters and task list properties', () => { 'taskName', 'parentTaskId', 'priority', - 'standAlone', + 'standalone', 'owner', 'processDefinitionId', 'processInstanceId', @@ -120,7 +120,7 @@ describe('Edit task filters and task list properties', () => { 'processInstanceId', 'parentTaskId', 'priority', - 'standAlone', + 'standalone', 'owner', 'assignee' ], @@ -460,7 +460,7 @@ describe('Edit task filters and task list properties', () => { }); - it('[C307114] Should display tasks sorted by standAlone when standAlone is selected from sort dropdown', async () => { + it('[C307114] Should display tasks sorted by standalone when standalone is selected from sort dropdown', async () => { await tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee(); await tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ALL'); await tasksCloudDemoPage.editTaskFilterCloudComponent().setSortFilterDropDown('StandAlone'); diff --git a/e2e/resources/forms/checkbox-visibility-condition.ts b/e2e/resources/forms/checkbox-visibility-condition.ts index 2f5d355b71..2989f70451 100644 --- a/e2e/resources/forms/checkbox-visibility-condition.ts +++ b/e2e/resources/forms/checkbox-visibility-condition.ts @@ -22,7 +22,7 @@ export const checkboxVisibilityFormJson = { name: 'test', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [], fields: [ @@ -217,7 +217,7 @@ export const multipleCheckboxVisibilityFormJson = { name: 'newtestform', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [], fields: [ diff --git a/e2e/resources/forms/custom-date-form.ts b/e2e/resources/forms/custom-date-form.ts index 04825517c7..f94423ff75 100644 --- a/e2e/resources/forms/custom-date-form.ts +++ b/e2e/resources/forms/custom-date-form.ts @@ -128,7 +128,7 @@ export const customDateFormAPS2 = `{ "name":"APS2customDateForm", "description":"", "version":0, - "standAlone":true, + "standalone":true, "formDefinition":{ "tabs":[ diff --git a/e2e/resources/forms/tab-visibility-conditions.ts b/e2e/resources/forms/tab-visibility-conditions.ts index dcfd1527a9..07b1637db9 100644 --- a/e2e/resources/forms/tab-visibility-conditions.ts +++ b/e2e/resources/forms/tab-visibility-conditions.ts @@ -22,7 +22,7 @@ export const tabFieldValueVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -115,7 +115,7 @@ export const tabVarValueVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -181,7 +181,7 @@ export const tabVarFieldVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -280,7 +280,7 @@ export const tabFieldFieldVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -389,7 +389,7 @@ export const tabFieldVarVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -488,7 +488,7 @@ export const tabVarVarVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { @@ -560,7 +560,7 @@ export const tabNextOperatorsVisibilityJson = { name: 'tabvisibility', description: '', version: 0, - standAlone: true, + standalone: true, formDefinition: { tabs: [ { diff --git a/lib/content-services/src/lib/content-metadata/services/config/content-metadata-config.factory.spec.ts b/lib/content-services/src/lib/content-metadata/services/config/content-metadata-config.factory.spec.ts index 59c444dbe8..2be46acbe4 100644 --- a/lib/content-services/src/lib/content-metadata/services/config/content-metadata-config.factory.spec.ts +++ b/lib/content-services/src/lib/content-metadata/services/config/content-metadata-config.factory.spec.ts @@ -35,14 +35,11 @@ describe('ContentMetadataConfigFactory', () => { HttpClientModule ], providers: [ - ContentMetadataConfigFactory, - AppConfigService, { provide: LogService, useValue: { - error: () => { + error: () => {} } } - } ] }); @@ -53,7 +50,7 @@ describe('ContentMetadataConfigFactory', () => { describe('get', () => { - let logService; + let logService: LogService; beforeEach(async(() => { logService = TestBed.get(LogService); diff --git a/lib/content-services/src/lib/content-metadata/services/property-groups-translator.service.spec.ts b/lib/content-services/src/lib/content-metadata/services/property-groups-translator.service.spec.ts index f499ef0bc2..3963ddf182 100644 --- a/lib/content-services/src/lib/content-metadata/services/property-groups-translator.service.spec.ts +++ b/lib/content-services/src/lib/content-metadata/services/property-groups-translator.service.spec.ts @@ -43,10 +43,9 @@ describe('PropertyGroupTranslatorService', () => { providers: [ { provide: LogService, useValue: { - error: () => { + error: () => {} } } - } ] }); diff --git a/lib/content-services/src/lib/content-node-share/content-node-share.dialog.spec.ts b/lib/content-services/src/lib/content-node-share/content-node-share.dialog.spec.ts index edbd309c48..aaf7c63236 100644 --- a/lib/content-services/src/lib/content-node-share/content-node-share.dialog.spec.ts +++ b/lib/content-services/src/lib/content-node-share/content-node-share.dialog.spec.ts @@ -53,8 +53,6 @@ describe('ShareDialogComponent', () => { ContentNodeShareModule ], providers: [ - NodesApiService, - SharedLinksApiService, { provide: AppConfigService, useClass: AppConfigServiceMock }, { provide: NotificationService, useValue: notificationServiceMock }, { provide: MatDialogRef, useValue: { close: () => {}} }, diff --git a/lib/content-services/src/lib/content-node-share/content-node-share.directive.spec.ts b/lib/content-services/src/lib/content-node-share/content-node-share.directive.spec.ts index 4446d38e4e..abfc7d4e98 100644 --- a/lib/content-services/src/lib/content-node-share/content-node-share.directive.spec.ts +++ b/lib/content-services/src/lib/content-node-share/content-node-share.directive.spec.ts @@ -22,7 +22,7 @@ import { ComponentFixture } from '@angular/core/testing'; import { Component } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { ContentTestingModule } from '../testing/content.testing.module'; -import { setupTestBed, CoreModule, SharedLinksApiService } from '@alfresco/adf-core'; +import { setupTestBed, CoreModule } from '@alfresco/adf-core'; import { ContentNodeShareModule } from './content-node-share.module'; @Component({ @@ -60,9 +60,6 @@ describe('NodeSharedDirective', () => { ], declarations: [ NodeShareTestComponent - ], - providers: [ - SharedLinksApiService ] }); diff --git a/lib/content-services/src/lib/directives/node-lock.directive.spec.ts b/lib/content-services/src/lib/directives/node-lock.directive.spec.ts index 71f4d58b94..c688accd7b 100644 --- a/lib/content-services/src/lib/directives/node-lock.directive.spec.ts +++ b/lib/content-services/src/lib/directives/node-lock.directive.spec.ts @@ -21,9 +21,7 @@ import { Component, DebugElement } from '@angular/core'; import { NodeLockDirective } from './node-lock.directive'; import { Node } from '@alfresco/js-api'; -import { NodeActionsService } from '../document-list/services/node-actions.service'; import { ContentNodeDialogService } from '../content-node-selector/content-node-dialog.service'; -import { DocumentListService } from '../document-list/services/document-list.service'; import { CoreModule, setupTestBed } from '@alfresco/adf-core'; const fakeNode: Node = { @@ -49,11 +47,6 @@ describe('NodeLock Directive', () => { imports: [ CoreModule.forRoot() ], - providers: [ - NodeActionsService, - ContentNodeDialogService, - DocumentListService - ], declarations: [ TestComponent, NodeLockDirective diff --git a/lib/content-services/src/lib/permission-manager/services/node-permission-dialog.service.spec.ts b/lib/content-services/src/lib/permission-manager/services/node-permission-dialog.service.spec.ts index e8834cb5da..fe53eb1338 100644 --- a/lib/content-services/src/lib/permission-manager/services/node-permission-dialog.service.spec.ts +++ b/lib/content-services/src/lib/permission-manager/services/node-permission-dialog.service.spec.ts @@ -34,8 +34,7 @@ describe('NodePermissionDialogService', () => { let contentService: ContentService; setupTestBed({ - imports: [ContentTestingModule], - providers: [NodePermissionService] + imports: [ContentTestingModule] }); beforeEach(() => { diff --git a/lib/core/mock/form/widget-visibility-cloud.service.mock.ts b/lib/core/mock/form/widget-visibility-cloud.service.mock.ts index eeec4d72d6..01245459d6 100644 --- a/lib/core/mock/form/widget-visibility-cloud.service.mock.ts +++ b/lib/core/mock/form/widget-visibility-cloud.service.mock.ts @@ -960,7 +960,7 @@ export const headerVisibilityCond: any = { 'name': 'text_form', 'description': '', 'version': 0, - 'standAlone': true, + 'standalone': true, 'formDefinition': { 'tabs': [], 'fields': [ diff --git a/lib/core/mock/form/widget-visibility.service.mock.ts b/lib/core/mock/form/widget-visibility.service.mock.ts index 833e2f9837..46fa24d365 100644 --- a/lib/core/mock/form/widget-visibility.service.mock.ts +++ b/lib/core/mock/form/widget-visibility.service.mock.ts @@ -1006,7 +1006,7 @@ export const tabInvalidFormVisibility: any = { 'name': 'tab-visibility', 'description': '', 'version': 0, - 'standAlone': true, + 'standalone': true, 'tabs': [ { 'id': 'a8a4718d-5019-4852-9645-bba9b8253d86', diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index bda5b5e50e..d5d8f6b7e5 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -44,7 +44,7 @@ describe('FormCloudComponent', () => { visibilityService = new WidgetVisibilityService(null, logService); spyOn(visibilityService, 'refreshVisibility').and.stub(); spyOn(formRenderingService, 'setComponentTypeResolver').and.returnValue(true); - formCloudService = new FormCloudService(null, new AppConfigService(null), logService); + formCloudService = new FormCloudService(null, new AppConfigService(null)); formService = new FormService(null, null, logService); formComponent = new FormCloudComponent(formCloudService, formService, null, formRenderingService, visibilityService); @@ -206,9 +206,10 @@ describe('FormCloudComponent', () => { formComponent.appName = appName; formComponent.formId = formId; + formComponent.appVersion = 1; formComponent.loadForm(); - expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); + expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId, 1); }); it('should refresh visibility when the form is loaded', () => { @@ -218,9 +219,10 @@ describe('FormCloudComponent', () => { formComponent.appName = appName; formComponent.formId = formId; + formComponent.appVersion = 1; formComponent.loadForm(); - expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId); + expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId, 1); expect(visibilityService.refreshVisibility).toHaveBeenCalled(); }); @@ -230,10 +232,11 @@ describe('FormCloudComponent', () => { const appName = 'test-app'; formComponent.appName = appName; + formComponent.appVersion = 1; const change = new SimpleChange(null, taskId, true); formComponent.ngOnChanges({ 'taskId': change }); - expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(appName, taskId); + expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(appName, taskId, 1); }); it('should call the process storage to retrieve the folder with only the taskId', fakeAsync(() => { @@ -281,10 +284,11 @@ describe('FormCloudComponent', () => { const appName = 'test-app'; formComponent.appName = appName; + formComponent.appVersion = 1; const change = new SimpleChange(null, formId, true); formComponent.ngOnChanges({ 'formId': change }); - expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); + expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId, 1); }); it('should not get form on load', () => { @@ -432,7 +436,7 @@ describe('FormCloudComponent', () => { spyOn(formCloudService, 'getTaskForm').and.returnValue(of({ taskId: taskId, selectedOutcome: 'custom-outcome' })); formComponent.formLoaded.subscribe(() => { - expect(formCloudService.getTaskForm).toHaveBeenCalledWith(appName, taskId); + expect(formCloudService.getTaskForm).toHaveBeenCalledWith(appName, taskId, 1); expect(formComponent.form).toBeDefined(); expect(formComponent.form.taskId).toBe(taskId); done(); @@ -440,6 +444,7 @@ describe('FormCloudComponent', () => { formComponent.appName = appName; formComponent.taskId = taskId; + formComponent.appVersion = 1; formComponent.loadForm(); }); diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts index 15e6ed5a8f..1ef821363f 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -53,6 +53,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, @Input() appName: string; + @Input() + appVersion?: number; + /** Task id to fetch corresponding form and values. */ @Input() formId: string; @@ -122,24 +125,25 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, ngOnChanges(changes: SimpleChanges) { const appName = changes['appName']; + if (appName && appName.currentValue) { if (this.taskId) { this.getFormDefinitionWithFolderTask(this.appName, this.taskId, this.processInstanceId); } else if (this.formId) { - this.getFormById(appName.currentValue, this.formId); + this.getFormById(appName.currentValue, this.formId, this.appVersion); } return; } const formId = changes['formId']; if (formId && formId.currentValue && this.appName) { - this.getFormById(this.appName, formId.currentValue); + this.getFormById(this.appName, formId.currentValue, this.appVersion); return; } const taskId = changes['taskId']; if (taskId && taskId.currentValue && this.appName) { - this.getFormByTaskId(this.appName, taskId.currentValue); + this.getFormByTaskId(this.appName, taskId.currentValue, this.appVersion); return; } @@ -159,9 +163,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, loadForm() { if (this.appName && this.taskId) { - this.getFormByTaskId(this.appName, this.taskId); + this.getFormByTaskId(this.appName, this.taskId, this.appVersion); } else if (this.appName && this.formId) { - this.getFormById(this.appName, this.formId); + this.getFormById(this.appName, this.formId, this.appVersion); } } @@ -182,35 +186,38 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null'; } - getFormByTaskId(appName: string, taskId: string): Promise { + getFormByTaskId(appName: string, taskId: string, version?: number): Promise { return new Promise(resolve => { - forkJoin(this.formCloudService.getTaskForm(appName, taskId), - this.formCloudService.getTaskVariables(appName, taskId)) - .pipe(takeUntil(this.onDestroy$)) - .subscribe( - (data) => { - this.formCloudRepresentationJSON = data[0]; - this.formCloudRepresentationJSON.processVariables = data[1]; - this.data = data[1]; - const parsedForm = this.parseForm(this.formCloudRepresentationJSON); - this.visibilityService.refreshVisibility( parsedForm); - parsedForm.validateForm(); - this.form = parsedForm; - this.onFormLoaded(this.form); - resolve(this.form); - }, - (error) => { - this.handleError(error); - // reject(error); - resolve(null); - } - ); + forkJoin( + this.formCloudService.getTaskForm(appName, taskId, version), + this.formCloudService.getTaskVariables(appName, taskId) + ) + .pipe(takeUntil(this.onDestroy$)) + .subscribe( + (data) => { + this.formCloudRepresentationJSON = data[0]; + this.formCloudRepresentationJSON.processVariables = data[1]; + this.data = data[1]; + + const parsedForm = this.parseForm(this.formCloudRepresentationJSON); + this.visibilityService.refreshVisibility( parsedForm); + parsedForm.validateForm(); + this.form = parsedForm; + + this.onFormLoaded(this.form); + resolve(this.form); + }, + (error) => { + this.handleError(error); + resolve(null); + } + ); }); } - getFormById(appName: string, formId: string) { + getFormById(appName: string, formId: string, appVersion?: number) { this.formCloudService - .getForm(appName, formId) + .getForm(appName, formId, appVersion) .pipe( map((form: any) => { const flattenForm = {...form.formRepresentation, ...form.formRepresentation.formDefinition}; @@ -238,7 +245,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, async getFormDefinitionWithFolder(appName: string, taskId: string, processInstanceId: string) { try { - await this.getFormByTaskId(appName, taskId); + await this.getFormByTaskId(appName, taskId, this.appVersion); const hasUploadWidget = ( this.form).hasUpload; if (hasUploadWidget) { diff --git a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts index 452221746e..08b849aefa 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts @@ -16,7 +16,7 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { AlfrescoApiService, AppConfigService, LogService, setupTestBed, StorageService, UserPreferencesService } from '@alfresco/adf-core'; +import { setupTestBed } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { StartTaskCloudTestingModule } from '../../task/start-task/testing/start-task-cloud.testing.module'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; @@ -34,7 +34,6 @@ describe('FormDefinitionCloudComponent', () => { setupTestBed({ imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule], - providers: [FormDefinitionSelectorCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService, UserPreferencesService], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); diff --git a/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts index 845be58160..bad242bdd3 100644 --- a/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts @@ -20,5 +20,5 @@ export interface FormDefinitionSelectorCloudModel { name?: string; description?: string; version?: string; - standAlone?: string; + standalone?: string; } diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts index 3c7d61b3e8..2cf711f8fa 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts @@ -18,7 +18,7 @@ import { TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { FormCloudService } from './form-cloud.service'; -import { AlfrescoApiService, CoreModule, setupTestBed, AppConfigService } from '@alfresco/adf-core'; +import { AlfrescoApiService, CoreModule, setupTestBed } from '@alfresco/adf-core'; import { of } from 'rxjs'; declare let jasmine: any; @@ -42,8 +42,7 @@ describe('Form Cloud service', () => { imports: [ NoopAnimationsModule, CoreModule.forRoot() - ], - providers: [FormCloudService, AlfrescoApiService, AppConfigService] + ] }); beforeEach(() => { diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index 721a5799eb..2d1d74f10c 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -16,11 +16,11 @@ */ import { Injectable } from '@angular/core'; -import { AlfrescoApiService, LogService, FormValues, AppConfigService, FormOutcomeModel, FormFieldOption, FormModel } from '@alfresco/adf-core'; -import { throwError, Observable, from } from 'rxjs'; -import { catchError, map, switchMap } from 'rxjs/operators'; +import { AlfrescoApiService, FormValues, AppConfigService, FormOutcomeModel, FormFieldOption, FormModel } from '@alfresco/adf-core'; +import { Observable, from } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model'; -import { SaveFormRepresentation, CompleteFormRepresentation } from '@alfresco/js-api'; +import { CompleteFormRepresentation } from '@alfresco/js-api'; import { TaskVariableCloud, ProcessStorageCloudModel } from '../models/task-variable-cloud.model'; import { BaseCloudService } from '../../services/base-cloud.service'; @@ -29,37 +29,35 @@ import { BaseCloudService } from '../../services/base-cloud.service'; }) export class FormCloudService extends BaseCloudService { - contentTypes = ['application/json']; - accepts = ['application/json']; - returnType = Object; - constructor( - private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, - private logService: LogService + apiService: AlfrescoApiService, + appConfigService: AppConfigService ) { - super(); - - this.contextRoot = this.appConfigService.get('bpmHost', ''); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** * Gets the form definition of a task. * @param appName Name of the app * @param taskId ID of the target task + * @param version Version of the form * @returns Form definition */ - getTaskForm(appName: string, taskId: string): Observable { + getTaskForm(appName: string, taskId: string, version?: number): Observable { return this.getTask(appName, taskId).pipe( - switchMap((task: TaskDetailsCloudModel) => { - return this.getForm(appName, task.formKey).pipe( - map((form: any) => { - const flattenForm = {...form.formRepresentation, ...form.formRepresentation.formDefinition}; + switchMap(task => { + return this.getForm(appName, task.formKey, version).pipe( + map(form => { + const flattenForm = { + ...form.formRepresentation, + ...form.formRepresentation.formDefinition, + taskId: task.id, + taskName: task.name, + processDefinitionId: task.processDefinitionId, + processInstanceId: task.processInstanceId + }; delete flattenForm.formDefinition; - flattenForm.taskId = task.id; - flattenForm.taskName = task.name; - flattenForm.processDefinitionId = task.processDefinitionId; - flattenForm.processInstanceId = task.processInstanceId; return flattenForm; }) ); @@ -72,24 +70,19 @@ export class FormCloudService extends BaseCloudService { * @param appName Name of the app * @param taskId ID of the target task * @param formId ID of the form to save - * @param formValues Form values object + * @param values Form values object * @returns Updated task details */ - saveTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues): Observable { - const apiUrl = this.buildSaveFormUrl(appName, formId); - const saveFormRepresentation = {values: formValues, taskId: taskId, processInstanceId: processInstanceId}; - return from(this.apiService - .getInstance() - .oauth2Auth.callCustomApi(apiUrl, 'POST', - null, null, null, - null, saveFormRepresentation, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + saveTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, values: FormValues): Observable { + const apiUrl = `${this.getBasePath(appName)}/form/v1/forms/${formId}/save`; + const saveFormRepresentation: any = { + values, + taskId, + processInstanceId + }; + + return this.post(apiUrl, saveFormRepresentation).pipe( + map((res: any) => res.entry) ); } @@ -106,10 +99,7 @@ export class FormCloudService extends BaseCloudService { '', {overwrite: true} )).pipe( - map((res: any) => { - return (res.entry); - }), - catchError((err) => this.handleError(err)) + map((res: any) => res.entry) ); } @@ -123,24 +113,14 @@ export class FormCloudService extends BaseCloudService { * @returns Updated task details */ completeTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues, outcome: string): Observable { - const apiUrl = this.buildSubmitFormUrl(appName, formId); - const completeFormRepresentation: any = {values: formValues, taskId: taskId, processInstanceId: processInstanceId}; + const apiUrl = `${this.getBasePath(appName)}/form/v1/forms/${formId}/submit`; + const completeFormRepresentation = {values: formValues, taskId: taskId, processInstanceId: processInstanceId}; if (outcome) { completeFormRepresentation.outcome = outcome; } - return from(this.apiService - .getInstance() - .oauth2Auth.callCustomApi(apiUrl, 'POST', - null, null, null, - null, completeFormRepresentation, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + return this.post(apiUrl, completeFormRepresentation).pipe( + map((res: any) => res.entry) ); } @@ -151,36 +131,20 @@ export class FormCloudService extends BaseCloudService { * @returns Details of the task */ getTask(appName: string, taskId: string): Observable { - const apiUrl = this.buildGetTaskUrl(appName, taskId); - return from(this.apiService - .getInstance() - .oauth2Auth.callCustomApi(apiUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + const apiUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; + + return this.get(apiUrl).pipe( + map((res: any) => res.entry) ); } getProcessStorageFolderTask(appName: string, taskId: string, processInstanceId: string): Observable { const apiUrl = this.buildFolderTask(appName, taskId, processInstanceId); - return from(this.apiService - .getInstance() - .oauth2Auth.callCustomApi(apiUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + + return this.get(apiUrl).pipe( map((res: any) => { return new ProcessStorageCloudModel(res); - }), - catchError((err) => this.handleError(err)) + }) ); } @@ -191,19 +155,12 @@ export class FormCloudService extends BaseCloudService { * @returns Task variables */ getTaskVariables(appName: string, taskId: string): Observable { - const apiUrl = this.buildGetTaskVariablesUrl(appName, taskId); - return from(this.apiService - .getInstance() - .oauth2Auth.callCustomApi(apiUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + const apiUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/variables`; + + return this.get(apiUrl).pipe( map((res: any) => { return res.list.entries.map((variable) => new TaskVariableCloud(variable.entry)); - }), - catchError((err) => this.handleError(err)) + }) ); } @@ -211,23 +168,17 @@ export class FormCloudService extends BaseCloudService { * Gets a form definition. * @param appName Name of the app * @param formKey key of the target task + * @param version Version of the form * @returns Form definition */ - getForm(appName: string, formKey: string): Observable { - const apiUrl = this.buildGetFormUrl(appName, formKey); - const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}; + getForm(appName: string, formKey: string, version?: number): Observable { + let url = `${this.getBasePath(appName)}/form/v1/forms/${formKey}`; - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - apiUrl, 'GET', pathParams, queryParams, - headerParams, formParams, bodyParam, - this.contentTypes, this.accepts, this.returnType, null, null) - ).pipe( - catchError((err) => this.handleError(err)) - ); + if (version !== undefined) { + url += `/versions/${version}`; + } + + return this.get(url); } /** @@ -236,18 +187,7 @@ export class FormCloudService extends BaseCloudService { * @returns Array of FormFieldOption object */ getDropDownJsonData(url: string): Observable { - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(url, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return res; - }), - catchError((err) => this.handleError(err)) - ); + return this.get(url); } /** @@ -259,7 +199,10 @@ export class FormCloudService extends BaseCloudService { */ parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormModel { if (json) { - const flattenForm = {...json.formRepresentation, ...json.formRepresentation.formDefinition}; + const flattenForm = { + ...json.formRepresentation, + ...json.formRepresentation.formDefinition + }; delete flattenForm.formDefinition; const formValues: FormValues = {}; @@ -282,35 +225,9 @@ export class FormCloudService extends BaseCloudService { return null; } - private buildGetTaskUrl(appName: string, taskId: string): string { - return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; - } - - private buildGetFormUrl(appName: string, formKey: string): string { - return `${this.getBasePath(appName)}/form/v1/forms/${formKey}`; - } - - private buildSaveFormUrl(appName: string, formId: string): string { - return `${this.getBasePath(appName)}/form/v1/forms/${formId}/save`; - } - - private buildSubmitFormUrl(appName: string, formId: string): string { - return `${this.getBasePath(appName)}/form/v1/forms/${formId}/submit`; - } - - private buildGetTaskVariablesUrl(appName: string, taskId: string): string { - return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/variables`; - } - private buildFolderTask(appName: string, taskId: string, processInstanceId: string): string { return processInstanceId ? `${this.getBasePath(appName)}/process-storage/v1/folders/${processInstanceId}/${taskId}` : `${this.getBasePath(appName)}/process-storage/v1/folders/${taskId}`; } - - private handleError(error: any) { - this.logService.error(error); - return throwError(error || 'Server error'); - } - } diff --git a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.spec.ts index a577a79b0f..5d25cc7ebc 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.spec.ts @@ -29,7 +29,7 @@ const responseBody = [ name: 'Form 1', description: '', version: 0, - standAlone: true + standalone: true } }, { @@ -38,7 +38,7 @@ const responseBody = [ name: 'Form 2', description: '', version: 0, - standAlone: false + standalone: false } }, { @@ -87,7 +87,7 @@ describe('Form Definition Selector Cloud Service', () => { }); }); - it('should fetch only standAlone enabled forms when getStandAloneTaskForms is called', (done) => { + it('should fetch only standalone enabled forms when getStandaloneTaskForms is called', (done) => { oauth2Auth.callCustomApi.and.returnValue(Promise.resolve(responseBody)); service.getStandAloneTaskForms(appName).subscribe((result) => { diff --git a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts index 2d4969965b..d6bb569e16 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts @@ -16,10 +16,10 @@ */ import { Injectable } from '@angular/core'; -import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; -import { catchError, map } from 'rxjs/operators'; +import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; +import { map } from 'rxjs/operators'; import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; -import { from, Observable, throwError } from 'rxjs'; +import { from, Observable } from 'rxjs'; import { BaseCloudService } from '../../services/base-cloud.service'; @Injectable({ @@ -27,15 +27,10 @@ import { BaseCloudService } from '../../services/base-cloud.service'; }) export class FormDefinitionSelectorCloudService extends BaseCloudService { - contentTypes = ['application/json']; - accepts = ['application/json']; - returnType = Object; - - constructor(private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, - private logService: LogService) { - super(); - this.contextRoot = this.appConfigService.get('bpmHost', ''); + constructor(apiService: AlfrescoApiService, + appConfigService: AppConfigService) { + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -44,24 +39,14 @@ export class FormDefinitionSelectorCloudService extends BaseCloudService { * @returns Details of the forms */ getForms(appName: string): Observable { + const url = `${this.getBasePath(appName)}/form/v1/forms`; - const queryUrl = this.buildGetFormsUrl(appName); - const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - queryUrl, 'GET', pathParams, queryParams, - headerParams, formParams, bodyParam, - contentTypes, accepts, null, null) - ).pipe( + return this.get(url).pipe( map((data: any) => { return data.map((formData: any) => { return formData.formRepresentation; }); - }), - catchError((err) => this.handleError(err)) + }) ); } @@ -73,19 +58,8 @@ export class FormDefinitionSelectorCloudService extends BaseCloudService { getStandAloneTaskForms(appName: string): Observable { return from(this.getForms(appName)).pipe( map((data: any) => { - return data.filter((formData: any) => formData.standAlone || formData.standAlone === undefined); - }), - catchError((err) => this.handleError(err)) + return data.filter((formData: any) => formData.standalone || formData.standalone === undefined); + }) ); - - } - - private buildGetFormsUrl(appName: string): any { - return `${this.getBasePath(appName)}/form/v1/forms`; - } - - private handleError(error: any) { - this.logService.error(error); - return throwError(error || 'Server error'); } } diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index c9d71bc41f..1a617db1e4 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -23,7 +23,6 @@ import { ProcessCloudModule } from './process/process-cloud.module'; import { GroupCloudModule } from './group/group-cloud.module'; import { FormCloudModule } from './form/form-cloud.module'; import { TaskFormModule } from './task/task-form/task-form.module'; -import { BaseCloudService } from './services/base-cloud.service'; import { UserPreferenceCloudService } from './services/user-preference-cloud.service'; import { LocalPreferenceCloudService, @@ -50,7 +49,6 @@ import { source: 'assets/adf-process-services-cloud' } }, - BaseCloudService, UserPreferenceCloudService, LocalPreferenceCloudService, { provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }, diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts index 3f6082cf3c..99ddd05c97 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -17,8 +17,8 @@ import { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; -import { Observable, from, throwError } from 'rxjs'; -import { catchError, map } from 'rxjs/operators'; +import { Observable, throwError } from 'rxjs'; +import { map } from 'rxjs/operators'; import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model'; import { BaseCloudService } from '../../../services/base-cloud.service'; @@ -26,16 +26,12 @@ import { BaseCloudService } from '../../../services/base-cloud.service'; providedIn: 'root' }) export class ProcessHeaderCloudService extends BaseCloudService { - contextRoot: string; - contentTypes = ['application/json']; - accepts = ['application/json']; - returnType = Object; - constructor(private alfrescoApiService: AlfrescoApiService, - private appConfigService: AppConfigService, + constructor(apiService: AlfrescoApiService, + appConfigService: AppConfigService, private logService: LogService) { - super(); - this.contextRoot = this.appConfigService.get('bpmHost', ''); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -46,27 +42,16 @@ export class ProcessHeaderCloudService extends BaseCloudService { */ getProcessInstanceById(appName: string, processInstanceId: string): Observable { if (appName && processInstanceId) { - const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`; - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + const url = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`; + + return this.get(url).pipe( map((res: any) => { return new ProcessInstanceCloud(res.entry); - }), - catchError((err) => this.handleError(err)) + }) ); } else { this.logService.error('AppName and ProcessInstanceId are mandatory for querying a task'); return throwError('AppName/ProcessInstanceId not configured'); } } - - private handleError(error: any) { - this.logService.error(error); - return throwError(error || 'Server error'); - } } diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts index a8302740f5..e6577ddc09 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts @@ -17,20 +17,18 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model'; -import { Observable, from, throwError } from 'rxjs'; +import { Observable, throwError } from 'rxjs'; import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model'; import { BaseCloudService } from '../../../services/base-cloud.service'; @Injectable() export class ProcessListCloudService extends BaseCloudService { - contentTypes = ['application/json']; - accepts = ['application/json']; - - constructor(private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, + constructor(apiService: AlfrescoApiService, + appConfigService: AppConfigService, private logService: LogService) { - super(); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -40,35 +38,27 @@ export class ProcessListCloudService extends BaseCloudService { */ getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable { if (requestNode.appName) { - const queryUrl = this.buildQueryUrl(requestNode); + const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`; const queryParams = this.buildQueryParams(requestNode); const sortingParams = this.buildSortingParam(requestNode.sorting); if (sortingParams) { queryParams['sort'] = sortingParams; } - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, queryParams, null, - null, null, this.contentTypes, - this.accepts, null, null) - ); + + return this.get(queryUrl, queryParams); } else { this.logService.error('Appname is mandatory for querying task'); return throwError('Appname not configured'); } } - private buildQueryUrl(requestNode: ProcessQueryCloudRequestModel): string { - this.contextRoot = this.appConfigService.get('bpmHost', ''); - return `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`; - } - private isPropertyValueValid(requestNode: any, property: string) { return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined; } private buildQueryParams(requestNode: ProcessQueryCloudRequestModel): Object { const queryParam = {}; + for (const property in requestNode) { if (requestNode.hasOwnProperty(property) && !this.isExcludedField(property) && @@ -76,6 +66,7 @@ export class ProcessListCloudService extends BaseCloudService { queryParam[property] = requestNode[property]; } } + return queryParam; } diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html index 3169f55f6f..00a882e614 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html @@ -48,8 +48,15 @@ - diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts index 1427a0cc82..3e8143209e 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts @@ -17,8 +17,8 @@ import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; -import { Observable, from, throwError } from 'rxjs'; -import { map, catchError } from 'rxjs/operators'; +import { Observable, throwError } from 'rxjs'; +import { map } from 'rxjs/operators'; import { ProcessInstanceCloud } from '../models/process-instance-cloud.model'; import { ProcessPayloadCloud } from '../models/process-payload-cloud.model'; import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model'; @@ -29,16 +29,11 @@ import { BaseCloudService } from '../../../services/base-cloud.service'; }) export class StartProcessCloudService extends BaseCloudService { - contextRoot: string; - contentTypes = ['application/json']; - accepts = ['application/json']; - returnType = Object; - - constructor(private alfrescoApiService: AlfrescoApiService, + constructor(apiService: AlfrescoApiService, private logService: LogService, - private appConfigService: AppConfigService) { - super(); - this.contextRoot = this.appConfigService.get('bpmHost', ''); + appConfigService: AppConfigService) { + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -47,21 +42,13 @@ export class StartProcessCloudService extends BaseCloudService { * @returns Array of process definitions */ getProcessDefinitions(appName: string): Observable { - if (appName) { - const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions`; + const url = `${this.getBasePath(appName)}/rb/v1/process-definitions`; - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, null, - null, null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + return this.get(url).pipe( map((res: any) => { return res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry)); - }), - catchError((err) => this.handleProcessError(err)) + }) ); } else { this.logService.error('AppName is mandatory for querying task'); @@ -72,26 +59,14 @@ export class StartProcessCloudService extends BaseCloudService { /** * Starts a process based on a process definition, name, form values or variables. * @param appName name of the Application - * @param requestPayload Details of the process (definition key, name, variables, etc) + * @param payload Details of the process (definition key, name, variables, etc) * @returns Details of the process instance just started */ - startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable { + startProcess(appName: string, payload: ProcessPayloadCloud): Observable { + const url = `${this.getBasePath(appName)}/rb/v1/process-instances`; - const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-instances`; - - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'POST', - null, null, - null, null, requestPayload, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((processInstance) => new ProcessInstanceCloud(processInstance)), - catchError((err) => this.handleProcessError(err)) + return this.post(url, payload).pipe( + map(processInstance => new ProcessInstanceCloud(processInstance)) ); } - - private handleProcessError(error: any) { - return throwError(error || 'Server error'); - } } diff --git a/lib/process-services-cloud/src/lib/services/base-cloud.service.ts b/lib/process-services-cloud/src/lib/services/base-cloud.service.ts index b253d34c3c..0934cc38d3 100644 --- a/lib/process-services-cloud/src/lib/services/base-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/services/base-cloud.service.ts @@ -15,21 +15,102 @@ * limitations under the License. */ -import { Injectable } from '@angular/core'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { from, Observable } from 'rxjs'; + +export interface CallApiParams { + path: string; + httpMethod: string; + pathParams?: any; + queryParams?: any; + headerParams?: any; + formParams?: any; + bodyParam?: any; + contentTypes?: string[]; + accepts?: string[]; + returnType?: any; + contextRoot?: string; + responseType?: string; +} -@Injectable() export class BaseCloudService { - public contextRoot: string; + protected contextRoot: string; - getBasePath(appName: string) { - if (this.isValidAppName(appName)) { - return `${this.contextRoot}/${appName}`; - } - return this.contextRoot; + protected defaultParams: CallApiParams = { + path: '', + httpMethod: '', + contentTypes: ['application/json'], + accepts: ['application/json'], + returnType: Object + }; + + constructor(protected apiService: AlfrescoApiService) {} + + getBasePath(appName: string): string { + return appName + ? `${this.contextRoot}/${appName}` + : this.contextRoot; } - private isValidAppName(appName: string) { - return appName && appName !== ''; + protected post(url: string, data?: T): Observable { + return from( + this.callApi({ + ...this.defaultParams, + path: url, + httpMethod: 'POST', + bodyParam: data + }) + ); + } + + protected put(url: string, data?: T): Observable { + return from( + this.callApi({ + ...this.defaultParams, + path: url, + httpMethod: 'PUT', + bodyParam: data + }) + ); + } + + protected delete(url: string): Observable { + return from( + this.callApi({ + ...this.defaultParams, + path: url, + httpMethod: 'DELETE' + }) + ); + } + + protected get(url: string, queryParams?: any): Observable { + return from( + this.callApi({ + ...this.defaultParams, + path: url, + httpMethod: 'GET', + queryParams + }) + ); + } + + protected callApi(params: CallApiParams): Promise { + return this.apiService.getInstance() + .oauth2Auth.callCustomApi( + params.path, + params.httpMethod, + params.pathParams, + params.queryParams, + params.headerParams, + params.formParams, + params.bodyParam, + params.contentTypes, + params.accepts, + params.returnType, + params.contextRoot, + params.responseType + ); } } diff --git a/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.spec.ts index 8fab2bdeb6..47b3df421d 100644 --- a/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.spec.ts @@ -18,7 +18,7 @@ import { TestBed, async } from '@angular/core/testing'; import { UserPreferenceCloudService } from './user-preference-cloud.service'; -import { setupTestBed, CoreModule, AlfrescoApiServiceMock, AppConfigService, LogService, AlfrescoApiService } from '@alfresco/adf-core'; +import { setupTestBed, CoreModule, AlfrescoApiServiceMock, AlfrescoApiService } from '@alfresco/adf-core'; import { mockPreferences, getMockPreference, createMockPreference, updateMockPreference } from '../mock/user-preference.mock'; describe('PreferenceService', () => { @@ -52,7 +52,6 @@ describe('PreferenceService', () => { CoreModule.forRoot() ], providers: [ - UserPreferenceCloudService, AppConfigService, LogService, { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock } ] }); @@ -60,7 +59,6 @@ describe('PreferenceService', () => { beforeEach(async(() => { service = TestBed.get(UserPreferenceCloudService); alfrescoApiMock = TestBed.get(AlfrescoApiService); - service.contextRoot = 'http://{{domain}}.com'; getInstanceSpy = spyOn(alfrescoApiMock, 'getInstance').and.returnValue(apiMock(mockPreferences)); })); diff --git a/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.ts b/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.ts index 5b2998124f..24cb01cf3c 100644 --- a/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/services/user-preference-cloud.service.ts @@ -18,21 +18,18 @@ import { Injectable } from '@angular/core'; import { PreferenceCloudServiceInterface } from './preference-cloud.interface'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; -import { from, throwError, Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { throwError, Observable } from 'rxjs'; import { BaseCloudService } from './base-cloud.service'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class UserPreferenceCloudService extends BaseCloudService implements PreferenceCloudServiceInterface { - contentTypes = ['application/json']; - accepts = ['application/json']; - constructor( - private alfrescoApiService: AlfrescoApiService, - private appConfigService: AppConfigService, + apiService: AlfrescoApiService, + appConfigService: AppConfigService, private logService: LogService) { - super(); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -42,13 +39,8 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref */ getPreferences(appName: string): Observable { if (appName) { - const uri = this.buildPreferenceServiceUri(appName); - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(uri, 'GET', - null, null, null, - null, null, this.contentTypes, - this.accepts, null, null) - ); + const url = `${this.getBasePath(appName)}/preference/v1/preferences`; + return this.get(url); } else { this.logService.error('Appname is mandatory for querying preferences'); return throwError('Appname not configured'); @@ -63,14 +55,8 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref */ getPreferenceByKey(appName: string, key: string): Observable { if (appName) { - const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; - return from( - this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(uri, 'GET', - null, null, null, - null, null, this.contentTypes, - this.accepts, null, null) - ).pipe(catchError((error) => throwError(error))); + const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`; + return this.get(url); } else { this.logService.error('Appname and key are mandatory for querying preference'); return throwError('Appname not configured'); @@ -86,17 +72,10 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref */ createPreference(appName: string, key: string, newPreference: any): Observable { if (appName) { - const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; - const requestPayload = JSON.stringify(newPreference); - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(uri, 'PUT', - null, null, - null, null, requestPayload, - this.contentTypes, this.accepts, - Object, null, null) - ).pipe( - catchError((err) => this.handleProcessError(err)) - ); + const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`; + const payload = JSON.stringify(newPreference); + + return this.put(url, payload); } else { this.logService.error('Appname and key are mandatory for creating preference'); return throwError('Appname not configured'); @@ -122,30 +101,11 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref */ deletePreference(appName: string, key: string): Observable { if (appName) { - const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; - return from(this.alfrescoApiService.getInstance() - .oauth2Auth.callCustomApi(uri, 'DELETE', - null, null, null, - null, null, this.contentTypes, - this.accepts, null, null, null) - ); + const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`; + return this.delete(url); } else { this.logService.error('Appname and key are mandatory to delete preference'); return throwError('Appname not configured'); } } - - /** - * Creates preference uri - * @param appName Name of the target app - * @returns String of preference service uri - */ - private buildPreferenceServiceUri(appName: string): string { - this.contextRoot = this.appConfigService.get('bpmHost', ''); - return `${this.getBasePath(appName)}/preference/v1/preferences`; - } - - private handleProcessError(error: any) { - return throwError(error || 'Server error'); - } } diff --git a/lib/process-services-cloud/src/lib/task/services/start-task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/start-task-cloud.service.ts index e75dcd7aba..f5c249c9b0 100644 --- a/lib/process-services-cloud/src/lib/task/services/start-task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/start-task-cloud.service.ts @@ -16,21 +16,22 @@ */ import { Injectable } from '@angular/core'; -import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; -import { Observable, from, throwError } from 'rxjs'; -import { map, catchError } from 'rxjs/operators'; +import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model'; import { BaseCloudService } from '../../services/base-cloud.service'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class StartTaskCloudService extends BaseCloudService { constructor( - private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, - private logService: LogService - ) { super(); } + apiService: AlfrescoApiService, + appConfigService: AppConfigService) { + super(apiService); + this.contextRoot = appConfigService.get('bpmHost'); + } /** * @deprecated in 3.5.0, use TaskCloudService instead. @@ -39,37 +40,12 @@ export class StartTaskCloudService extends BaseCloudService { * @returns Details of the newly created task */ createNewTask(taskDetails: TaskDetailsCloudModel): Observable { - const queryUrl = this.buildCreateTaskUrl(taskDetails.appName); - const bodyParam = JSON.stringify(this.buildRequestBody(taskDetails)); - const pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; + const url = `${this.getBasePath(taskDetails.appName)}/rb/v1/tasks`; + const payload = JSON.stringify(new StartTaskCloudRequestModel(taskDetails)); - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - queryUrl, 'POST', pathParams, queryParams, - headerParams, formParams, bodyParam, - contentTypes, accepts, null, null) - ).pipe( - map((response: StartTaskCloudResponseModel) => { - return new TaskDetailsCloudModel(response.entry); - }), - catchError((err) => this.handleError(err)) + return this.post(url, payload) + .pipe( + map(response => response.entry) ); } - - private buildCreateTaskUrl(appName: string): any { - this.contextRoot = this.appConfigService.get('bpmHost'); - return `${this.getBasePath(appName)}/rb/v1/tasks`; - } - - private buildRequestBody(taskDetails: any) { - return new StartTaskCloudRequestModel(taskDetails); - } - - private handleError(error: any) { - this.logService.error(error); - return throwError(error || 'Server error'); - } } diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index 22a58a5380..cf8ba45ce9 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -17,8 +17,8 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core'; -import { from, throwError, Observable, of, Subject } from 'rxjs'; -import { catchError, map } from 'rxjs/operators'; +import { throwError, Observable, of, Subject } from 'rxjs'; +import { map } from 'rxjs/operators'; import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model'; import { BaseCloudService } from '../../services/base-cloud.service'; import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; @@ -28,22 +28,16 @@ import { StartTaskCloudRequestModel } from '../start-task/models/start-task-clou }) export class TaskCloudService extends BaseCloudService { - contentTypes = ['application/json']; - accepts = ['application/json']; - returnType = Object; - - private dataChangesDetected = new Subject(); - dataChangesDetected$: Observable; + dataChangesDetected$ = new Subject(); constructor( - private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, + apiService: AlfrescoApiService, + appConfigService: AppConfigService, private logService: LogService, private identityUserService: IdentityUserService ) { - super(); - this.contextRoot = this.appConfigService.get('bpmHost', ''); - this.dataChangesDetected$ = this.dataChangesDetected.asObservable(); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } /** @@ -54,21 +48,10 @@ export class TaskCloudService extends BaseCloudService { */ completeTask(appName: string, taskId: string): Observable { if (appName && taskId) { - const queryUrl = this.buildCompleteTaskUrl(appName, taskId); - const bodyParam = { 'payloadType': 'CompleteTaskPayload' }; - const pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; + const url = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/complete`; + const payload = { 'payloadType': 'CompleteTaskPayload' }; - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - queryUrl, 'POST', pathParams, queryParams, - headerParams, formParams, bodyParam, - contentTypes, accepts, null, null) - ).pipe( - catchError((err) => this.handleError(err)) - ); + return this.post(url, payload); } else { this.logService.error('AppName and TaskId are mandatory for complete a task'); return throwError('AppName/TaskId not configured'); @@ -81,7 +64,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Boolean value if the task can be completed */ canCompleteTask(taskDetails: TaskDetailsCloudModel): boolean { - return taskDetails && taskDetails.isAssigned() && this.isAssignedToMe(taskDetails.assignee); + return taskDetails && taskDetails.status === 'ASSIGNED' && this.isAssignedToMe(taskDetails.assignee); } /** @@ -90,7 +73,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Boolean value if the task is editable */ isTaskEditable(taskDetails: TaskDetailsCloudModel): boolean { - return taskDetails && taskDetails.isAssigned() && this.isAssignedToMe(taskDetails.assignee); + return taskDetails && taskDetails.status === 'ASSIGNED' && this.isAssignedToMe(taskDetails.assignee); } /** @@ -99,7 +82,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Boolean value if the task can be completed */ canClaimTask(taskDetails: TaskDetailsCloudModel): boolean { - return taskDetails && taskDetails.canClaimTask(); + return taskDetails && taskDetails.status === 'CREATED'; } /** @@ -109,7 +92,7 @@ export class TaskCloudService extends BaseCloudService { */ canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean { const currentUser = this.identityUserService.getCurrentUserInfo().username; - return taskDetails && taskDetails.canUnclaimTask(currentUser); + return taskDetails && taskDetails.status === 'ASSIGNED' && taskDetails.assignee === currentUser; } /** @@ -122,18 +105,12 @@ export class TaskCloudService extends BaseCloudService { claimTask(appName: string, taskId: string, assignee: string): Observable { if (appName && taskId) { const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'POST', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + + return this.post(queryUrl).pipe( map((res: any) => { - this.dataChangesDetected.next(); - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + this.dataChangesDetected$.next(); + return res.entry; + }) ); } else { this.logService.error('AppName and TaskId are mandatory for querying a task'); @@ -150,18 +127,12 @@ export class TaskCloudService extends BaseCloudService { unclaimTask(appName: string, taskId: string): Observable { if (appName && taskId) { const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'POST', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( + + return this.post(queryUrl).pipe( map((res: any) => { - this.dataChangesDetected.next(); - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + this.dataChangesDetected$.next(); + return res.entry; + }) ); } else { this.logService.error('AppName and TaskId are mandatory for querying a task'); @@ -178,17 +149,9 @@ export class TaskCloudService extends BaseCloudService { getTaskById(appName: string, taskId: string): Observable { if (appName && taskId) { const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + + return this.get(queryUrl).pipe( + map((res: any) => res.entry) ); } else { this.logService.error('AppName and TaskId are mandatory for querying a task'); @@ -202,23 +165,12 @@ export class TaskCloudService extends BaseCloudService { * @returns Details of the newly created task */ createNewTask(startTaskRequest: StartTaskCloudRequestModel, appName: string): Observable { - const queryUrl = this.buildCreateTaskUrl(appName); - const bodyParam = JSON.stringify(this.buildRequestBody(startTaskRequest)); - const pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; + const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks`; + const payload = JSON.stringify(new StartTaskCloudRequestModel(startTaskRequest)); - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - queryUrl, 'POST', pathParams, queryParams, - headerParams, formParams, bodyParam, - contentTypes, accepts, null, null) - ).pipe( - map((response: StartTaskCloudResponseModel) => { - return new TaskDetailsCloudModel(response.entry); - }), - catchError((err) => this.handleError(err)) + return this.post(queryUrl, payload) + .pipe( + map(response => response.entry) ); } @@ -226,25 +178,16 @@ export class TaskCloudService extends BaseCloudService { * Updates the details (name, description, due date) for a task. * @param appName Name of the app * @param taskId ID of the task to update - * @param updatePayload Data to update the task + * @param payload Data to update the task * @returns Updated task details */ - updateTask(appName: string, taskId: string, updatePayload: any): Observable { + updateTask(appName: string, taskId: string, payload: any): Observable { if (appName && taskId) { - - updatePayload.payloadType = 'UpdateTaskPayload'; + payload.payloadType = 'UpdateTaskPayload'; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'PUT', - null, null, null, - null, updatePayload, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((res: any) => { - return new TaskDetailsCloudModel(res.entry); - }), - catchError((err) => this.handleError(err)) + + return this.put(queryUrl, payload).pipe( + map((res: any) => res.entry) ); } else { this.logService.error('AppName and TaskId are mandatory for querying a task'); @@ -261,18 +204,7 @@ export class TaskCloudService extends BaseCloudService { getCandidateUsers(appName: string, taskId: string): Observable { if (appName && taskId) { const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((response: string[]) => { - return response; - }), - catchError((err) => this.handleError(err)) - ); + return this.get(queryUrl); } else { this.logService.error('AppName and TaskId are mandatory to get candidate user'); return of([]); @@ -288,18 +220,7 @@ export class TaskCloudService extends BaseCloudService { getCandidateGroups(appName: string, taskId: string): Observable { if (appName && taskId) { const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`; - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, null, null, - null, null, - this.contentTypes, this.accepts, - this.returnType, null, null) - ).pipe( - map((response: string[]) => { - return response; - }), - catchError((err) => this.handleError(err)) - ); + return this.get(queryUrl); } else { this.logService.error('AppName and TaskId are mandatory to get candidate groups'); return of([]); @@ -310,23 +231,4 @@ export class TaskCloudService extends BaseCloudService { const currentUser = this.identityUserService.getCurrentUserInfo().username; return assignee === currentUser; } - - private buildCompleteTaskUrl(appName: string, taskId: string): string { - return `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/complete`; - } - - private buildCreateTaskUrl(appName: string): string { - this.contextRoot = this.appConfigService.get('bpmHost'); - return `${this.getBasePath(appName)}/rb/v1/tasks`; - } - - private buildRequestBody(startTaskRequest: StartTaskCloudRequestModel) { - return new StartTaskCloudRequestModel(startTaskRequest); - } - - private handleError(error: any) { - this.logService.error(error); - return throwError(error || 'Server error'); - } - } diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts index bc75de9d0d..c640a25027 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts @@ -15,98 +15,45 @@ * limitations under the License. */ -export class TaskDetailsCloudModel { - - id: string; - name: string; - appName: string; - assignee: string; - appVersion: string; - createdDate: Date; - claimedDate: Date; - completedDate: Date; - formKey: any; - category: any; - description: string; - dueDate: Date; - lastModified: Date; - lastModifiedTo: Date; - lastModifiedFrom: Date; - owner: any; - parentTaskId: number; - priority: number; - processDefinitionId: string; - processInstanceId: string; - status: TaskStatusEnum; - standalone: boolean; - candidateUsers: string[]; - candidateGroups: string[]; - managerOfCandidateGroup: boolean; - memberOfCandidateGroup: boolean; - memberOfCandidateUsers: boolean; +export interface TaskDetailsCloudModel { + id?: string; + name?: string; + appName?: string; + assignee?: string; + appVersion?: number; + createdDate?: Date; + claimedDate?: Date; + completedDate?: Date; + formKey?: any; + category?: any; + description?: string; + dueDate?: Date; + lastModified?: Date; + lastModifiedTo?: Date; + lastModifiedFrom?: Date; + owner?: any; + parentTaskId?: number; + priority?: number; + processDefinitionId?: string; + processInstanceId?: string; + status?: TaskStatus; + standalone?: boolean; + candidateUsers?: string[]; + candidateGroups?: string[]; + managerOfCandidateGroup?: boolean; + memberOfCandidateGroup?: boolean; + memberOfCandidateUsers?: boolean; processDefinitionDeploymentId?: string; - - constructor(obj?: any) { - if (obj) { - this.id = obj.id || null; - this.name = obj.name || null; - this.appName = obj.appName || null; - this.assignee = obj.assignee || null; - this.appVersion = obj.appVersion || null; - this.createdDate = obj.createdDate || null; - this.claimedDate = obj.claimedDate || null; - this.completedDate = obj.completedDate || null; - this.formKey = obj.formKey || null; - this.description = obj.description || null; - this.dueDate = obj.dueDate || null; - this.lastModified = obj.lastModified || null; - this.lastModifiedTo = obj.lastModifiedTo || null; - this.lastModifiedFrom = obj.lastModifiedFrom || null; - this.owner = obj.owner || null; - this.parentTaskId = obj.parentTaskId || null; - this.priority = obj.priority || null; - this.processDefinitionId = obj.processDefinitionId || null; - this.processInstanceId = obj.processInstanceId || null; - this.status = obj.status || null; - this.standalone = obj.standalone || null; - this.candidateUsers = obj.candidateUsers || null; - this.candidateGroups = obj.candidateGroups || null; - this.managerOfCandidateGroup = obj.managerOfCandidateGroup || null; - this.memberOfCandidateGroup = obj.memberOfCandidateGroup || null; - this.memberOfCandidateUsers = obj.memberOfCandidateUsers || null; - } - } - - isCompleted(): boolean { - return this.status === TaskStatusEnum.COMPLETED; - } - - isCancelled(): boolean { - return this.status === TaskStatusEnum.CANCELLED; - } - - isAssigned(): boolean { - return this.status === TaskStatusEnum.ASSIGNED; - } - - canClaimTask(): boolean { - return this.status === TaskStatusEnum.CREATED; - } - - canUnclaimTask(user: string): boolean { - return this.isAssigned() && this.assignee === user; - } } export interface StartTaskCloudResponseModel { entry: TaskDetailsCloudModel; } -export enum TaskStatusEnum { - COMPLETED= 'COMPLETED', - DELETED = 'DELETED', - CREATED = 'CREATED', - ASSIGNED = 'ASSIGNED', - SUSPENDED = 'SUSPENDED', - CANCELLED = 'CANCELLED' -} +export type TaskStatus = | + 'COMPLETED' | + 'DELETED' | + 'CREATED' | + 'ASSIGNED' | + 'SUSPENDED' | + 'CANCELLED'; diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html index 6bf69edd0a..9a5c83fc04 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html @@ -1,6 +1,7 @@
{ identityUserService = TestBed.get(IdentityUserService); getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' }); taskCloudService = TestBed.get(TaskCloudService); - getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(taskDetails)); spyOn(taskCloudService, 'getCandidateGroups').and.returnValue(of([])); spyOn(taskCloudService, 'getCandidateUsers').and.returnValue(of([])); @@ -153,8 +153,8 @@ describe('TaskFormCloudComponent', () => { it('should not show unclaim button when status is not ASSIGNED', async(() => { component.appName = 'app1'; component.taskId = 'task1'; - taskDetails.status = ''; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + taskDetails.status = undefined; + getTaskSpy.and.returnValue(of(taskDetails)); component.loadTask(); fixture.detectChanges(); @@ -168,7 +168,7 @@ describe('TaskFormCloudComponent', () => { component.appName = 'app1'; component.taskId = 'task1'; taskDetails.status = 'CREATED'; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + getTaskSpy.and.returnValue(of(taskDetails)); component.loadTask(); fixture.detectChanges(); @@ -181,8 +181,8 @@ describe('TaskFormCloudComponent', () => { it('should not show claim button when status is not CREATED', async(() => { component.appName = 'app1'; component.taskId = 'task1'; - taskDetails.status = ''; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + taskDetails.status = undefined; + getTaskSpy.and.returnValue(of(taskDetails)); component.loadTask(); fixture.detectChanges(); @@ -306,7 +306,7 @@ describe('TaskFormCloudComponent', () => { it('should emit taskClaimed when task is claimed', (done) => { spyOn(taskCloudService, 'claimTask').and.returnValue(of({})); taskDetails.status = 'CREATED'; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + getTaskSpy.and.returnValue(of(taskDetails)); component.appName = 'app1'; component.taskId = 'task1'; @@ -354,7 +354,7 @@ describe('TaskFormCloudComponent', () => { const reloadSpy = spyOn(component, 'loadTask').and.callThrough(); taskDetails.status = 'CREATED'; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + getTaskSpy.and.returnValue(of(taskDetails)); component.appName = 'app1'; component.taskId = 'task1'; @@ -373,7 +373,7 @@ describe('TaskFormCloudComponent', () => { spyOn(component, 'hasCandidateUsers').and.returnValue(true); taskDetails.status = 'ASSIGNED'; - getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + getTaskSpy.and.returnValue(of(taskDetails)); component.appName = 'app1'; component.taskId = 'task1'; diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index da5cf13cf1..1a5c150b2e 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -120,32 +120,25 @@ export class TaskFormCloudComponent implements OnChanges { this.loadTask(); return; } - } loadTask() { this.loading = true; - this.taskCloudService.getTaskById(this.appName, this.taskId).subscribe((details: TaskDetailsCloudModel) => { - this.taskDetails = details; - this.loading = false; - }); - this.taskCloudService.getCandidateUsers(this.appName, this.taskId).subscribe((users: string[]) => { - if (users) { - this.candidateUsers = users; - } - }); + this.taskCloudService + .getTaskById(this.appName, this.taskId) + .subscribe(details => { + this.taskDetails = details; + this.loading = false; + }); - this.taskCloudService.getCandidateGroups(this.appName, this.taskId).subscribe((groups: string[]) => { - if (groups) { - this.candidateGroups = groups; - } - }); + this.taskCloudService + .getCandidateUsers(this.appName, this.taskId) + .subscribe(users => this.candidateUsers = users || []); - } - - private reloadTask() { - this.loadTask(); + this.taskCloudService + .getCandidateGroups(this.appName, this.taskId) + .subscribe(groups => this.candidateGroups = groups || []); } hasForm(): boolean { @@ -186,17 +179,17 @@ export class TaskFormCloudComponent implements OnChanges { } onCompleteTask() { - this.reloadTask(); + this.loadTask(); this.taskCompleted.emit(this.taskId); } onClaimTask() { - this.reloadTask(); + this.loadTask(); this.taskClaimed.emit(this.taskId); } onUnclaimTask() { - this.reloadTask(); + this.loadTask(); this.taskUnclaimed.emit(this.taskId); } diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index 0049e593e2..a2b85fd096 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -28,7 +28,7 @@ import { CardViewUpdateService, CardViewDatetimeItemModel } from '@alfresco/adf-core'; -import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model'; +import { TaskDetailsCloudModel, TaskStatus } from '../../start-task/models/task-details-cloud.model'; import { Router } from '@angular/router'; import { TaskCloudService } from '../../services/task-cloud.service'; import { Subject } from 'rxjs'; @@ -62,7 +62,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges { @Output() error: EventEmitter = new EventEmitter(); - taskDetails: TaskDetailsCloudModel = new TaskDetailsCloudModel(); + taskDetails: TaskDetailsCloudModel = {}; properties: CardViewItem[]; inEdit: boolean = false; parentTaskName: string; @@ -99,7 +99,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges { } ngOnChanges() { - this.taskDetails = new TaskDetailsCloudModel(); + this.taskDetails = {}; if (this.appName && this.taskId) { this.loadTaskDetailsById(this.appName, this.taskId); } else { @@ -278,8 +278,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges { ); } - isCompleted() { - return this.taskDetails && this.taskDetails.status && this.taskDetails.status.toUpperCase() === TaskStatusEnum.COMPLETED; + isCompleted(): boolean { + return this.taskDetails && this.taskDetails.status === 'COMPLETED'; } hasAssignee(): boolean { @@ -299,7 +299,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges { } isClickable(): boolean { - const states = [TaskStatusEnum.ASSIGNED, TaskStatusEnum.CREATED, TaskStatusEnum.SUSPENDED]; + const states: TaskStatus[] = ['ASSIGNED', 'CREATED', 'SUSPENDED']; return states.includes(this.taskDetails.status); } diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts index be9db86c9c..2428e8ab73 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts @@ -17,80 +17,74 @@ import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; -export const assignedTaskDetailsCloudMock = new TaskDetailsCloudModel( - { - 'appName': 'task-app', - 'appVersion': '', - 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', - 'assignee': 'AssignedTaskUser', - 'name': 'This is a new task ', - 'description': 'This is the description ', - 'createdDate': 1545048055900, - 'dueDate': Date.now(), - 'claimedDate': null, - 'priority': 5, - 'category': null, - 'processDefinitionId': null, - 'processInstanceId': null, - 'status': 'ASSIGNED', - 'owner': 'ownerUser', - 'parentTaskId': null, - 'formKey': null, - 'lastModified': 1545048055900, - 'lastModifiedTo': null, - 'lastModifiedFrom': null, - 'standalone': true - } -); +export const assignedTaskDetailsCloudMock: TaskDetailsCloudModel = { + 'appName': 'task-app', + 'appVersion': 1, + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'AssignedTaskUser', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': new Date(1545048055900), + 'dueDate': new Date(), + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'ASSIGNED', + 'owner': 'ownerUser', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': new Date(1545048055900), + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standalone': true +}; -export const createdTaskDetailsCloudMock = new TaskDetailsCloudModel( - { - 'appName': 'task-app', - 'appVersion': '', - 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', - 'assignee': 'CreatedTaskUser', - 'name': 'This is a new task ', - 'description': 'This is the description ', - 'createdDate': 1545048055900, - 'dueDate': 1545091200000, - 'claimedDate': null, - 'priority': 5, - 'category': null, - 'processDefinitionId': null, - 'processInstanceId': null, - 'status': 'CREATED', - 'owner': 'ownerUser', - 'parentTaskId': null, - 'formKey': null, - 'lastModified': 1545048055900, - 'lastModifiedTo': null, - 'lastModifiedFrom': null, - 'standalone': true - } -); +export const createdTaskDetailsCloudMock: TaskDetailsCloudModel = { + 'appName': 'task-app', + 'appVersion': 1, + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'CreatedTaskUser', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': new Date(1545048055900), + 'dueDate': new Date(1545091200000), + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'CREATED', + 'owner': 'ownerUser', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': new Date(1545048055900), + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standalone': true +}; -export const emptyOwnerTaskDetailsCloudMock = new TaskDetailsCloudModel( - { - 'appName': 'task-app', - 'appVersion': '', - 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', - 'assignee': 'AssignedTaskUser', - 'name': 'This is a new task ', - 'description': 'This is the description ', - 'createdDate': 1545048055900, - 'dueDate': 1545091200000, - 'claimedDate': null, - 'priority': 5, - 'category': null, - 'processDefinitionId': null, - 'processInstanceId': null, - 'status': 'ASSIGNED', - 'owner': null, - 'parentTaskId': null, - 'formKey': null, - 'lastModified': 1545048055900, - 'lastModifiedTo': null, - 'lastModifiedFrom': null, - 'standalone': true - } -); +export const emptyOwnerTaskDetailsCloudMock: TaskDetailsCloudModel = { + 'appName': 'task-app', + 'appVersion': 1, + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'AssignedTaskUser', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': new Date(1545048055900), + 'dueDate': new Date(1545091200000), + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'ASSIGNED', + 'owner': null, + 'parentTaskId': null, + 'formKey': null, + 'lastModified': new Date(1545048055900), + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standalone': true +}; diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts index 1ead073c4e..4d461e4d9a 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts @@ -18,53 +18,40 @@ import { Injectable } from '@angular/core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; -import { Observable, from, throwError } from 'rxjs'; +import { Observable, throwError } from 'rxjs'; import { TaskListCloudSortingModel } from '../models/task-list-sorting.model'; import { BaseCloudService } from '../../../services/base-cloud.service'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class TaskListCloudService extends BaseCloudService { - constructor(private apiService: AlfrescoApiService, - private appConfigService: AppConfigService, + constructor(apiService: AlfrescoApiService, + appConfigService: AppConfigService, private logService: LogService) { - super(); + super(apiService); + this.contextRoot = appConfigService.get('bpmHost', ''); } - contentTypes = ['application/json']; - accepts = ['application/json']; - /** * Finds a task using an object with optional query properties. * @param requestNode Query object * @returns Task information */ getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable { - if (requestNode.appName) { - const queryUrl = this.buildQueryUrl(requestNode); + const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/tasks`; const queryParams = this.buildQueryParams(requestNode); const sortingParams = this.buildSortingParam(requestNode.sorting); if (sortingParams) { queryParams['sort'] = sortingParams; } - return from(this.apiService.getInstance() - .oauth2Auth.callCustomApi(queryUrl, 'GET', - null, queryParams, null, - null, null, ['application/json'], - ['application/json'], null, null) - ); + return this.get(queryUrl, queryParams); } else { this.logService.error('Appname is mandatory for querying task'); return throwError('Appname not configured'); } } - private buildQueryUrl(requestNode: TaskQueryCloudRequestModel) { - this.contextRoot = this.appConfigService.get('bpmHost', ''); - return `${this.getBasePath(requestNode.appName)}/query/v1/tasks`; - } - private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object { const queryParam: Object = {}; for (const property in requestNode) { diff --git a/lib/process-services/src/lib/form/form.component.ts b/lib/process-services/src/lib/form/form.component.ts index 5c281df16e..5a7e5bd8c6 100644 --- a/lib/process-services/src/lib/form/form.component.ts +++ b/lib/process-services/src/lib/form/form.component.ts @@ -200,7 +200,6 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro }, (error) => { this.handleError(error); - // reject(error); resolve(null); } ); diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index 3b9ff4c450..3b49edb89d 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -28,7 +28,7 @@ const column = { assignee: 'Assignee', parentTaskId: 'ParentTaskId', priority: 'Priority', - standAlone: 'StandAlone', + standalone: 'Standalone', owner: 'Owner' }; @@ -149,7 +149,7 @@ export class TaskListCloudComponentPage { } async getAllRowsByStandAloneColumn() { - return this.dataTable.getAllRowsColumnValues(column.standAlone); + return this.dataTable.getAllRowsColumnValues(column.standalone); } async getAllRowsByOwnerColumn() {