diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html index 154da753f2..6e9b2c44c4 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.html @@ -105,9 +105,10 @@ (click)="cancelStartProcess()" id="cancel_process" > - {{ 'ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.CANCEL' | translate | uppercase}} + {{ cancelButtonLabel }} diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts index 1866049f3a..d2a1ea0844 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts @@ -67,6 +67,7 @@ describe('StartProcessCloudComponent', () => { let startProcessWithFormSpy: jasmine.Spy; let formDefinitionSpy: jasmine.Spy; let getStartEventFormStaticValuesMappingSpy: jasmine.Spy; + let getStartEventConstantSpy: jasmine.Spy; const firstChange = new SimpleChange(undefined, 'myApp', true); @@ -112,6 +113,7 @@ describe('StartProcessCloudComponent', () => { startProcessSpy = spyOn(processService, 'startProcess').and.returnValue(of(fakeProcessInstance)); startProcessWithFormSpy = spyOn(processService, 'startProcessWithForm').and.returnValue(of(fakeProcessWithFormInstance)); getStartEventFormStaticValuesMappingSpy = spyOn(processService, 'getStartEventFormStaticValuesMapping').and.returnValue(of([])); + getStartEventConstantSpy = spyOn(processService, 'getStartEventConstants').and.returnValue(of([])); loader = TestbedHarnessEnvironment.loader(fixture); }); @@ -120,6 +122,56 @@ describe('StartProcessCloudComponent', () => { TestBed.resetTestingModule(); }); + /** + * Setup the component with the given start event information. + * @param values the values for the form + * @param staticValues the static values retrieved from the API for the form + * @param constantValues the constant values retrieved from the API for customising the buttons + * @returns the start and cancel buttons HTML elements + */ + function loadWithStartEventInformation( + values?: TaskVariableCloud[], + staticValues?: TaskVariableCloud[] | Error, + constantValues?: TaskVariableCloud[] | Error + ): { + startButton: any; + cancelButton: any; + } { + if (values) { + component.values = values; + } + if (staticValues) { + if (staticValues instanceof Error) { + getStartEventConstantSpy.and.returnValue(throwError(() => staticValues)); + } else { + getStartEventFormStaticValuesMappingSpy.and.returnValue(of(staticValues)); + } + } + if (constantValues) { + if (constantValues instanceof Error) { + getStartEventConstantSpy.and.returnValue(throwError(() => constantValues)); + } else { + getStartEventConstantSpy.and.returnValue(of(constantValues)); + } + } + + component.name = 'My new process'; + component.processDefinitionName = 'processwithoutform2'; + getDefinitionsSpy.and.returnValue(of(fakeSingleProcessDefinitionWithoutForm(component.processDefinitionName))); + fixture.detectChanges(); + + const change = new SimpleChange(null, 'MyApp', true); + component.ngOnChanges({ appName: change }); + fixture.detectChanges(); + tick(550); + fixture.detectChanges(); + + const startButton = fixture.nativeElement.querySelector('#button-start'); + const cancelButton = fixture.nativeElement.querySelector('#cancel_process'); + + return { startButton, cancelButton }; + } + describe('start a process without start form', () => { beforeEach(() => { component.name = 'My formless new process'; @@ -197,19 +249,47 @@ describe('StartProcessCloudComponent', () => { new TaskVariableCloud({ name: 'static2', value: 0 }), new TaskVariableCloud({ name: 'static3', value: true }) ]; - component.name = 'My new process'; - component.processDefinitionName = 'processwithoutform2'; - component.values = values; - getDefinitionsSpy.and.returnValue(of(fakeSingleProcessDefinitionWithoutForm(component.processDefinitionName))); - getStartEventFormStaticValuesMappingSpy.and.returnValue(of(staticInputs)); - fixture.detectChanges(); - const change = new SimpleChange(null, 'MyApp', true); - component.ngOnChanges({ appName: change }); - fixture.detectChanges(); - tick(550); + loadWithStartEventInformation(values, staticInputs); + expect(component.resolvedValues).toEqual(staticInputs.concat(values)); })); + + describe('start event constants', () => { + it('should not display the buttons when they are disabled by the constants', fakeAsync(() => { + const constants: TaskVariableCloud[] = [ + new TaskVariableCloud({ name: 'startEnabled', value: 'false' }), + new TaskVariableCloud({ name: 'cancelEnabled', value: 'false' }) + ]; + + const { startButton, cancelButton } = loadWithStartEventInformation(null, null, constants); + + expect(startButton).toBeNull(); + expect(cancelButton).toBeNull(); + })); + + it('should display the customised button labels when they are set in the constants', fakeAsync(() => { + const constants: TaskVariableCloud[] = [ + new TaskVariableCloud({ name: 'startEnabled', value: 'true' }), + new TaskVariableCloud({ name: 'startLabel', value: 'Start' }), + new TaskVariableCloud({ name: 'cancelEnabled', value: 'true' }), + new TaskVariableCloud({ name: 'cancelLabel', value: 'Cancel' }) + ]; + const { startButton, cancelButton } = loadWithStartEventInformation(null, null, constants); + + expect(startButton.textContent?.trim()).toEqual('Start'); + expect(cancelButton.textContent?.trim()).toEqual('Cancel'); + })); + + it('should load with default values when retrieving the constants fails', fakeAsync(() => { + const { startButton, cancelButton } = loadWithStartEventInformation(null, null, new Error('test')); + + expect(startButton).not.toBeNull(); + expect(cancelButton).not.toBeNull(); + expect(startButton.textContent?.trim()).toEqual(component.defaultStartProcessButtonLabel); + expect(cancelButton.textContent?.trim()).toEqual(component.defaultCancelProcessButtonLabel); + })); + }); }); describe('start a process with start form', () => { diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts index 229833a5ef..b9e383c71c 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts @@ -30,18 +30,18 @@ import { ViewEncapsulation } from '@angular/core'; -import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel } from '@alfresco/adf-core'; +import { ContentLinkModel, FORM_FIELD_VALIDATORS, FormFieldValidator, FormModel, TranslationService } from '@alfresco/adf-core'; import { AbstractControl, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; import { MatAutocompleteTrigger } from '@angular/material/autocomplete'; -import { Subject } from 'rxjs'; -import { debounceTime, takeUntil } from 'rxjs/operators'; -import { TaskVariableCloud } from '../../../form/models/task-variable-cloud.model'; -import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model'; -import { ProcessNameCloudPipe } from '../../../pipes/process-name-cloud.pipe'; +import { catchError, debounceTime, takeUntil } from 'rxjs/operators'; import { ProcessInstanceCloud } from '../models/process-instance-cloud.model'; import { ProcessPayloadCloud } from '../models/process-payload-cloud.model'; import { ProcessWithFormPayloadCloud } from '../models/process-with-form-payload-cloud.model'; import { StartProcessCloudService } from '../services/start-process-cloud.service'; +import { forkJoin, of, Subject } from 'rxjs'; +import { ProcessDefinitionCloud } from '../../../models/process-definition-cloud.model'; +import { TaskVariableCloud } from '../../../form/models/task-variable-cloud.model'; +import { ProcessNameCloudPipe } from '../../../pipes/process-name-cloud.pipe'; const MAX_NAME_LENGTH: number = 255; const PROCESS_DEFINITION_DEBOUNCE: number = 300; @@ -131,6 +131,10 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy isFormCloudLoading = false; processDefinitionLoaded = false; + showStartProcessButton = true; + startProcessButtonLabel: string; + cancelButtonLabel: string; + formCloud?: FormModel; processForm = new FormGroup({ processInstanceName: new FormControl('', [ @@ -172,6 +176,19 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy return !!this.processDefinitionCurrent?.formKey; } + get defaultStartProcessButtonLabel(): string { + return this.translateService.instant('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.START').toUpperCase(); + } + + get defaultCancelProcessButtonLabel(): string { + return this.translateService.instant('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.FORM.ACTION.CANCEL').toUpperCase(); + } + + constructor(private translateService: TranslationService) { + this.startProcessButtonLabel = this.defaultStartProcessButtonLabel; + this.cancelButtonLabel = this.defaultCancelProcessButtonLabel; + } + ngOnInit() { this.initFieldValidators(); @@ -230,19 +247,39 @@ export class StartProcessCloudComponent implements OnChanges, OnInit, OnDestroy (process: ProcessDefinitionCloud) => process.name === selectedProcessDefinitionName || process.key === selectedProcessDefinitionName ); - this.startProcessCloudService.getStartEventFormStaticValuesMapping(this.appName, processDefinitionCurrent.id).subscribe( - (staticMappings) => { - this.staticMappings = staticMappings; - this.resolvedValues = this.staticMappings.concat(this.values || []); - this.processDefinitionCurrent = processDefinitionCurrent; - this.isFormCloudLoading = false; - }, - () => { - this.resolvedValues = this.values; - this.processDefinitionCurrent = processDefinitionCurrent; - this.isFormCloudLoading = false; + forkJoin([ + this.startProcessCloudService + .getStartEventFormStaticValuesMapping(this.appName, processDefinitionCurrent.id) + .pipe(catchError(() => of([] as TaskVariableCloud[]))), + this.startProcessCloudService + .getStartEventConstants(this.appName, processDefinitionCurrent.id) + .pipe(catchError(() => of([] as TaskVariableCloud[]))) + ]).subscribe(([staticMappings, constants]) => { + this.staticMappings = staticMappings; + this.resolvedValues = this.staticMappings.concat(this.values || []); + this.processDefinitionCurrent = processDefinitionCurrent; + this.isFormCloudLoading = false; + + const displayStart = constants?.find((constant) => constant.name === 'startEnabled'); + const startLabel = constants?.find((constant) => constant.name === 'startLabel'); + + const displayCancel = constants?.find((constant) => constant.name === 'cancelEnabled'); + const cancelLabel = constants?.find((constant) => constant.name === 'cancelLabel'); + + if (displayStart) { + this.showStartProcessButton = displayStart?.value === 'true'; } - ); + if (startLabel) { + this.startProcessButtonLabel = startLabel?.value?.trim()?.length > 0 ? startLabel.value.trim() : this.defaultStartProcessButtonLabel; + } + + if (displayCancel) { + this.showCancelButton = displayCancel?.value === 'true' && this.showCancelButton; + } + if (cancelLabel) { + this.cancelButtonLabel = cancelLabel?.value?.trim()?.length > 0 ? cancelLabel.value.trim() : this.defaultCancelProcessButtonLabel; + } + }); this.isFormCloudLoaded = false; this.processPayloadCloud.processDefinitionKey = processDefinitionCurrent.key; diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.spec.ts index f10b602747..2ba675349b 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.spec.ts @@ -125,4 +125,29 @@ describe('StartProcessCloudService', () => { expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/rb/v1/process-definitions/${processDefinitionId}/static-values`); expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET'); }); + + it('should transform the response into task variables when retrieving the constant values for the start event', async () => { + const appName = 'test-app'; + const processDefinitionId = 'processDefinitionId'; + const requestSpy = spyOn(adfHttpClient, 'request'); + requestSpy.and.returnValue(Promise.resolve({ constant1: 'value', constant2: '0', constant3: 'true' })); + + const result = await service.getStartEventConstants(appName, processDefinitionId).toPromise(); + + expect(result.length).toEqual(3); + expect(result[0].name).toEqual('constant1'); + expect(result[0].id).toEqual('constant1'); + expect(result[0].value).toEqual('value'); + expect(result[0].type).toEqual('string'); + expect(result[1].name).toEqual('constant2'); + expect(result[1].id).toEqual('constant2'); + expect(result[1].value).toEqual('0'); + expect(result[1].type).toEqual('string'); + expect(result[2].name).toEqual('constant3'); + expect(result[2].id).toEqual('constant3'); + expect(result[2].value).toEqual('true'); + expect(result[2].type).toEqual('string'); + expect(requestSpy.calls.mostRecent().args[0]).toContain(`${appName}/rb/v1/process-definitions/${processDefinitionId}/constant-values`); + expect(requestSpy.calls.mostRecent().args[1].httpMethod).toBe('GET'); + }); }); diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts index d847f99e39..37bdc98a98 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts @@ -119,4 +119,26 @@ export class StartProcessCloudService extends BaseCloudService { }) ); } + + /** + * Gets the constants mapped to the start form of a process definition. + * + * @param appName Name of the app + * @param processDefinitionId ID of the target process definition + * @returns Constants values for the start event + */ + getStartEventConstants(appName: string, processDefinitionId: string): Observable { + const apiUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions/${processDefinitionId}/constant-values`; + return this.get(apiUrl).pipe( + map((res: { [key: string]: any }) => { + const result = []; + if (res) { + Object.keys(res).forEach((constant) => + result.push(new TaskVariableCloud({ name: constant, value: res[constant], type: 'string' })) + ); + } + return result; + }) + ); + } }