[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
This commit is contained in:
Denys Vuika
2019-11-14 14:04:21 +00:00
committed by Eugenio Romano
parent 1f768eb22f
commit 3644ba8b7c
40 changed files with 502 additions and 824 deletions

View File

@@ -170,8 +170,8 @@ describe('Start Task Form', () => {
await uploadActions.deleteFileOrFolder(uploadedFolder.entry.id); await uploadActions.deleteFileOrFolder(uploadedFolder.entry.id);
await apiService.login(testUser.email, testUser.password); await apiService.login(testUser.email, testUser.password);
const tasksService = new TasksService(apiService); const tasksService = new TasksService(apiService);
const standAloneTaskId = await tasksService.getTaskId(standaloneTaskName, candidateBaseApp); const standaloneTaskId = await tasksService.getTaskId(standaloneTaskName, candidateBaseApp);
await tasksService.deleteTask(standAloneTaskId, candidateBaseApp); await tasksService.deleteTask(standaloneTaskId, candidateBaseApp);
await apiService.login(browser.params.identityAdmin.email, browser.params.identityAdmin.password); await apiService.login(browser.params.identityAdmin.email, browser.params.identityAdmin.password);
await identityService.deleteIdentityUser(testUser.idIdentityService); await identityService.deleteIdentityUser(testUser.idIdentityService);

View File

@@ -103,7 +103,7 @@ describe('Edit task filters and task list properties', () => {
'taskName', 'taskName',
'parentTaskId', 'parentTaskId',
'priority', 'priority',
'standAlone', 'standalone',
'owner', 'owner',
'processDefinitionId', 'processDefinitionId',
'processInstanceId', 'processInstanceId',
@@ -120,7 +120,7 @@ describe('Edit task filters and task list properties', () => {
'processInstanceId', 'processInstanceId',
'parentTaskId', 'parentTaskId',
'priority', 'priority',
'standAlone', 'standalone',
'owner', 'owner',
'assignee' '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().clearAssignee();
await tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ALL'); await tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ALL');
await tasksCloudDemoPage.editTaskFilterCloudComponent().setSortFilterDropDown('StandAlone'); await tasksCloudDemoPage.editTaskFilterCloudComponent().setSortFilterDropDown('StandAlone');

View File

@@ -22,7 +22,7 @@ export const checkboxVisibilityFormJson = {
name: 'test', name: 'test',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [], tabs: [],
fields: [ fields: [
@@ -217,7 +217,7 @@ export const multipleCheckboxVisibilityFormJson = {
name: 'newtestform', name: 'newtestform',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [], tabs: [],
fields: [ fields: [

View File

@@ -128,7 +128,7 @@ export const customDateFormAPS2 = `{
"name":"APS2customDateForm", "name":"APS2customDateForm",
"description":"", "description":"",
"version":0, "version":0,
"standAlone":true, "standalone":true,
"formDefinition":{ "formDefinition":{
"tabs":[ "tabs":[

View File

@@ -22,7 +22,7 @@ export const tabFieldValueVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -115,7 +115,7 @@ export const tabVarValueVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -181,7 +181,7 @@ export const tabVarFieldVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -280,7 +280,7 @@ export const tabFieldFieldVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -389,7 +389,7 @@ export const tabFieldVarVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -488,7 +488,7 @@ export const tabVarVarVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {
@@ -560,7 +560,7 @@ export const tabNextOperatorsVisibilityJson = {
name: 'tabvisibility', name: 'tabvisibility',
description: '', description: '',
version: 0, version: 0,
standAlone: true, standalone: true,
formDefinition: { formDefinition: {
tabs: [ tabs: [
{ {

View File

@@ -35,14 +35,11 @@ describe('ContentMetadataConfigFactory', () => {
HttpClientModule HttpClientModule
], ],
providers: [ providers: [
ContentMetadataConfigFactory,
AppConfigService,
{ {
provide: LogService, useValue: { provide: LogService, useValue: {
error: () => { error: () => {}
} }
} }
}
] ]
}); });
@@ -53,7 +50,7 @@ describe('ContentMetadataConfigFactory', () => {
describe('get', () => { describe('get', () => {
let logService; let logService: LogService;
beforeEach(async(() => { beforeEach(async(() => {
logService = TestBed.get(LogService); logService = TestBed.get(LogService);

View File

@@ -43,10 +43,9 @@ describe('PropertyGroupTranslatorService', () => {
providers: [ providers: [
{ {
provide: LogService, useValue: { provide: LogService, useValue: {
error: () => { error: () => {}
} }
} }
}
] ]
}); });

View File

@@ -53,8 +53,6 @@ describe('ShareDialogComponent', () => {
ContentNodeShareModule ContentNodeShareModule
], ],
providers: [ providers: [
NodesApiService,
SharedLinksApiService,
{ provide: AppConfigService, useClass: AppConfigServiceMock }, { provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: NotificationService, useValue: notificationServiceMock }, { provide: NotificationService, useValue: notificationServiceMock },
{ provide: MatDialogRef, useValue: { close: () => {}} }, { provide: MatDialogRef, useValue: { close: () => {}} },

View File

@@ -22,7 +22,7 @@ import { ComponentFixture } from '@angular/core/testing';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { ContentTestingModule } from '../testing/content.testing.module'; 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'; import { ContentNodeShareModule } from './content-node-share.module';
@Component({ @Component({
@@ -60,9 +60,6 @@ describe('NodeSharedDirective', () => {
], ],
declarations: [ declarations: [
NodeShareTestComponent NodeShareTestComponent
],
providers: [
SharedLinksApiService
] ]
}); });

View File

@@ -21,9 +21,7 @@ import { Component, DebugElement } from '@angular/core';
import { NodeLockDirective } from './node-lock.directive'; import { NodeLockDirective } from './node-lock.directive';
import { Node } from '@alfresco/js-api'; 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 { 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'; import { CoreModule, setupTestBed } from '@alfresco/adf-core';
const fakeNode: Node = <Node> { const fakeNode: Node = <Node> {
@@ -49,11 +47,6 @@ describe('NodeLock Directive', () => {
imports: [ imports: [
CoreModule.forRoot() CoreModule.forRoot()
], ],
providers: [
NodeActionsService,
ContentNodeDialogService,
DocumentListService
],
declarations: [ declarations: [
TestComponent, TestComponent,
NodeLockDirective NodeLockDirective

View File

@@ -34,8 +34,7 @@ describe('NodePermissionDialogService', () => {
let contentService: ContentService; let contentService: ContentService;
setupTestBed({ setupTestBed({
imports: [ContentTestingModule], imports: [ContentTestingModule]
providers: [NodePermissionService]
}); });
beforeEach(() => { beforeEach(() => {

View File

@@ -960,7 +960,7 @@ export const headerVisibilityCond: any = {
'name': 'text_form', 'name': 'text_form',
'description': '', 'description': '',
'version': 0, 'version': 0,
'standAlone': true, 'standalone': true,
'formDefinition': { 'formDefinition': {
'tabs': [], 'tabs': [],
'fields': [ 'fields': [

View File

@@ -1006,7 +1006,7 @@ export const tabInvalidFormVisibility: any = {
'name': 'tab-visibility', 'name': 'tab-visibility',
'description': '', 'description': '',
'version': 0, 'version': 0,
'standAlone': true, 'standalone': true,
'tabs': [ 'tabs': [
{ {
'id': 'a8a4718d-5019-4852-9645-bba9b8253d86', 'id': 'a8a4718d-5019-4852-9645-bba9b8253d86',

View File

@@ -44,7 +44,7 @@ describe('FormCloudComponent', () => {
visibilityService = new WidgetVisibilityService(null, logService); visibilityService = new WidgetVisibilityService(null, logService);
spyOn(visibilityService, 'refreshVisibility').and.stub(); spyOn(visibilityService, 'refreshVisibility').and.stub();
spyOn(formRenderingService, 'setComponentTypeResolver').and.returnValue(true); 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); formService = new FormService(null, null, logService);
formComponent = new FormCloudComponent(formCloudService, formService, null, formRenderingService, visibilityService); formComponent = new FormCloudComponent(formCloudService, formService, null, formRenderingService, visibilityService);
@@ -206,9 +206,10 @@ describe('FormCloudComponent', () => {
formComponent.appName = appName; formComponent.appName = appName;
formComponent.formId = formId; formComponent.formId = formId;
formComponent.appVersion = 1;
formComponent.loadForm(); formComponent.loadForm();
expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId, 1);
}); });
it('should refresh visibility when the form is loaded', () => { it('should refresh visibility when the form is loaded', () => {
@@ -218,9 +219,10 @@ describe('FormCloudComponent', () => {
formComponent.appName = appName; formComponent.appName = appName;
formComponent.formId = formId; formComponent.formId = formId;
formComponent.appVersion = 1;
formComponent.loadForm(); formComponent.loadForm();
expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId); expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId, 1);
expect(visibilityService.refreshVisibility).toHaveBeenCalled(); expect(visibilityService.refreshVisibility).toHaveBeenCalled();
}); });
@@ -230,10 +232,11 @@ describe('FormCloudComponent', () => {
const appName = 'test-app'; const appName = 'test-app';
formComponent.appName = appName; formComponent.appName = appName;
formComponent.appVersion = 1;
const change = new SimpleChange(null, taskId, true); const change = new SimpleChange(null, taskId, true);
formComponent.ngOnChanges({ 'taskId': change }); 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(() => { 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'; const appName = 'test-app';
formComponent.appName = appName; formComponent.appName = appName;
formComponent.appVersion = 1;
const change = new SimpleChange(null, formId, true); const change = new SimpleChange(null, formId, true);
formComponent.ngOnChanges({ 'formId': change }); formComponent.ngOnChanges({ 'formId': change });
expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId, 1);
}); });
it('should not get form on load', () => { it('should not get form on load', () => {
@@ -432,7 +436,7 @@ describe('FormCloudComponent', () => {
spyOn(formCloudService, 'getTaskForm').and.returnValue(of({ taskId: taskId, selectedOutcome: 'custom-outcome' })); spyOn(formCloudService, 'getTaskForm').and.returnValue(of({ taskId: taskId, selectedOutcome: 'custom-outcome' }));
formComponent.formLoaded.subscribe(() => { formComponent.formLoaded.subscribe(() => {
expect(formCloudService.getTaskForm).toHaveBeenCalledWith(appName, taskId); expect(formCloudService.getTaskForm).toHaveBeenCalledWith(appName, taskId, 1);
expect(formComponent.form).toBeDefined(); expect(formComponent.form).toBeDefined();
expect(formComponent.form.taskId).toBe(taskId); expect(formComponent.form.taskId).toBe(taskId);
done(); done();
@@ -440,6 +444,7 @@ describe('FormCloudComponent', () => {
formComponent.appName = appName; formComponent.appName = appName;
formComponent.taskId = taskId; formComponent.taskId = taskId;
formComponent.appVersion = 1;
formComponent.loadForm(); formComponent.loadForm();
}); });

View File

@@ -53,6 +53,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
@Input() @Input()
appName: string; appName: string;
@Input()
appVersion?: number;
/** Task id to fetch corresponding form and values. */ /** Task id to fetch corresponding form and values. */
@Input() @Input()
formId: string; formId: string;
@@ -122,24 +125,25 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
const appName = changes['appName']; const appName = changes['appName'];
if (appName && appName.currentValue) { if (appName && appName.currentValue) {
if (this.taskId) { if (this.taskId) {
this.getFormDefinitionWithFolderTask(this.appName, this.taskId, this.processInstanceId); this.getFormDefinitionWithFolderTask(this.appName, this.taskId, this.processInstanceId);
} else if (this.formId) { } else if (this.formId) {
this.getFormById(appName.currentValue, this.formId); this.getFormById(appName.currentValue, this.formId, this.appVersion);
} }
return; return;
} }
const formId = changes['formId']; const formId = changes['formId'];
if (formId && formId.currentValue && this.appName) { if (formId && formId.currentValue && this.appName) {
this.getFormById(this.appName, formId.currentValue); this.getFormById(this.appName, formId.currentValue, this.appVersion);
return; return;
} }
const taskId = changes['taskId']; const taskId = changes['taskId'];
if (taskId && taskId.currentValue && this.appName) { if (taskId && taskId.currentValue && this.appName) {
this.getFormByTaskId(this.appName, taskId.currentValue); this.getFormByTaskId(this.appName, taskId.currentValue, this.appVersion);
return; return;
} }
@@ -159,9 +163,9 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
loadForm() { loadForm() {
if (this.appName && this.taskId) { 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) { } 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'; return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null';
} }
getFormByTaskId(appName: string, taskId: string): Promise<FormModel> { getFormByTaskId(appName: string, taskId: string, version?: number): Promise<FormModel> {
return new Promise<FormModel>(resolve => { return new Promise<FormModel>(resolve => {
forkJoin(this.formCloudService.getTaskForm(appName, taskId), forkJoin(
this.formCloudService.getTaskVariables(appName, taskId)) this.formCloudService.getTaskForm(appName, taskId, version),
.pipe(takeUntil(this.onDestroy$)) this.formCloudService.getTaskVariables(appName, taskId)
.subscribe( )
(data) => { .pipe(takeUntil(this.onDestroy$))
this.formCloudRepresentationJSON = data[0]; .subscribe(
this.formCloudRepresentationJSON.processVariables = data[1]; (data) => {
this.data = data[1]; this.formCloudRepresentationJSON = data[0];
const parsedForm = this.parseForm(this.formCloudRepresentationJSON); this.formCloudRepresentationJSON.processVariables = data[1];
this.visibilityService.refreshVisibility(<any> parsedForm); this.data = data[1];
parsedForm.validateForm();
this.form = parsedForm; const parsedForm = this.parseForm(this.formCloudRepresentationJSON);
this.onFormLoaded(this.form); this.visibilityService.refreshVisibility(<any> parsedForm);
resolve(this.form); parsedForm.validateForm();
}, this.form = parsedForm;
(error) => {
this.handleError(error); this.onFormLoaded(this.form);
// reject(error); resolve(this.form);
resolve(null); },
} (error) => {
); this.handleError(error);
resolve(null);
}
);
}); });
} }
getFormById(appName: string, formId: string) { getFormById(appName: string, formId: string, appVersion?: number) {
this.formCloudService this.formCloudService
.getForm(appName, formId) .getForm(appName, formId, appVersion)
.pipe( .pipe(
map((form: any) => { map((form: any) => {
const flattenForm = {...form.formRepresentation, ...form.formRepresentation.formDefinition}; 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) { async getFormDefinitionWithFolder(appName: string, taskId: string, processInstanceId: string) {
try { try {
await this.getFormByTaskId(appName, taskId); await this.getFormByTaskId(appName, taskId, this.appVersion);
const hasUploadWidget = (<any> this.form).hasUpload; const hasUploadWidget = (<any> this.form).hasUpload;
if (hasUploadWidget) { if (hasUploadWidget) {

View File

@@ -16,7 +16,7 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; 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 { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { StartTaskCloudTestingModule } from '../../task/start-task/testing/start-task-cloud.testing.module'; import { StartTaskCloudTestingModule } from '../../task/start-task/testing/start-task-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -34,7 +34,6 @@ describe('FormDefinitionCloudComponent', () => {
setupTestBed({ setupTestBed({
imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule], imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule],
providers: [FormDefinitionSelectorCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService, UserPreferencesService],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]
}); });

View File

@@ -20,5 +20,5 @@ export interface FormDefinitionSelectorCloudModel {
name?: string; name?: string;
description?: string; description?: string;
version?: string; version?: string;
standAlone?: string; standalone?: string;
} }

View File

@@ -18,7 +18,7 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormCloudService } from './form-cloud.service'; 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'; import { of } from 'rxjs';
declare let jasmine: any; declare let jasmine: any;
@@ -42,8 +42,7 @@ describe('Form Cloud service', () => {
imports: [ imports: [
NoopAnimationsModule, NoopAnimationsModule,
CoreModule.forRoot() CoreModule.forRoot()
], ]
providers: [FormCloudService, AlfrescoApiService, AppConfigService]
}); });
beforeEach(() => { beforeEach(() => {

View File

@@ -16,11 +16,11 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, LogService, FormValues, AppConfigService, FormOutcomeModel, FormFieldOption, FormModel } from '@alfresco/adf-core'; import { AlfrescoApiService, FormValues, AppConfigService, FormOutcomeModel, FormFieldOption, FormModel } from '@alfresco/adf-core';
import { throwError, Observable, from } from 'rxjs'; import { Observable, from } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model'; 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 { TaskVariableCloud, ProcessStorageCloudModel } from '../models/task-variable-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service'; import { BaseCloudService } from '../../services/base-cloud.service';
@@ -29,37 +29,35 @@ import { BaseCloudService } from '../../services/base-cloud.service';
}) })
export class FormCloudService extends BaseCloudService { export class FormCloudService extends BaseCloudService {
contentTypes = ['application/json'];
accepts = ['application/json'];
returnType = Object;
constructor( constructor(
private apiService: AlfrescoApiService, apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService
private logService: LogService
) { ) {
super(); super(apiService);
this.contextRoot = appConfigService.get('bpmHost', '');
this.contextRoot = this.appConfigService.get('bpmHost', '');
} }
/** /**
* Gets the form definition of a task. * Gets the form definition of a task.
* @param appName Name of the app * @param appName Name of the app
* @param taskId ID of the target task * @param taskId ID of the target task
* @param version Version of the form
* @returns Form definition * @returns Form definition
*/ */
getTaskForm(appName: string, taskId: string): Observable<any> { getTaskForm(appName: string, taskId: string, version?: number): Observable<any> {
return this.getTask(appName, taskId).pipe( return this.getTask(appName, taskId).pipe(
switchMap((task: TaskDetailsCloudModel) => { switchMap(task => {
return this.getForm(appName, task.formKey).pipe( return this.getForm(appName, task.formKey, version).pipe(
map((form: any) => { map(form => {
const flattenForm = {...form.formRepresentation, ...form.formRepresentation.formDefinition}; const flattenForm = {
...form.formRepresentation,
...form.formRepresentation.formDefinition,
taskId: task.id,
taskName: task.name,
processDefinitionId: task.processDefinitionId,
processInstanceId: task.processInstanceId
};
delete flattenForm.formDefinition; delete flattenForm.formDefinition;
flattenForm.taskId = task.id;
flattenForm.taskName = task.name;
flattenForm.processDefinitionId = task.processDefinitionId;
flattenForm.processInstanceId = task.processInstanceId;
return flattenForm; return flattenForm;
}) })
); );
@@ -72,24 +70,19 @@ export class FormCloudService extends BaseCloudService {
* @param appName Name of the app * @param appName Name of the app
* @param taskId ID of the target task * @param taskId ID of the target task
* @param formId ID of the form to save * @param formId ID of the form to save
* @param formValues Form values object * @param values Form values object
* @returns Updated task details * @returns Updated task details
*/ */
saveTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues): Observable<TaskDetailsCloudModel> { saveTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, values: FormValues): Observable<TaskDetailsCloudModel> {
const apiUrl = this.buildSaveFormUrl(appName, formId); const apiUrl = `${this.getBasePath(appName)}/form/v1/forms/${formId}/save`;
const saveFormRepresentation = <SaveFormRepresentation> {values: formValues, taskId: taskId, processInstanceId: processInstanceId}; const saveFormRepresentation: any = {
return from(this.apiService values,
.getInstance() taskId,
.oauth2Auth.callCustomApi(apiUrl, 'POST', processInstanceId
null, null, null, };
null, saveFormRepresentation,
this.contentTypes, this.accepts, return this.post(apiUrl, saveFormRepresentation).pipe(
this.returnType, null, null) map((res: any) => res.entry)
).pipe(
map((res: any) => {
return new TaskDetailsCloudModel(res.entry);
}),
catchError((err) => this.handleError(err))
); );
} }
@@ -106,10 +99,7 @@ export class FormCloudService extends BaseCloudService {
'', '',
{overwrite: true} {overwrite: true}
)).pipe( )).pipe(
map((res: any) => { map((res: any) => res.entry)
return (res.entry);
}),
catchError((err) => this.handleError(err))
); );
} }
@@ -123,24 +113,14 @@ export class FormCloudService extends BaseCloudService {
* @returns Updated task details * @returns Updated task details
*/ */
completeTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues, outcome: string): Observable<TaskDetailsCloudModel> { completeTaskForm(appName: string, taskId: string, processInstanceId: string, formId: string, formValues: FormValues, outcome: string): Observable<TaskDetailsCloudModel> {
const apiUrl = this.buildSubmitFormUrl(appName, formId); const apiUrl = `${this.getBasePath(appName)}/form/v1/forms/${formId}/submit`;
const completeFormRepresentation: any = <CompleteFormRepresentation> {values: formValues, taskId: taskId, processInstanceId: processInstanceId}; const completeFormRepresentation = <CompleteFormRepresentation> {values: formValues, taskId: taskId, processInstanceId: processInstanceId};
if (outcome) { if (outcome) {
completeFormRepresentation.outcome = outcome; completeFormRepresentation.outcome = outcome;
} }
return from(this.apiService return this.post(apiUrl, completeFormRepresentation).pipe(
.getInstance() map((res: any) => res.entry)
.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))
); );
} }
@@ -151,36 +131,20 @@ export class FormCloudService extends BaseCloudService {
* @returns Details of the task * @returns Details of the task
*/ */
getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
const apiUrl = this.buildGetTaskUrl(appName, taskId); const apiUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
return from(this.apiService
.getInstance() return this.get(apiUrl).pipe(
.oauth2Auth.callCustomApi(apiUrl, 'GET', map((res: any) => res.entry)
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))
); );
} }
getProcessStorageFolderTask(appName: string, taskId: string, processInstanceId: string): Observable<ProcessStorageCloudModel> { getProcessStorageFolderTask(appName: string, taskId: string, processInstanceId: string): Observable<ProcessStorageCloudModel> {
const apiUrl = this.buildFolderTask(appName, taskId, processInstanceId); const apiUrl = this.buildFolderTask(appName, taskId, processInstanceId);
return from(this.apiService
.getInstance() return this.get(apiUrl).pipe(
.oauth2Auth.callCustomApi(apiUrl, 'GET',
null, null, null,
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
return new ProcessStorageCloudModel(res); return new ProcessStorageCloudModel(res);
}), })
catchError((err) => this.handleError(err))
); );
} }
@@ -191,19 +155,12 @@ export class FormCloudService extends BaseCloudService {
* @returns Task variables * @returns Task variables
*/ */
getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]> { getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]> {
const apiUrl = this.buildGetTaskVariablesUrl(appName, taskId); const apiUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/variables`;
return from(this.apiService
.getInstance() return this.get(apiUrl).pipe(
.oauth2Auth.callCustomApi(apiUrl, 'GET',
null, null, null,
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
return res.list.entries.map((variable) => new TaskVariableCloud(variable.entry)); 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. * Gets a form definition.
* @param appName Name of the app * @param appName Name of the app
* @param formKey key of the target task * @param formKey key of the target task
* @param version Version of the form
* @returns Form definition * @returns Form definition
*/ */
getForm(appName: string, formKey: string): Observable<any> { getForm(appName: string, formKey: string, version?: number): Observable<any> {
const apiUrl = this.buildGetFormUrl(appName, formKey); let url = `${this.getBasePath(appName)}/form/v1/forms/${formKey}`;
const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {},
formParams = {};
return from( if (version !== undefined) {
this.apiService url += `/versions/${version}`;
.getInstance() }
.oauth2Auth.callCustomApi(
apiUrl, 'GET', pathParams, queryParams, return this.get(url);
headerParams, formParams, bodyParam,
this.contentTypes, this.accepts, this.returnType, null, null)
).pipe(
catchError((err) => this.handleError(err))
);
} }
/** /**
@@ -236,18 +187,7 @@ export class FormCloudService extends BaseCloudService {
* @returns Array of FormFieldOption object * @returns Array of FormFieldOption object
*/ */
getDropDownJsonData(url: string): Observable<FormFieldOption[]> { getDropDownJsonData(url: string): Observable<FormFieldOption[]> {
return from(this.apiService.getInstance() return this.get<FormFieldOption[]>(url);
.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))
);
} }
/** /**
@@ -259,7 +199,10 @@ export class FormCloudService extends BaseCloudService {
*/ */
parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormModel { parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormModel {
if (json) { if (json) {
const flattenForm = {...json.formRepresentation, ...json.formRepresentation.formDefinition}; const flattenForm = {
...json.formRepresentation,
...json.formRepresentation.formDefinition
};
delete flattenForm.formDefinition; delete flattenForm.formDefinition;
const formValues: FormValues = {}; const formValues: FormValues = {};
@@ -282,35 +225,9 @@ export class FormCloudService extends BaseCloudService {
return null; 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 { private buildFolderTask(appName: string, taskId: string, processInstanceId: string): string {
return processInstanceId return processInstanceId
? `${this.getBasePath(appName)}/process-storage/v1/folders/${processInstanceId}/${taskId}` ? `${this.getBasePath(appName)}/process-storage/v1/folders/${processInstanceId}/${taskId}`
: `${this.getBasePath(appName)}/process-storage/v1/folders/${taskId}`; : `${this.getBasePath(appName)}/process-storage/v1/folders/${taskId}`;
} }
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
} }

View File

@@ -29,7 +29,7 @@ const responseBody = [
name: 'Form 1', name: 'Form 1',
description: '', description: '',
version: 0, version: 0,
standAlone: true standalone: true
} }
}, },
{ {
@@ -38,7 +38,7 @@ const responseBody = [
name: 'Form 2', name: 'Form 2',
description: '', description: '',
version: 0, 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)); oauth2Auth.callCustomApi.and.returnValue(Promise.resolve(responseBody));
service.getStandAloneTaskForms(appName).subscribe((result) => { service.getStandAloneTaskForms(appName).subscribe((result) => {

View File

@@ -16,10 +16,10 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { catchError, map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; 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'; import { BaseCloudService } from '../../services/base-cloud.service';
@Injectable({ @Injectable({
@@ -27,15 +27,10 @@ import { BaseCloudService } from '../../services/base-cloud.service';
}) })
export class FormDefinitionSelectorCloudService extends BaseCloudService { export class FormDefinitionSelectorCloudService extends BaseCloudService {
contentTypes = ['application/json']; constructor(apiService: AlfrescoApiService,
accepts = ['application/json']; appConfigService: AppConfigService) {
returnType = Object; super(apiService);
this.contextRoot = appConfigService.get('bpmHost', '');
constructor(private apiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private logService: LogService) {
super();
this.contextRoot = this.appConfigService.get('bpmHost', '');
} }
/** /**
@@ -44,24 +39,14 @@ export class FormDefinitionSelectorCloudService extends BaseCloudService {
* @returns Details of the forms * @returns Details of the forms
*/ */
getForms(appName: string): Observable<FormDefinitionSelectorCloudModel[]> { getForms(appName: string): Observable<FormDefinitionSelectorCloudModel[]> {
const url = `${this.getBasePath(appName)}/form/v1/forms`;
const queryUrl = this.buildGetFormsUrl(appName); return this.get(url).pipe(
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(
map((data: any) => { map((data: any) => {
return data.map((formData: any) => { return data.map((formData: any) => {
return <FormDefinitionSelectorCloudModel> formData.formRepresentation; return <FormDefinitionSelectorCloudModel> formData.formRepresentation;
}); });
}), })
catchError((err) => this.handleError(err))
); );
} }
@@ -73,19 +58,8 @@ export class FormDefinitionSelectorCloudService extends BaseCloudService {
getStandAloneTaskForms(appName: string): Observable<FormDefinitionSelectorCloudModel[]> { getStandAloneTaskForms(appName: string): Observable<FormDefinitionSelectorCloudModel[]> {
return from(this.getForms(appName)).pipe( return from(this.getForms(appName)).pipe(
map((data: any) => { map((data: any) => {
return data.filter((formData: any) => formData.standAlone || formData.standAlone === undefined); return data.filter((formData: any) => formData.standalone || formData.standalone === undefined);
}), })
catchError((err) => this.handleError(err))
); );
}
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');
} }
} }

View File

@@ -23,7 +23,6 @@ import { ProcessCloudModule } from './process/process-cloud.module';
import { GroupCloudModule } from './group/group-cloud.module'; import { GroupCloudModule } from './group/group-cloud.module';
import { FormCloudModule } from './form/form-cloud.module'; import { FormCloudModule } from './form/form-cloud.module';
import { TaskFormModule } from './task/task-form/task-form.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 { UserPreferenceCloudService } from './services/user-preference-cloud.service';
import { import {
LocalPreferenceCloudService, LocalPreferenceCloudService,
@@ -50,7 +49,6 @@ import {
source: 'assets/adf-process-services-cloud' source: 'assets/adf-process-services-cloud'
} }
}, },
BaseCloudService,
UserPreferenceCloudService, UserPreferenceCloudService,
LocalPreferenceCloudService, LocalPreferenceCloudService,
{ provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }, { provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService },

View File

@@ -17,8 +17,8 @@
import { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf-core'; import { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs'; import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model'; import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model';
import { BaseCloudService } from '../../../services/base-cloud.service'; import { BaseCloudService } from '../../../services/base-cloud.service';
@@ -26,16 +26,12 @@ import { BaseCloudService } from '../../../services/base-cloud.service';
providedIn: 'root' providedIn: 'root'
}) })
export class ProcessHeaderCloudService extends BaseCloudService { export class ProcessHeaderCloudService extends BaseCloudService {
contextRoot: string;
contentTypes = ['application/json'];
accepts = ['application/json'];
returnType = Object;
constructor(private alfrescoApiService: AlfrescoApiService, constructor(apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService,
private logService: LogService) { private logService: LogService) {
super(); super(apiService);
this.contextRoot = this.appConfigService.get('bpmHost', ''); this.contextRoot = appConfigService.get('bpmHost', '');
} }
/** /**
@@ -46,27 +42,16 @@ export class ProcessHeaderCloudService extends BaseCloudService {
*/ */
getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> { getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> {
if (appName && processInstanceId) { if (appName && processInstanceId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`; const url = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`;
return from(this.alfrescoApiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'GET', return this.get(url).pipe(
null, null, null,
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
return new ProcessInstanceCloud(res.entry); return new ProcessInstanceCloud(res.entry);
}), })
catchError((err) => this.handleError(err))
); );
} else { } else {
this.logService.error('AppName and ProcessInstanceId are mandatory for querying a task'); this.logService.error('AppName and ProcessInstanceId are mandatory for querying a task');
return throwError('AppName/ProcessInstanceId not configured'); return throwError('AppName/ProcessInstanceId not configured');
} }
} }
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');
}
} }

View File

@@ -17,20 +17,18 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model'; 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 { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
import { BaseCloudService } from '../../../services/base-cloud.service'; import { BaseCloudService } from '../../../services/base-cloud.service';
@Injectable() @Injectable()
export class ProcessListCloudService extends BaseCloudService { export class ProcessListCloudService extends BaseCloudService {
contentTypes = ['application/json']; constructor(apiService: AlfrescoApiService,
accepts = ['application/json']; appConfigService: AppConfigService,
constructor(private apiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private logService: LogService) { private logService: LogService) {
super(); super(apiService);
this.contextRoot = appConfigService.get('bpmHost', '');
} }
/** /**
@@ -40,35 +38,27 @@ export class ProcessListCloudService extends BaseCloudService {
*/ */
getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> { getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> {
if (requestNode.appName) { if (requestNode.appName) {
const queryUrl = this.buildQueryUrl(requestNode); const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`;
const queryParams = this.buildQueryParams(requestNode); const queryParams = this.buildQueryParams(requestNode);
const sortingParams = this.buildSortingParam(requestNode.sorting); const sortingParams = this.buildSortingParam(requestNode.sorting);
if (sortingParams) { if (sortingParams) {
queryParams['sort'] = sortingParams; queryParams['sort'] = sortingParams;
} }
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'GET', return this.get(queryUrl, queryParams);
null, queryParams, null,
null, null, this.contentTypes,
this.accepts, null, null)
);
} else { } else {
this.logService.error('Appname is mandatory for querying task'); this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured'); 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) { private isPropertyValueValid(requestNode: any, property: string) {
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined; return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
} }
private buildQueryParams(requestNode: ProcessQueryCloudRequestModel): Object { private buildQueryParams(requestNode: ProcessQueryCloudRequestModel): Object {
const queryParam = {}; const queryParam = {};
for (const property in requestNode) { for (const property in requestNode) {
if (requestNode.hasOwnProperty(property) && if (requestNode.hasOwnProperty(property) &&
!this.isExcludedField(property) && !this.isExcludedField(property) &&
@@ -76,6 +66,7 @@ export class ProcessListCloudService extends BaseCloudService {
queryParam[property] = requestNode[property]; queryParam[property] = requestNode[property];
} }
} }
return queryParam; return queryParam;
} }

View File

@@ -48,8 +48,15 @@
</form> </form>
<ng-container *ngIf="hasForm() else taskFormCloudButtons"> <ng-container *ngIf="hasForm() else taskFormCloudButtons">
<adf-cloud-form [appName]="appName" [data]="values" [formId]="processDefinitionCurrent.formKey" <adf-cloud-form
[showSaveButton]="false" [showCompleteButton]="false" [showRefreshButton]="false" [showValidationIcon]="false" [appName]="appName"
[appVersion]="processDefinitionCurrent.appVersion"
[data]="values"
[formId]="processDefinitionCurrent.formKey"
[showSaveButton]="false"
[showCompleteButton]="false"
[showRefreshButton]="false"
[showValidationIcon]="false"
[showTitle]="false" [showTitle]="false"
(formLoaded)="onFormLoaded($event)"> (formLoaded)="onFormLoaded($event)">
<adf-cloud-form-custom-outcomes> <adf-cloud-form-custom-outcomes>

View File

@@ -17,8 +17,8 @@
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs'; import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ProcessInstanceCloud } from '../models/process-instance-cloud.model'; import { ProcessInstanceCloud } from '../models/process-instance-cloud.model';
import { ProcessPayloadCloud } from '../models/process-payload-cloud.model'; import { ProcessPayloadCloud } from '../models/process-payload-cloud.model';
import { ProcessDefinitionCloud } from '../models/process-definition-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 { export class StartProcessCloudService extends BaseCloudService {
contextRoot: string; constructor(apiService: AlfrescoApiService,
contentTypes = ['application/json'];
accepts = ['application/json'];
returnType = Object;
constructor(private alfrescoApiService: AlfrescoApiService,
private logService: LogService, private logService: LogService,
private appConfigService: AppConfigService) { appConfigService: AppConfigService) {
super(); super(apiService);
this.contextRoot = this.appConfigService.get('bpmHost', ''); this.contextRoot = appConfigService.get('bpmHost', '');
} }
/** /**
@@ -47,21 +42,13 @@ export class StartProcessCloudService extends BaseCloudService {
* @returns Array of process definitions * @returns Array of process definitions
*/ */
getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> { getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> {
if (appName) { 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() return this.get(url).pipe(
.oauth2Auth.callCustomApi(queryUrl, 'GET',
null, null,
null, null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
return res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry)); return res.list.entries.map((processDefs) => new ProcessDefinitionCloud(processDefs.entry));
}), })
catchError((err) => this.handleProcessError(err))
); );
} else { } else {
this.logService.error('AppName is mandatory for querying task'); 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. * Starts a process based on a process definition, name, form values or variables.
* @param appName name of the Application * @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 * @returns Details of the process instance just started
*/ */
startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> { startProcess(appName: string, payload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> {
const url = `${this.getBasePath(appName)}/rb/v1/process-instances`;
const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-instances`; return this.post(url, payload).pipe(
map(processInstance => new ProcessInstanceCloud(processInstance))
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))
); );
} }
private handleProcessError(error: any) {
return throwError(error || 'Server error');
}
} }

View File

@@ -15,21 +15,102 @@
* limitations under the License. * 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 { export class BaseCloudService {
public contextRoot: string; protected contextRoot: string;
getBasePath(appName: string) { protected defaultParams: CallApiParams = {
if (this.isValidAppName(appName)) { path: '',
return `${this.contextRoot}/${appName}`; httpMethod: '',
} contentTypes: ['application/json'],
return this.contextRoot; accepts: ['application/json'],
returnType: Object
};
constructor(protected apiService: AlfrescoApiService) {}
getBasePath(appName: string): string {
return appName
? `${this.contextRoot}/${appName}`
: this.contextRoot;
} }
private isValidAppName(appName: string) { protected post<T, R>(url: string, data?: T): Observable<R> {
return appName && appName !== ''; return from(
this.callApi<R>({
...this.defaultParams,
path: url,
httpMethod: 'POST',
bodyParam: data
})
);
}
protected put<T, R>(url: string, data?: T): Observable<R> {
return from(
this.callApi<R>({
...this.defaultParams,
path: url,
httpMethod: 'PUT',
bodyParam: data
})
);
}
protected delete(url: string): Observable<void> {
return from(
this.callApi<void>({
...this.defaultParams,
path: url,
httpMethod: 'DELETE'
})
);
}
protected get<T>(url: string, queryParams?: any): Observable<T> {
return from(
this.callApi<T>({
...this.defaultParams,
path: url,
httpMethod: 'GET',
queryParams
})
);
}
protected callApi<T>(params: CallApiParams): Promise<T> {
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
);
} }
} }

View File

@@ -18,7 +18,7 @@
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async } from '@angular/core/testing';
import { UserPreferenceCloudService } from './user-preference-cloud.service'; 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'; import { mockPreferences, getMockPreference, createMockPreference, updateMockPreference } from '../mock/user-preference.mock';
describe('PreferenceService', () => { describe('PreferenceService', () => {
@@ -52,7 +52,6 @@ describe('PreferenceService', () => {
CoreModule.forRoot() CoreModule.forRoot()
], ],
providers: [ providers: [
UserPreferenceCloudService, AppConfigService, LogService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock } { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }
] ]
}); });
@@ -60,7 +59,6 @@ describe('PreferenceService', () => {
beforeEach(async(() => { beforeEach(async(() => {
service = TestBed.get(UserPreferenceCloudService); service = TestBed.get(UserPreferenceCloudService);
alfrescoApiMock = TestBed.get(AlfrescoApiService); alfrescoApiMock = TestBed.get(AlfrescoApiService);
service.contextRoot = 'http://{{domain}}.com';
getInstanceSpy = spyOn(alfrescoApiMock, 'getInstance').and.returnValue(apiMock(mockPreferences)); getInstanceSpy = spyOn(alfrescoApiMock, 'getInstance').and.returnValue(apiMock(mockPreferences));
})); }));

View File

@@ -18,21 +18,18 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { PreferenceCloudServiceInterface } from './preference-cloud.interface'; import { PreferenceCloudServiceInterface } from './preference-cloud.interface';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { from, throwError, Observable } from 'rxjs'; import { throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { BaseCloudService } from './base-cloud.service'; import { BaseCloudService } from './base-cloud.service';
@Injectable() @Injectable({ providedIn: 'root' })
export class UserPreferenceCloudService extends BaseCloudService implements PreferenceCloudServiceInterface { export class UserPreferenceCloudService extends BaseCloudService implements PreferenceCloudServiceInterface {
contentTypes = ['application/json'];
accepts = ['application/json'];
constructor( constructor(
private alfrescoApiService: AlfrescoApiService, apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService,
private logService: LogService) { 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<any> { getPreferences(appName: string): Observable<any> {
if (appName) { if (appName) {
const uri = this.buildPreferenceServiceUri(appName); const url = `${this.getBasePath(appName)}/preference/v1/preferences`;
return from(this.alfrescoApiService.getInstance() return this.get(url);
.oauth2Auth.callCustomApi(uri, 'GET',
null, null, null,
null, null, this.contentTypes,
this.accepts, null, null)
);
} else { } else {
this.logService.error('Appname is mandatory for querying preferences'); this.logService.error('Appname is mandatory for querying preferences');
return throwError('Appname not configured'); return throwError('Appname not configured');
@@ -63,14 +55,8 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
*/ */
getPreferenceByKey(appName: string, key: string): Observable<any> { getPreferenceByKey(appName: string, key: string): Observable<any> {
if (appName) { if (appName) {
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return from( return this.get(url);
this.alfrescoApiService.getInstance()
.oauth2Auth.callCustomApi(uri, 'GET',
null, null, null,
null, null, this.contentTypes,
this.accepts, null, null)
).pipe(catchError((error) => throwError(error)));
} else { } else {
this.logService.error('Appname and key are mandatory for querying preference'); this.logService.error('Appname and key are mandatory for querying preference');
return throwError('Appname not configured'); return throwError('Appname not configured');
@@ -86,17 +72,10 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
*/ */
createPreference(appName: string, key: string, newPreference: any): Observable<any> { createPreference(appName: string, key: string, newPreference: any): Observable<any> {
if (appName) { if (appName) {
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
const requestPayload = JSON.stringify(newPreference); const payload = JSON.stringify(newPreference);
return from(this.alfrescoApiService.getInstance()
.oauth2Auth.callCustomApi(uri, 'PUT', return this.put(url, payload);
null, null,
null, null, requestPayload,
this.contentTypes, this.accepts,
Object, null, null)
).pipe(
catchError((err) => this.handleProcessError(err))
);
} else { } else {
this.logService.error('Appname and key are mandatory for creating preference'); this.logService.error('Appname and key are mandatory for creating preference');
return throwError('Appname not configured'); return throwError('Appname not configured');
@@ -122,30 +101,11 @@ export class UserPreferenceCloudService extends BaseCloudService implements Pref
*/ */
deletePreference(appName: string, key: string): Observable<any> { deletePreference(appName: string, key: string): Observable<any> {
if (appName) { if (appName) {
const uri = this.buildPreferenceServiceUri(appName) + '/' + `${key}`; const url = `${this.getBasePath(appName)}/preference/v1/preferences/${key}`;
return from(this.alfrescoApiService.getInstance() return this.delete(url);
.oauth2Auth.callCustomApi(uri, 'DELETE',
null, null, null,
null, null, this.contentTypes,
this.accepts, null, null, null)
);
} else { } else {
this.logService.error('Appname and key are mandatory to delete preference'); this.logService.error('Appname and key are mandatory to delete preference');
return throwError('Appname not configured'); 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');
}
} }

View File

@@ -16,21 +16,22 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { Observable, from, throwError } from 'rxjs'; import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model';
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model'; import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service'; import { BaseCloudService } from '../../services/base-cloud.service';
@Injectable() @Injectable({ providedIn: 'root' })
export class StartTaskCloudService extends BaseCloudService { export class StartTaskCloudService extends BaseCloudService {
constructor( constructor(
private apiService: AlfrescoApiService, apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService) {
private logService: LogService super(apiService);
) { super(); } this.contextRoot = appConfigService.get('bpmHost');
}
/** /**
* @deprecated in 3.5.0, use TaskCloudService instead. * @deprecated in 3.5.0, use TaskCloudService instead.
@@ -39,37 +40,12 @@ export class StartTaskCloudService extends BaseCloudService {
* @returns Details of the newly created task * @returns Details of the newly created task
*/ */
createNewTask(taskDetails: TaskDetailsCloudModel): Observable<TaskDetailsCloudModel> { createNewTask(taskDetails: TaskDetailsCloudModel): Observable<TaskDetailsCloudModel> {
const queryUrl = this.buildCreateTaskUrl(taskDetails.appName); const url = `${this.getBasePath(taskDetails.appName)}/rb/v1/tasks`;
const bodyParam = JSON.stringify(this.buildRequestBody(taskDetails)); const payload = JSON.stringify(new StartTaskCloudRequestModel(taskDetails));
const pathParams = {}, queryParams = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from( return this.post<any, StartTaskCloudResponseModel>(url, payload)
this.apiService .pipe(
.getInstance() map(response => response.entry)
.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))
); );
} }
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');
}
} }

View File

@@ -17,8 +17,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core'; import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } from '@alfresco/adf-core';
import { from, throwError, Observable, of, Subject } from 'rxjs'; import { throwError, Observable, of, Subject } from 'rxjs';
import { catchError, map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model'; import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service'; import { BaseCloudService } from '../../services/base-cloud.service';
import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; 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 { export class TaskCloudService extends BaseCloudService {
contentTypes = ['application/json']; dataChangesDetected$ = new Subject();
accepts = ['application/json'];
returnType = Object;
private dataChangesDetected = new Subject();
dataChangesDetected$: Observable<any>;
constructor( constructor(
private apiService: AlfrescoApiService, apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService,
private logService: LogService, private logService: LogService,
private identityUserService: IdentityUserService private identityUserService: IdentityUserService
) { ) {
super(); super(apiService);
this.contextRoot = this.appConfigService.get('bpmHost', ''); this.contextRoot = appConfigService.get('bpmHost', '');
this.dataChangesDetected$ = this.dataChangesDetected.asObservable();
} }
/** /**
@@ -54,21 +48,10 @@ export class TaskCloudService extends BaseCloudService {
*/ */
completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = this.buildCompleteTaskUrl(appName, taskId); const url = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/complete`;
const bodyParam = { 'payloadType': 'CompleteTaskPayload' }; const payload = { 'payloadType': 'CompleteTaskPayload' };
const pathParams = {}, queryParams = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from( return this.post<any, TaskDetailsCloudModel>(url, payload);
this.apiService
.getInstance()
.oauth2Auth.callCustomApi(
queryUrl, 'POST', pathParams, queryParams,
headerParams, formParams, bodyParam,
contentTypes, accepts, null, null)
).pipe(
catchError((err) => this.handleError(err))
);
} else { } else {
this.logService.error('AppName and TaskId are mandatory for complete a task'); this.logService.error('AppName and TaskId are mandatory for complete a task');
return throwError('AppName/TaskId not configured'); return throwError('AppName/TaskId not configured');
@@ -81,7 +64,7 @@ export class TaskCloudService extends BaseCloudService {
* @returns Boolean value if the task can be completed * @returns Boolean value if the task can be completed
*/ */
canCompleteTask(taskDetails: TaskDetailsCloudModel): boolean { 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 * @returns Boolean value if the task is editable
*/ */
isTaskEditable(taskDetails: TaskDetailsCloudModel): boolean { 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 * @returns Boolean value if the task can be completed
*/ */
canClaimTask(taskDetails: TaskDetailsCloudModel): boolean { 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 { canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean {
const currentUser = this.identityUserService.getCurrentUserInfo().username; 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<TaskDetailsCloudModel> { claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`;
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'POST', return this.post(queryUrl).pipe(
null, null, null,
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
this.dataChangesDetected.next(); this.dataChangesDetected$.next();
return new TaskDetailsCloudModel(res.entry); return res.entry;
}), })
catchError((err) => this.handleError(err))
); );
} else { } else {
this.logService.error('AppName and TaskId are mandatory for querying a task'); 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<TaskDetailsCloudModel> { unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`;
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'POST', return this.post(queryUrl).pipe(
null, null, null,
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => { map((res: any) => {
this.dataChangesDetected.next(); this.dataChangesDetected$.next();
return new TaskDetailsCloudModel(res.entry); return res.entry;
}), })
catchError((err) => this.handleError(err))
); );
} else { } else {
this.logService.error('AppName and TaskId are mandatory for querying a task'); 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<TaskDetailsCloudModel> { getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`;
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'GET', return this.get(queryUrl).pipe(
null, null, null, map((res: any) => res.entry)
null, null,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => {
return new TaskDetailsCloudModel(res.entry);
}),
catchError((err) => this.handleError(err))
); );
} else { } else {
this.logService.error('AppName and TaskId are mandatory for querying a task'); 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 * @returns Details of the newly created task
*/ */
createNewTask(startTaskRequest: StartTaskCloudRequestModel, appName: string): Observable<TaskDetailsCloudModel> { createNewTask(startTaskRequest: StartTaskCloudRequestModel, appName: string): Observable<TaskDetailsCloudModel> {
const queryUrl = this.buildCreateTaskUrl(appName); const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks`;
const bodyParam = JSON.stringify(this.buildRequestBody(startTaskRequest)); const payload = JSON.stringify(new StartTaskCloudRequestModel(startTaskRequest));
const pathParams = {}, queryParams = {}, headerParams = {},
formParams = {}, contentTypes = ['application/json'], accepts = ['application/json'];
return from( return this.post<any, StartTaskCloudResponseModel>(queryUrl, payload)
this.apiService .pipe(
.getInstance() map(response => response.entry)
.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))
); );
} }
@@ -226,25 +178,16 @@ export class TaskCloudService extends BaseCloudService {
* Updates the details (name, description, due date) for a task. * Updates the details (name, description, due date) for a task.
* @param appName Name of the app * @param appName Name of the app
* @param taskId ID of the task to update * @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 * @returns Updated task details
*/ */
updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> { updateTask(appName: string, taskId: string, payload: any): Observable<TaskDetailsCloudModel> {
if (appName && taskId) { if (appName && taskId) {
payload.payloadType = 'UpdateTaskPayload';
updatePayload.payloadType = 'UpdateTaskPayload';
const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`;
return from(this.apiService.getInstance()
.oauth2Auth.callCustomApi(queryUrl, 'PUT', return this.put(queryUrl, payload).pipe(
null, null, null, map((res: any) => res.entry)
null, updatePayload,
this.contentTypes, this.accepts,
this.returnType, null, null)
).pipe(
map((res: any) => {
return new TaskDetailsCloudModel(res.entry);
}),
catchError((err) => this.handleError(err))
); );
} else { } else {
this.logService.error('AppName and TaskId are mandatory for querying a task'); 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<string[]> { getCandidateUsers(appName: string, taskId: string): Observable<string[]> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`; const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-users`;
return from(this.apiService.getInstance() return this.get<string[]>(queryUrl);
.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))
);
} else { } else {
this.logService.error('AppName and TaskId are mandatory to get candidate user'); this.logService.error('AppName and TaskId are mandatory to get candidate user');
return of([]); return of([]);
@@ -288,18 +220,7 @@ export class TaskCloudService extends BaseCloudService {
getCandidateGroups(appName: string, taskId: string): Observable<string[]> { getCandidateGroups(appName: string, taskId: string): Observable<string[]> {
if (appName && taskId) { if (appName && taskId) {
const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`; const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/candidate-groups`;
return from(this.apiService.getInstance() return this.get<string[]>(queryUrl);
.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))
);
} else { } else {
this.logService.error('AppName and TaskId are mandatory to get candidate groups'); this.logService.error('AppName and TaskId are mandatory to get candidate groups');
return of([]); return of([]);
@@ -310,23 +231,4 @@ export class TaskCloudService extends BaseCloudService {
const currentUser = this.identityUserService.getCurrentUserInfo().username; const currentUser = this.identityUserService.getCurrentUserInfo().username;
return assignee === currentUser; 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');
}
} }

View File

@@ -15,98 +15,45 @@
* limitations under the License. * limitations under the License.
*/ */
export class TaskDetailsCloudModel { export interface TaskDetailsCloudModel {
id?: string;
id: string; name?: string;
name: string; appName?: string;
appName: string; assignee?: string;
assignee: string; appVersion?: number;
appVersion: string; createdDate?: Date;
createdDate: Date; claimedDate?: Date;
claimedDate: Date; completedDate?: Date;
completedDate: Date; formKey?: any;
formKey: any; category?: any;
category: any; description?: string;
description: string; dueDate?: Date;
dueDate: Date; lastModified?: Date;
lastModified: Date; lastModifiedTo?: Date;
lastModifiedTo: Date; lastModifiedFrom?: Date;
lastModifiedFrom: Date; owner?: any;
owner: any; parentTaskId?: number;
parentTaskId: number; priority?: number;
priority: number; processDefinitionId?: string;
processDefinitionId: string; processInstanceId?: string;
processInstanceId: string; status?: TaskStatus;
status: TaskStatusEnum; standalone?: boolean;
standalone: boolean; candidateUsers?: string[];
candidateUsers: string[]; candidateGroups?: string[];
candidateGroups: string[]; managerOfCandidateGroup?: boolean;
managerOfCandidateGroup: boolean; memberOfCandidateGroup?: boolean;
memberOfCandidateGroup: boolean; memberOfCandidateUsers?: boolean;
memberOfCandidateUsers: boolean;
processDefinitionDeploymentId?: string; 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 { export interface StartTaskCloudResponseModel {
entry: TaskDetailsCloudModel; entry: TaskDetailsCloudModel;
} }
export enum TaskStatusEnum { export type TaskStatus = |
COMPLETED= 'COMPLETED', 'COMPLETED' |
DELETED = 'DELETED', 'DELETED' |
CREATED = 'CREATED', 'CREATED' |
ASSIGNED = 'ASSIGNED', 'ASSIGNED' |
SUSPENDED = 'SUSPENDED', 'SUSPENDED' |
CANCELLED = 'CANCELLED' 'CANCELLED';
}

View File

@@ -1,6 +1,7 @@
<div *ngIf="!loading; else loadingTemplate"> <div *ngIf="!loading; else loadingTemplate">
<adf-cloud-form *ngIf="hasForm(); else withoutForm" <adf-cloud-form *ngIf="hasForm(); else withoutForm"
[appName]="appName" [appName]="appName"
[appVersion]="taskDetails.appVersion"
[taskId]="taskId" [taskId]="taskId"
[processInstanceId]="taskDetails.processInstanceId" [processInstanceId]="taskDetails.processInstanceId"
[readOnly]="isReadOnly()" [readOnly]="isReadOnly()"

View File

@@ -27,11 +27,11 @@ import { TaskFormCloudComponent } from './task-form-cloud.component';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service'; import { TaskCloudService } from '../../services/task-cloud.service';
const taskDetails = { const taskDetails: TaskDetailsCloudModel = {
appName: 'simple-app', appName: 'simple-app',
assignee: 'admin.adf', assignee: 'admin.adf',
completedDate: null, completedDate: null,
createdDate: 1555419255340, createdDate: new Date(1555419255340),
description: null, description: null,
formKey: null, formKey: null,
id: 'bd6b1741-6046-11e9-80f0-0a586460040d', id: 'bd6b1741-6046-11e9-80f0-0a586460040d',
@@ -63,7 +63,7 @@ describe('TaskFormCloudComponent', () => {
identityUserService = TestBed.get(IdentityUserService); identityUserService = TestBed.get(IdentityUserService);
getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' }); getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' });
taskCloudService = TestBed.get(TaskCloudService); 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, 'getCandidateGroups').and.returnValue(of([]));
spyOn(taskCloudService, 'getCandidateUsers').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(() => { it('should not show unclaim button when status is not ASSIGNED', async(() => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
taskDetails.status = ''; taskDetails.status = undefined;
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.loadTask(); component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
@@ -168,7 +168,7 @@ describe('TaskFormCloudComponent', () => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
taskDetails.status = 'CREATED'; taskDetails.status = 'CREATED';
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.loadTask(); component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
@@ -181,8 +181,8 @@ describe('TaskFormCloudComponent', () => {
it('should not show claim button when status is not CREATED', async(() => { it('should not show claim button when status is not CREATED', async(() => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
taskDetails.status = ''; taskDetails.status = undefined;
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.loadTask(); component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
@@ -306,7 +306,7 @@ describe('TaskFormCloudComponent', () => {
it('should emit taskClaimed when task is claimed', (done) => { it('should emit taskClaimed when task is claimed', (done) => {
spyOn(taskCloudService, 'claimTask').and.returnValue(of({})); spyOn(taskCloudService, 'claimTask').and.returnValue(of({}));
taskDetails.status = 'CREATED'; taskDetails.status = 'CREATED';
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
@@ -354,7 +354,7 @@ describe('TaskFormCloudComponent', () => {
const reloadSpy = spyOn(component, 'loadTask').and.callThrough(); const reloadSpy = spyOn(component, 'loadTask').and.callThrough();
taskDetails.status = 'CREATED'; taskDetails.status = 'CREATED';
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
@@ -373,7 +373,7 @@ describe('TaskFormCloudComponent', () => {
spyOn(component, 'hasCandidateUsers').and.returnValue(true); spyOn(component, 'hasCandidateUsers').and.returnValue(true);
taskDetails.status = 'ASSIGNED'; taskDetails.status = 'ASSIGNED';
getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';

View File

@@ -120,32 +120,25 @@ export class TaskFormCloudComponent implements OnChanges {
this.loadTask(); this.loadTask();
return; return;
} }
} }
loadTask() { loadTask() {
this.loading = true; 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[]) => { this.taskCloudService
if (users) { .getTaskById(this.appName, this.taskId)
this.candidateUsers = users; .subscribe(details => {
} this.taskDetails = details;
}); this.loading = false;
});
this.taskCloudService.getCandidateGroups(this.appName, this.taskId).subscribe((groups: string[]) => { this.taskCloudService
if (groups) { .getCandidateUsers(this.appName, this.taskId)
this.candidateGroups = groups; .subscribe(users => this.candidateUsers = users || []);
}
});
} this.taskCloudService
.getCandidateGroups(this.appName, this.taskId)
private reloadTask() { .subscribe(groups => this.candidateGroups = groups || []);
this.loadTask();
} }
hasForm(): boolean { hasForm(): boolean {
@@ -186,17 +179,17 @@ export class TaskFormCloudComponent implements OnChanges {
} }
onCompleteTask() { onCompleteTask() {
this.reloadTask(); this.loadTask();
this.taskCompleted.emit(this.taskId); this.taskCompleted.emit(this.taskId);
} }
onClaimTask() { onClaimTask() {
this.reloadTask(); this.loadTask();
this.taskClaimed.emit(this.taskId); this.taskClaimed.emit(this.taskId);
} }
onUnclaimTask() { onUnclaimTask() {
this.reloadTask(); this.loadTask();
this.taskUnclaimed.emit(this.taskId); this.taskUnclaimed.emit(this.taskId);
} }

View File

@@ -28,7 +28,7 @@ import {
CardViewUpdateService, CardViewUpdateService,
CardViewDatetimeItemModel CardViewDatetimeItemModel
} from '@alfresco/adf-core'; } 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 { Router } from '@angular/router';
import { TaskCloudService } from '../../services/task-cloud.service'; import { TaskCloudService } from '../../services/task-cloud.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@@ -62,7 +62,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
@Output() @Output()
error: EventEmitter<any> = new EventEmitter<any>(); error: EventEmitter<any> = new EventEmitter<any>();
taskDetails: TaskDetailsCloudModel = new TaskDetailsCloudModel(); taskDetails: TaskDetailsCloudModel = {};
properties: CardViewItem[]; properties: CardViewItem[];
inEdit: boolean = false; inEdit: boolean = false;
parentTaskName: string; parentTaskName: string;
@@ -99,7 +99,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
} }
ngOnChanges() { ngOnChanges() {
this.taskDetails = new TaskDetailsCloudModel(); this.taskDetails = {};
if (this.appName && this.taskId) { if (this.appName && this.taskId) {
this.loadTaskDetailsById(this.appName, this.taskId); this.loadTaskDetailsById(this.appName, this.taskId);
} else { } else {
@@ -278,8 +278,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
); );
} }
isCompleted() { isCompleted(): boolean {
return this.taskDetails && this.taskDetails.status && this.taskDetails.status.toUpperCase() === TaskStatusEnum.COMPLETED; return this.taskDetails && this.taskDetails.status === 'COMPLETED';
} }
hasAssignee(): boolean { hasAssignee(): boolean {
@@ -299,7 +299,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
} }
isClickable(): boolean { isClickable(): boolean {
const states = [TaskStatusEnum.ASSIGNED, TaskStatusEnum.CREATED, TaskStatusEnum.SUSPENDED]; const states: TaskStatus[] = ['ASSIGNED', 'CREATED', 'SUSPENDED'];
return states.includes(this.taskDetails.status); return states.includes(this.taskDetails.status);
} }

View File

@@ -17,80 +17,74 @@
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
export const assignedTaskDetailsCloudMock = new TaskDetailsCloudModel( export const assignedTaskDetailsCloudMock: TaskDetailsCloudModel = {
{ 'appName': 'task-app',
'appName': 'task-app', 'appVersion': 1,
'appVersion': '', 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad',
'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', 'assignee': 'AssignedTaskUser',
'assignee': 'AssignedTaskUser', 'name': 'This is a new task ',
'name': 'This is a new task ', 'description': 'This is the description ',
'description': 'This is the description ', 'createdDate': new Date(1545048055900),
'createdDate': 1545048055900, 'dueDate': new Date(),
'dueDate': Date.now(), 'claimedDate': null,
'claimedDate': null, 'priority': 5,
'priority': 5, 'category': null,
'category': null, 'processDefinitionId': null,
'processDefinitionId': null, 'processInstanceId': null,
'processInstanceId': null, 'status': 'ASSIGNED',
'status': 'ASSIGNED', 'owner': 'ownerUser',
'owner': 'ownerUser', 'parentTaskId': null,
'parentTaskId': null, 'formKey': null,
'formKey': null, 'lastModified': new Date(1545048055900),
'lastModified': 1545048055900, 'lastModifiedTo': null,
'lastModifiedTo': null, 'lastModifiedFrom': null,
'lastModifiedFrom': null, 'standalone': true
'standalone': true };
}
);
export const createdTaskDetailsCloudMock = new TaskDetailsCloudModel( export const createdTaskDetailsCloudMock: TaskDetailsCloudModel = {
{ 'appName': 'task-app',
'appName': 'task-app', 'appVersion': 1,
'appVersion': '', 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad',
'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', 'assignee': 'CreatedTaskUser',
'assignee': 'CreatedTaskUser', 'name': 'This is a new task ',
'name': 'This is a new task ', 'description': 'This is the description ',
'description': 'This is the description ', 'createdDate': new Date(1545048055900),
'createdDate': 1545048055900, 'dueDate': new Date(1545091200000),
'dueDate': 1545091200000, 'claimedDate': null,
'claimedDate': null, 'priority': 5,
'priority': 5, 'category': null,
'category': null, 'processDefinitionId': null,
'processDefinitionId': null, 'processInstanceId': null,
'processInstanceId': null, 'status': 'CREATED',
'status': 'CREATED', 'owner': 'ownerUser',
'owner': 'ownerUser', 'parentTaskId': null,
'parentTaskId': null, 'formKey': null,
'formKey': null, 'lastModified': new Date(1545048055900),
'lastModified': 1545048055900, 'lastModifiedTo': null,
'lastModifiedTo': null, 'lastModifiedFrom': null,
'lastModifiedFrom': null, 'standalone': true
'standalone': true };
}
);
export const emptyOwnerTaskDetailsCloudMock = new TaskDetailsCloudModel( export const emptyOwnerTaskDetailsCloudMock: TaskDetailsCloudModel = {
{ 'appName': 'task-app',
'appName': 'task-app', 'appVersion': 1,
'appVersion': '', 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad',
'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', 'assignee': 'AssignedTaskUser',
'assignee': 'AssignedTaskUser', 'name': 'This is a new task ',
'name': 'This is a new task ', 'description': 'This is the description ',
'description': 'This is the description ', 'createdDate': new Date(1545048055900),
'createdDate': 1545048055900, 'dueDate': new Date(1545091200000),
'dueDate': 1545091200000, 'claimedDate': null,
'claimedDate': null, 'priority': 5,
'priority': 5, 'category': null,
'category': null, 'processDefinitionId': null,
'processDefinitionId': null, 'processInstanceId': null,
'processInstanceId': null, 'status': 'ASSIGNED',
'status': 'ASSIGNED', 'owner': null,
'owner': null, 'parentTaskId': null,
'parentTaskId': null, 'formKey': null,
'formKey': null, 'lastModified': new Date(1545048055900),
'lastModified': 1545048055900, 'lastModifiedTo': null,
'lastModifiedTo': null, 'lastModifiedFrom': null,
'lastModifiedFrom': null, 'standalone': true
'standalone': true };
}
);

View File

@@ -18,53 +18,40 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; 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 { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
import { BaseCloudService } from '../../../services/base-cloud.service'; import { BaseCloudService } from '../../../services/base-cloud.service';
@Injectable() @Injectable({ providedIn: 'root' })
export class TaskListCloudService extends BaseCloudService { export class TaskListCloudService extends BaseCloudService {
constructor(private apiService: AlfrescoApiService, constructor(apiService: AlfrescoApiService,
private appConfigService: AppConfigService, appConfigService: AppConfigService,
private logService: LogService) { 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. * Finds a task using an object with optional query properties.
* @param requestNode Query object * @param requestNode Query object
* @returns Task information * @returns Task information
*/ */
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> { getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
if (requestNode.appName) { if (requestNode.appName) {
const queryUrl = this.buildQueryUrl(requestNode); const queryUrl = `${this.getBasePath(requestNode.appName)}/query/v1/tasks`;
const queryParams = this.buildQueryParams(requestNode); const queryParams = this.buildQueryParams(requestNode);
const sortingParams = this.buildSortingParam(requestNode.sorting); const sortingParams = this.buildSortingParam(requestNode.sorting);
if (sortingParams) { if (sortingParams) {
queryParams['sort'] = sortingParams; queryParams['sort'] = sortingParams;
} }
return from(this.apiService.getInstance() return this.get(queryUrl, queryParams);
.oauth2Auth.callCustomApi(queryUrl, 'GET',
null, queryParams, null,
null, null, ['application/json'],
['application/json'], null, null)
);
} else { } else {
this.logService.error('Appname is mandatory for querying task'); this.logService.error('Appname is mandatory for querying task');
return throwError('Appname not configured'); 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 { private buildQueryParams(requestNode: TaskQueryCloudRequestModel): Object {
const queryParam: Object = {}; const queryParam: Object = {};
for (const property in requestNode) { for (const property in requestNode) {

View File

@@ -200,7 +200,6 @@ export class FormComponent extends FormBaseComponent implements OnInit, OnDestro
}, },
(error) => { (error) => {
this.handleError(error); this.handleError(error);
// reject(error);
resolve(null); resolve(null);
} }
); );

View File

@@ -28,7 +28,7 @@ const column = {
assignee: 'Assignee', assignee: 'Assignee',
parentTaskId: 'ParentTaskId', parentTaskId: 'ParentTaskId',
priority: 'Priority', priority: 'Priority',
standAlone: 'StandAlone', standalone: 'Standalone',
owner: 'Owner' owner: 'Owner'
}; };
@@ -149,7 +149,7 @@ export class TaskListCloudComponentPage {
} }
async getAllRowsByStandAloneColumn() { async getAllRowsByStandAloneColumn() {
return this.dataTable.getAllRowsColumnValues(column.standAlone); return this.dataTable.getAllRowsColumnValues(column.standalone);
} }
async getAllRowsByOwnerColumn() { async getAllRowsByOwnerColumn() {