diff --git a/CHANGELOG.md b/CHANGELOG.md index b89e5b7b..09fe25b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## Added + +- support for `FORM` predicate type in `evaluateConditionalPredicate` + ## [6.0.1] - 2024-03-14 ### Fixed diff --git a/package-lock.json b/package-lock.json index e600369e..e0d3ac49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1817,7 +1817,7 @@ }, "node_modules/@oneblink/types": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/oneblink/types.git#86b2ef0ea557963fcd126e7cd068699191053ec2", + "resolved": "git+ssh://git@github.com/oneblink/types.git#6326d27be41ec8c3d721144421903f5126570213", "dev": true, "license": "GPL-3.0-only", "engines": { @@ -10785,7 +10785,7 @@ } }, "@oneblink/types": { - "version": "git+ssh://git@github.com/oneblink/types.git#86b2ef0ea557963fcd126e7cd068699191053ec2", + "version": "git+ssh://git@github.com/oneblink/types.git#6326d27be41ec8c3d721144421903f5126570213", "dev": true, "from": "@oneblink/types@github:oneblink/types" }, diff --git a/src/conditionalLogicService/evaluateConditionalPredicate.ts b/src/conditionalLogicService/evaluateConditionalPredicate.ts index 2b1bfac0..62e3a0de 100644 --- a/src/conditionalLogicService/evaluateConditionalPredicate.ts +++ b/src/conditionalLogicService/evaluateConditionalPredicate.ts @@ -3,6 +3,7 @@ import { FormElementsCtrl } from '../types' import { typeCastService, formElementsService } from '..' import evaluateConditionalOptionsPredicate from './evaluateConditionalOptionsPredicate' import { conditionallyShowByPredicate } from './conditionallyShowElement' +import { flattenFormElements } from '../formElementsService' const fnMap = { '>': (lhs: number, rhs: number) => lhs > rhs, @@ -139,6 +140,30 @@ export default function evaluateConditionalPredicate({ } return } + case 'FORM': + if (predicate.predicate) { + if ( + !predicateElement || + predicateElement.type !== 'form' || + !predicateElement.elements + ) { + return + } + const formModel = formElementsCtrl.model[predicateElement.name] as { + [name: string]: unknown + } + return evaluateConditionalPredicate({ + predicate: predicate.predicate, + formElementsCtrl: { + flattenedElements: flattenFormElements(predicateElement.elements), + model: formModel, + parentFormElementsCtrl: formElementsCtrl.parentFormElementsCtrl + ? formElementsCtrl.parentFormElementsCtrl + : formElementsCtrl, + }, + }) + } + return case 'OPTIONS': default: { const optionsPredicateElement = diff --git a/tests/conditionalLogicService/evaluateConditionalPredicate.test.ts b/tests/conditionalLogicService/evaluateConditionalPredicate.test.ts index 09a0e446..2b4694af 100644 --- a/tests/conditionalLogicService/evaluateConditionalPredicate.test.ts +++ b/tests/conditionalLogicService/evaluateConditionalPredicate.test.ts @@ -1,5 +1,6 @@ import { ConditionTypes, FormTypes } from '@oneblink/types' import evaluateConditionalPredicate from '../../src/conditionalLogicService/evaluateConditionalPredicate' +import { flattenFormElements } from '../../src/formElementsService' describe('evaluateConditionalPredicate', () => { const predicate: ConditionTypes.ConditionalPredicate = { @@ -42,6 +43,47 @@ describe('evaluateConditionalPredicate', () => { isDataLookup: false, isElementLookup: false, } + const nestedPredicate: ConditionTypes.ConditionalPredicate = { + elementId: 'formFormElement', + type: 'FORM', + predicate: predicate, + } + + const nestedPredicateElement: FormTypes.FormElement = { + id: 'predicateNumber', + name: 'predicateNumber', + label: 'predicateNumber', + type: 'number', + required: false, + conditionallyShow: true, + conditionallyShowPredicates: [nestedPredicate], + isDataLookup: false, + isElementLookup: false, + isSlider: false, + } + const childFormFormElementPredicate: ConditionTypes.ConditionalPredicate = { + elementId: 'childFormFormElement', + type: 'FORM', + predicate: predicate, + } + const parentFormFormElementPredicate: ConditionTypes.ConditionalPredicate = { + elementId: 'parentFormFormElement', + type: 'FORM', + predicate: childFormFormElementPredicate, + } + + const deeplyNestedPredicateElement: FormTypes.FormElement = { + id: 'predicateNumber', + name: 'predicateNumber', + label: 'predicateNumber', + type: 'number', + required: false, + conditionallyShow: true, + conditionallyShowPredicates: [parentFormFormElementPredicate], + isDataLookup: false, + isElementLookup: false, + isSlider: false, + } test('should show root element', () => { const isShown = evaluateConditionalPredicate({ @@ -108,4 +150,70 @@ describe('evaluateConditionalPredicate', () => { }) expect(isShown).toBe(predicateElement) }) + + test('should show element conditionally shown from element within a form element', () => { + const formFormElement: FormTypes.FormFormElement = { + id: 'formFormElement', + formId: 1, + name: 'formFormElement', + type: 'form', + conditionallyShow: false, + elements: [comparisonElement], + } + const isShown = evaluateConditionalPredicate({ + predicate: nestedPredicate, + formElementsCtrl: { + flattenedElements: flattenFormElements([ + formFormElement, + nestedPredicateElement, + ]), + model: { + formFormElement: { + comparisonNumber: 1, + }, + predicateNumber: 1, + }, + }, + }) + + expect(isShown).toBe(nestedPredicateElement) + }) + + test('should show element conditionally shown from element within a deeply nested form element', () => { + const childFormFormElement: FormTypes.FormFormElement = { + id: 'childFormFormElement', + formId: 1, + name: 'childFormFormElement', + type: 'form', + conditionallyShow: false, + elements: [comparisonElement], + } + const parentFormFormElement: FormTypes.FormFormElement = { + id: 'parentFormFormElement', + formId: 1, + name: 'parentFormFormElement', + type: 'form', + conditionallyShow: false, + elements: [childFormFormElement], + } + const isShown = evaluateConditionalPredicate({ + predicate: parentFormFormElementPredicate, + formElementsCtrl: { + flattenedElements: flattenFormElements([ + parentFormFormElement, + deeplyNestedPredicateElement, + ]), + model: { + parentFormFormElement: { + childFormFormElement: { + comparisonNumber: 1, + }, + }, + predicateNumber: 1, + }, + }, + }) + + expect(isShown).toBe(deeplyNestedPredicateElement) + }) })