From cb988b0145fa43d804ddaa56ab211a9175914564 Mon Sep 17 00:00:00 2001 From: Silviu Popa Date: Fri, 9 Aug 2019 00:51:10 +0300 Subject: [PATCH] [ADF-4790] [ADF-4791] - fix visibility condition for text/checkbox and variable/value (#4978) * [ADF-4790] [ADF-4791] - fix visibility condition for empty string and checkbox - value/variable * reset package-lock * reset package-lock.json * fix lint and change return type --- .../widgets/core/form-field.model.ts | 3 + .../widget-visibility-cloud.service.spec.ts | 110 ++++++++++++++++-- .../services/widget-visibility.service.ts | 21 ++-- .../widget-visibility-cloud.service.mock.ts | 84 +++++++++++++ 4 files changed, 201 insertions(+), 17 deletions(-) diff --git a/lib/core/form/components/widgets/core/form-field.model.ts b/lib/core/form/components/widgets/core/form-field.model.ts index db8f85ddf3..2993564929 100644 --- a/lib/core/form/components/widgets/core/form-field.model.ts +++ b/lib/core/form/components/widgets/core/form-field.model.ts @@ -413,6 +413,9 @@ export class FormFieldModel extends FormWidgetModel { case FormFieldTypes.AMOUNT: this.form.values[this.id] = this.enableFractions ? parseFloat(this.value) : parseInt(this.value, 10); break; + case FormFieldTypes.BOOLEAN: + this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : false; + break; default: if (!FormFieldTypes.isReadOnlyType(this.type) && !this.isInvalidFieldType(this.type)) { this.form.values[this.id] = this.value; diff --git a/lib/core/form/services/widget-visibility-cloud.service.spec.ts b/lib/core/form/services/widget-visibility-cloud.service.spec.ts index 8fd7f5a079..ba51e2dd8b 100644 --- a/lib/core/form/services/widget-visibility-cloud.service.spec.ts +++ b/lib/core/form/services/widget-visibility-cloud.service.spec.ts @@ -34,7 +34,8 @@ import { AlfrescoApiServiceMock } from '../../mock/alfresco-api.service.mock'; import { fakeFormJson, fakeTaskProcessVariableModels, formTest, formValues, complexVisibilityJsonVisible, - nextConditionForm, complexVisibilityJsonNotVisible } from 'core/mock/form/widget-visibility-cloud.service.mock'; + nextConditionForm, complexVisibilityJsonNotVisible, + headerVisibilityCond } from 'core/mock/form/widget-visibility-cloud.service.mock'; declare let jasmine: any; @@ -398,7 +399,7 @@ describe('WidgetVisibilityCloudService', () => { const formValue = service.searchValueInForm(stubFormWithFields, 'FIELD_MYSTERY'); expect(formValue).not.toBeUndefined(); - expect(formValue).toBe(''); + expect(formValue).toEqual(''); }); it('should search in the form if element value is not in form values', () => { @@ -412,7 +413,7 @@ describe('WidgetVisibilityCloudService', () => { const formValue = service.getFormValue(fakeFormWithField, 'FIELD_MYSTERY'); expect(formValue).not.toBeUndefined(); - expect(formValue).toBe(''); + expect(formValue).toEqual(''); }); it('should retrieve the value for the right field when it is a value', () => { @@ -480,9 +481,9 @@ describe('WidgetVisibilityCloudService', () => { expect(leftValue).toBe('value_2'); }); - it('should return empty string for a value that is not on variable or form', () => { + it('should return undefined for a value that is not on variable or form', () => { const leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); - expect(leftValue).toBe(''); + expect(leftValue).toEqual(''); }); it('should evaluate the visibility for the field with single visibility condition between two field values', () => { @@ -507,9 +508,11 @@ describe('WidgetVisibilityCloudService', () => { }); it('should evaluate the visibility for the field with single visibility condition between form values', () => { - visibilityObjTest.leftType = 'LEFT_FORM_FIELD_ID'; + visibilityObjTest.leftType = WidgetTypeEnum.field; + visibilityObjTest.leftValue = 'LEFT_FORM_FIELD_ID'; visibilityObjTest.operator = '!='; - visibilityObjTest.rightType = 'RIGHT_FORM_FIELD_ID'; + visibilityObjTest.rightType = WidgetTypeEnum.field; + visibilityObjTest.rightValue = 'RIGHT_FORM_FIELD_ID'; const isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); expect(isVisible).toBeTruthy(); @@ -740,6 +743,7 @@ describe('WidgetVisibilityCloudService', () => { visibilityObjTest.leftType = WidgetTypeEnum.field; visibilityObjTest.leftValue = 'FIELD_FORM_EMPTY'; visibilityObjTest.operator = '=='; + visibilityObjTest.rightType = WidgetTypeEnum.value; visibilityObjTest.rightValue = 'PROCESS_RIGHT_FORM_FIELD_VALUE'; const myForm = new FormModel({ @@ -1075,5 +1079,97 @@ describe('WidgetVisibilityCloudService', () => { expect(isVisible).toBeTruthy(); }); + + it('should evaluate visibility between checkbox and variable', (done) => { + visibilityObjTest.leftType = WidgetTypeEnum.field; + visibilityObjTest.leftValue = 'CheckboxTwo'; + visibilityObjTest.operator = '=='; + visibilityObjTest.rightType = WidgetTypeEnum.variable; + visibilityObjTest.rightValue = 'var2'; + + const checkboxForm = new FormModel({ + id: '9999', + name: 'CHECKBOX_VISIBILITY', + processDefinitionId: 'PROCESS_TEST:9:9999', + processDefinitionName: 'PROCESS_TEST', + processDefinitionKey: 'PROCESS_TEST', + taskId: '999', + taskName: 'TEST', + fields: [ + { + fieldType: 'ContainerRepresentation', + id: '000000000000000000', + name: 'Label', + type: 'container', + value: null, + numberOfColumns: 2, + fields: { + 1: [ + { + id: 'CheckboxOne', + name: 'CheckboxOne', + type: 'boolean', + required: false, + value: false, + colspan: 1, + visibilityCondition: null + }, + { + id: 'CheckboxTwo', + name: 'CheckboxTwo', + type: 'boolean', + required: false, + value: false, + colspan: 1, + visibilityCondition: null + } + ], + 2: [ + { + id: 'CheckboxThree', + name: 'CheckboxThree', + type: 'boolean', + required: false, + colspan: 1, + visibilityCondition: visibilityObjTest + } + ] + } + } + ], + variables: [ + { + id: 'id', + name: 'var2', + type: 'boolean', + value: false + } + ] + }); + + service.refreshVisibility(checkboxForm); + + const fieldWithVisibilityAttached = checkboxForm.getFieldById('CheckboxThree'); + expect(fieldWithVisibilityAttached.isVisible).toBeTruthy(); + done(); + }); + + it('should evaluate visibility between empty text fields', (done) => { + visibilityObjTest.leftType = WidgetTypeEnum.field; + visibilityObjTest.leftValue = 'Text1'; + visibilityObjTest.operator = '=='; + visibilityObjTest.rightType = WidgetTypeEnum.field; + visibilityObjTest.rightValue = 'Text2'; + + const checkboxForm = new FormModel(headerVisibilityCond); + checkboxForm.getFieldById('Text1').value = '1'; + checkboxForm.getFieldById('Text1').value = ''; + + service.refreshVisibility(checkboxForm); + + const fieldWithVisibilityAttached = checkboxForm.getFieldById('Header0hm6n0'); + expect(fieldWithVisibilityAttached.isVisible).toBeTruthy(); + done(); + }); }); }); diff --git a/lib/core/form/services/widget-visibility.service.ts b/lib/core/form/services/widget-visibility.service.ts index 915319b586..8fc01d7edd 100644 --- a/lib/core/form/services/widget-visibility.service.ts +++ b/lib/core/form/services/widget-visibility.service.ts @@ -98,8 +98,9 @@ export class WidgetVisibilityService { leftValue = this.getVariableValue(form, visibilityObj.leftValue, this.processVarList); } else if (visibilityObj.leftType && visibilityObj.leftType === WidgetTypeEnum.field) { leftValue = this.getFormValue(form, visibilityObj.leftValue); - if (this.isInvalidValue(leftValue)) { - leftValue = this.getVariableValue(form, visibilityObj.leftValue, this.processVarList); + if (leftValue === undefined || leftValue === '') { + const variableValue = this.getVariableValue(form, visibilityObj.leftValue, this.processVarList); + leftValue = !this.isInvalidValue(variableValue) ? variableValue : leftValue; } } return leftValue; @@ -124,7 +125,7 @@ export class WidgetVisibilityService { getFormValue(form: FormModel, fieldId: string): any { let value = this.getFieldValue(form.values, fieldId); - if (!value) { + if (this.isInvalidValue(value)) { value = this.searchValueInForm(form, fieldId); } return value; @@ -146,7 +147,7 @@ export class WidgetVisibilityService { } private isInvalidValue(value: any): boolean { - return value === undefined || value === ''; + return value === undefined || value === null; } searchValueInForm(form: FormModel, fieldId: string): string { @@ -157,13 +158,12 @@ export class WidgetVisibilityService { if (!fieldValue) { if (formField.value && formField.value.id) { fieldValue = formField.value.id; - } else { + } else if (!this.isInvalidValue(formField.value)) { fieldValue = formField.value; } } } }); - return fieldValue; } @@ -195,11 +195,12 @@ export class WidgetVisibilityService { } getVariableValue(form: FormModel, name: string, processVarList: TaskProcessVariableModel[]): string { - return this.getFormVariableValue(form, name) || - this.getProcessVariableValue(name, processVarList); + const processVariableValue = this.getProcessVariableValue(name, processVarList); + const variableDefaultValue = this.getFormVariableDefaultValue(form, name); + return (processVariableValue === undefined) ? variableDefaultValue : processVariableValue; } - private getFormVariableValue(form: FormModel, identifier: string): string { + private getFormVariableDefaultValue(form: FormModel, identifier: string): string { const variables = this.getFormVariables(form); if (variables) { const formVariable = variables.find((formVar) => { @@ -213,7 +214,6 @@ export class WidgetVisibilityService { value += 'T00:00:00.000Z'; } } - return value; } } @@ -229,6 +229,7 @@ export class WidgetVisibilityService { return processVariable.value; } } + } evaluateLogicalOperation(logicOp, previousValue, newValue): boolean { diff --git a/lib/core/mock/form/widget-visibility-cloud.service.mock.ts b/lib/core/mock/form/widget-visibility-cloud.service.mock.ts index b37630aeac..f8a6d3cde2 100644 --- a/lib/core/mock/form/widget-visibility-cloud.service.mock.ts +++ b/lib/core/mock/form/widget-visibility-cloud.service.mock.ts @@ -954,3 +954,87 @@ export let nextConditionForm = { } ] }; + +export let headerVisibilityCond = { + 'id': 'form-f0823c05-51eb-4703-8634-75a6d5e15df5', + 'name': 'text_form', + 'description': '', + 'version': 0, + 'standAlone': true, + 'formDefinition': { + 'tabs': [], + 'fields': [ + { + 'id': 'Header0hm6n0', + 'name': 'Header', + 'type': 'group', + 'tab': null, + 'params': { + 'allowCollapse': false, + 'collapseByDefault': false + }, + 'numberOfColumns': 1, + 'fields': { + '1': [] + }, + 'visibilityCondition': { + 'leftType': 'field', + 'leftValue': 'Text1', + 'operator': '==', + 'rightValue': 'Text2', + 'rightType': 'field', + 'nextConditionOperator': '', + 'nextCondition': null + } + }, + { + 'id': '19c3a066-c1bf-47f1-97f2-2b9420be3566', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'id': 'Text1', + 'name': 'Text1', + 'type': 'text', + 'required': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'regexPattern': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'id': 'Text2', + 'name': 'Text2', + 'type': 'text', + 'required': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'regexPattern': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + } + ], + 'outcomes': [], + 'metadata': {}, + 'variables': [] + } +};