[AAE-612] Support for Form Outcome Visibility Conditions (#5934)

This commit is contained in:
davidcanonieto 2020-07-30 17:05:10 +01:00 committed by GitHub
parent 0afbe36787
commit 1e692252a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 12 deletions

View File

@ -23,11 +23,30 @@ describe('FormOutcomeModel', () => {
it('should setup with json config', () => { it('should setup with json config', () => {
const json = { const json = {
id: '<id>', id: '<id>',
name: '<name>' name: '<name>',
visibilityCondition: {
leftType: 'field',
leftValue: 'TextOne',
operator: '==',
rightValue: 'showTab',
rightType: 'value',
nextConditionOperator: '',
nextCondition: null
}
}; };
const model = new FormOutcomeModel(null, json); const model = new FormOutcomeModel(null, json);
expect(model.id).toBe(json.id); expect(model.id).toBe(json.id);
expect(model.name).toBe(json.name); expect(model.name).toBe(json.name);
expect(model.visibilityCondition).toBeDefined();
});
it('should not setup with null json config', () => {
const model = new FormOutcomeModel(null, null);
expect(model.id).toBeUndefined();
expect(model.name).toBeUndefined();
expect(model.isVisible).toBeDefined();
expect(model.isVisible).toBe(true);
expect(model.visibilityCondition).toBeUndefined();
}); });
it('should store the form reference', () => { it('should store the form reference', () => {

View File

@ -19,6 +19,7 @@
import { FormWidgetModel } from './form-widget.model'; import { FormWidgetModel } from './form-widget.model';
import { FormModel } from './form.model'; import { FormModel } from './form.model';
import { WidgetVisibilityModel } from './../../../models/widget-visibility.model';
export class FormOutcomeModel extends FormWidgetModel { export class FormOutcomeModel extends FormWidgetModel {
@ -28,6 +29,8 @@ export class FormOutcomeModel extends FormWidgetModel {
isSystem: boolean = false; isSystem: boolean = false;
isSelected: boolean = false; isSelected: boolean = false;
isVisible: boolean = true;
visibilityCondition: WidgetVisibilityModel;
constructor(form: FormModel, json?: any) { constructor(form: FormModel, json?: any) {
super(form, json); super(form, json);
@ -35,6 +38,7 @@ export class FormOutcomeModel extends FormWidgetModel {
if (json) { if (json) {
this.isSystem = json.isSystem ? true : false; this.isSystem = json.isSystem ? true : false;
this.isSelected = form && json.name === form.selectedOutcome ? true : false; this.isSelected = form && json.name === form.selectedOutcome ? true : false;
this.visibilityCondition = new WidgetVisibilityModel(json.visibilityCondition);
} }
} }
} }

View File

@ -35,7 +35,7 @@ describe('TabModel', () => {
expect(model.isVisible).toBe(true); expect(model.isVisible).toBe(true);
}); });
it('should not setup with json config', () => { it('should not setup with null json config', () => {
const model = new TabModel(null, null); const model = new TabModel(null, null);
expect(model.id).toBeUndefined(); expect(model.id).toBeUndefined();
expect(model.title).toBeUndefined(); expect(model.title).toBeUndefined();

View File

@ -21,7 +21,8 @@ import {
FormFieldModel, FormFieldModel,
FormFieldTypes, FormFieldTypes,
FormModel, FormModel,
TabModel TabModel,
FormOutcomeModel
} from './../components/widgets/core/index'; } from './../components/widgets/core/index';
import { TaskProcessVariableModel } from './../models/task-process-variable.model'; import { TaskProcessVariableModel } from './../models/task-process-variable.model';
import { WidgetVisibilityModel, WidgetTypeEnum } from './../models/widget-visibility.model'; import { WidgetVisibilityModel, WidgetTypeEnum } from './../models/widget-visibility.model';
@ -31,7 +32,7 @@ import {
fakeFormJson, fakeTaskProcessVariableModels, fakeFormJson, fakeTaskProcessVariableModels,
formTest, formValues, complexVisibilityJsonVisible, formTest, formValues, complexVisibilityJsonVisible,
nextConditionForm, complexVisibilityJsonNotVisible, nextConditionForm, complexVisibilityJsonNotVisible,
headerVisibilityCond } from 'core/mock/form/widget-visibility-cloud.service.mock'; headerVisibilityCond } from '../../mock/form/widget-visibility-cloud.service.mock';
import { CoreTestingModule } from '../../testing/core.testing.module'; import { CoreTestingModule } from '../../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@ -672,6 +673,24 @@ describe('WidgetVisibilityCloudService', () => {
expect(fakeFormWithField.tabs[0].isVisible).toBeFalsy(); expect(fakeFormWithField.tabs[0].isVisible).toBeFalsy();
}); });
it('should refresh the visibility for Outcomes in forms', () => {
visibilityObjTest.leftType = WidgetTypeEnum.field;
visibilityObjTest.leftValue = 'FIELD_TEST';
visibilityObjTest.operator = '!=';
visibilityObjTest.rightValue = 'RIGHT_FORM_FIELD_VALUE';
const outcome = new FormOutcomeModel(fakeFormWithField, {
isSystem: false,
isSelected: false,
isVisible: true
});
outcome.visibilityCondition = visibilityObjTest;
fakeFormWithField.outcomes.push(outcome);
service.refreshVisibility(fakeFormWithField);
const outcomeIndex = fakeFormWithField.outcomes.length - 1;
expect(fakeFormWithField.outcomes[outcomeIndex].isVisible).toBeFalsy();
});
it('should use the form value to evaluate the visibility condition if the form value is defined', (done) => { it('should use the form value to evaluate the visibility condition if the form value is defined', (done) => {
service.getTaskProcessVariable('9999').subscribe( service.getTaskProcessVariable('9999').subscribe(
(res: TaskProcessVariableModel[]) => { (res: TaskProcessVariableModel[]) => {

View File

@ -20,7 +20,7 @@ import { LogService } from '../../services/log.service';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import moment from 'moment-es6'; import moment from 'moment-es6';
import { Observable, from, throwError } from 'rxjs'; import { Observable, from, throwError } from 'rxjs';
import { FormFieldModel, FormModel, TabModel, ContainerModel } from '../components/widgets/core/index'; import { FormFieldModel, FormModel, TabModel, ContainerModel, FormOutcomeModel } from '../components/widgets/core/index';
import { TaskProcessVariableModel } from '../models/task-process-variable.model'; import { TaskProcessVariableModel } from '../models/task-process-variable.model';
import { WidgetVisibilityModel, WidgetTypeEnum } from '../models/widget-visibility.model'; import { WidgetVisibilityModel, WidgetTypeEnum } from '../models/widget-visibility.model';
import { map, catchError } from 'rxjs/operators'; import { map, catchError } from 'rxjs/operators';
@ -43,6 +43,10 @@ export class WidgetVisibilityService {
form.tabs.map((tabModel) => this.refreshEntityVisibility(tabModel)); form.tabs.map((tabModel) => this.refreshEntityVisibility(tabModel));
} }
if (form && form.outcomes && form.outcomes.length > 0) {
form.outcomes.map((outcomeModel) => this.refreshOutcomeVisibility(outcomeModel));
}
if (form) { if (form) {
form.getFormFields().map((field) => this.refreshEntityVisibility(field)); form.getFormFields().map((field) => this.refreshEntityVisibility(field));
} }
@ -53,6 +57,10 @@ export class WidgetVisibilityService {
element.isVisible = visible && this.isParentTabVisible(this.form, element); element.isVisible = visible && this.isParentTabVisible(this.form, element);
} }
refreshOutcomeVisibility(element: FormOutcomeModel) {
element.isVisible = this.evaluateVisibility(element.form, element.visibilityCondition);
}
evaluateVisibility(form: FormModel, visibilityObj: WidgetVisibilityModel): boolean { evaluateVisibility(form: FormModel, visibilityObj: WidgetVisibilityModel): boolean {
const isLeftFieldPresent = visibilityObj && (visibilityObj.leftType || visibilityObj.leftValue); const isLeftFieldPresent = visibilityObj && (visibilityObj.leftType || visibilityObj.leftValue);
if (!isLeftFieldPresent || isLeftFieldPresent === 'null') { if (!isLeftFieldPresent || isLeftFieldPresent === 'null') {

View File

@ -36,12 +36,14 @@
</mat-card-content> </mat-card-content>
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions"> <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions">
<ng-content select="adf-cloud-form-custom-outcomes"></ng-content> <ng-content select="adf-cloud-form-custom-outcomes"></ng-content>
<button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes" <ng-container *ngFor="let outcome of form.outcomes">
[color]="getColorForOutcome(outcome.name)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)" <button *ngIf="outcome.isVisible" [id]="'adf-form-'+ outcome.name | formatSpace" [color]="getColorForOutcome(outcome.name)"
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)"
(click)="onOutcomeClicked(outcome)"> [class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
{{outcome.name | translate | uppercase }} (click)="onOutcomeClicked(outcome)">
</button> {{outcome.name | translate | uppercase }}
</button>
</ng-container>
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>
</div> </div>

View File

@ -991,6 +991,29 @@ describe('FormCloudComponent', () => {
const label = fixture.debugElement.query(By.css(`${container} label`)); const label = fixture.debugElement.query(By.css(`${container} label`));
expect(label.nativeElement.innerText).toEqual('Attach file'); expect(label.nativeElement.innerText).toEqual('Attach file');
}); });
it('should be able to set visibility conditions for Outcomes', async () => {
spyOn(formCloudService, 'getForm').and.returnValue(of(conditionalUploadWidgetsMock));
const formId = '123';
const appName = 'test-app';
formComponent.formId = formId;
formComponent.appVersion = 1;
formComponent.ngOnChanges({ 'appName': new SimpleChange(null, appName, true) });
expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId, 1);
fixture.detectChanges();
let outcome = fixture.debugElement.query(By.css(`#adf-form-custom_outcome`));
expect(outcome).toBeNull();
const inputElement = fixture.debugElement.query(By.css('[id="field-Text0xlk8n-container"] input'));
inputElement.nativeElement.value = 'hi';
inputElement.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
outcome = fixture.debugElement.query(By.css(`#adf-form-custom_outcome`));
expect(outcome.nativeElement.innerText).toEqual('CUSTOM OUTCOME');
});
}); });
describe('Multilingual Form', () => { describe('Multilingual Form', () => {

View File

@ -826,7 +826,21 @@ export const conditionalUploadWidgetsMock = {
} }
} }
], ],
'outcomes': [], 'outcomes': [
{
'id': '5f2f1c2d-5a79-4ed1-a262-4fef190d41eb',
'name': 'Custom Outcome',
'visibilityCondition': {
'leftType': 'field',
'leftValue': 'Text0xlk8n',
'operator': '==',
'rightValue': 'hi',
'rightType': 'value',
'nextConditionOperator': '',
'nextCondition': null
}
}
],
'metadata': {}, 'metadata': {},
'variables': [] 'variables': []
} }