Skip to content

Commit 96f9aa9

Browse files
committed
Refactor the component paths to ensure we are always referencing the correct path.
1 parent 770d1df commit 96f9aa9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1126
-895
lines changed

src/error/FieldError.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { getComponentErrorField } from 'process/validation/util';
21
import { ValidationContext } from 'types';
2+
import { getComponentErrorField } from 'utils/formUtil';
33

44
type FieldErrorContext = ValidationContext & {
55
field?: string;

src/modules/jsonlogic/index.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { BaseEvaluator, EvaluatorOptions } from 'utils';
1+
import { normalizeContext } from 'utils/formUtil';
22
import { jsonLogic } from './jsonLogic';
3+
import { BaseEvaluator, EvaluatorOptions, EvaluatorContext } from 'utils/Evaluator';
34
export class JSONLogicEvaluator extends BaseEvaluator {
45
public static evaluate(
56
func: any,
@@ -24,12 +25,6 @@ export class JSONLogicEvaluator extends BaseEvaluator {
2425
}
2526
}
2627

27-
export type EvaluatorContext = {
28-
evalContext?: (context: any) => any;
29-
instance?: any;
30-
[key: string]: any;
31-
};
32-
3328
export type EvaluatorFn = (context: EvaluatorContext) => any;
3429

3530
export function evaluate(
@@ -40,7 +35,9 @@ export function evaluate(
4035
options: EvaluatorOptions = {},
4136
) {
4237
const { evalContext, instance } = context;
43-
const evalContextValue = evalContext ? evalContext(context) : context;
38+
const evalContextValue = evalContext
39+
? evalContext(normalizeContext(context))
40+
: normalizeContext(context);
4441
if (evalContextFn) {
4542
evalContextFn(evalContextValue);
4643
}
@@ -63,7 +60,9 @@ export function interpolate(
6360
evalContextFn?: EvaluatorFn,
6461
): string {
6562
const { evalContext, instance } = context;
66-
const evalContextValue = evalContext ? evalContext(context) : context;
63+
const evalContextValue = evalContext
64+
? evalContext(normalizeContext(context))
65+
: normalizeContext(context);
6766
if (evalContextFn) {
6867
evalContextFn(evalContextValue);
6968
}

src/process/__tests__/process.test.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
skipValidForLogicallyHiddenComp,
1515
skipValidWithHiddenParentComp,
1616
} from './fixtures';
17-
import { get } from 'lodash';
17+
import _ from 'lodash';
1818

1919
/*
2020
describe('Process Tests', () => {
@@ -959,6 +959,7 @@ describe('Process Tests', function () {
959959

960960
const errors: any = [];
961961
const context = {
962+
_,
962963
form,
963964
submission,
964965
data: submission.data,
@@ -1114,8 +1115,8 @@ describe('Process Tests', function () {
11141115
submission.data = context.data;
11151116
context.processors = ProcessTargets.evaluator;
11161117
processSync(context);
1117-
assert.equal(get(context.submission.data, 'form1.data.form.data.textField'), 'one 1');
1118-
assert.equal(get(context.submission.data, 'form1.data.form.data.textField1'), 'two 2');
1118+
assert.equal(_.get(context.submission.data, 'form1.data.form.data.textField'), 'one 1');
1119+
assert.equal(_.get(context.submission.data, 'form1.data.form.data.textField1'), 'two 2');
11191120
});
11201121

11211122
it('should remove submission data not in a nested form definition', async function () {
@@ -3437,7 +3438,7 @@ describe('Process Tests', function () {
34373438
});
34383439
});
34393440

3440-
it('Should allow the submission to go through without errors if there is no the subform reference value', async function () {
3441+
it('Should allow the submission to go through without errors if there is no subform reference value', async function () {
34413442
const form = {
34423443
_id: '66bc5cff7ca1729623a182db',
34433444
title: 'form2',

src/process/calculation/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ProcessorInfo,
88
} from 'types';
99
import { set } from 'lodash';
10+
import { normalizeContext } from 'utils/formUtil';
1011

1112
export const shouldCalculate = (context: CalculationContext): boolean => {
1213
const { component, config } = context;
@@ -23,7 +24,9 @@ export const calculateProcessSync: ProcessorFnSync<CalculationScope> = (
2324
if (!shouldCalculate(context)) {
2425
return;
2526
}
26-
const evalContextValue = evalContext ? evalContext(context) : context;
27+
const evalContextValue = evalContext
28+
? evalContext(normalizeContext(context))
29+
: normalizeContext(context);
2730
evalContextValue.value = value || null;
2831
if (!scope.calculated) scope.calculated = [];
2932
const newValue = JSONLogicEvaluator.evaluate(component.calculateValue, evalContextValue, 'value');

src/process/clearHidden.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
ProcessorFnSync,
77
ConditionsScope,
88
} from 'types';
9-
import { getComponentAbsolutePath } from 'utils/formUtil';
109

1110
type ClearHiddenScope = ProcessorScope & {
1211
clearHidden: {
@@ -19,7 +18,6 @@ type ClearHiddenScope = ProcessorScope & {
1918
*/
2019
export const clearHiddenProcess: ProcessorFnSync<ClearHiddenScope> = (context) => {
2120
const { component, data, value, scope, path } = context;
22-
const absolutePath = getComponentAbsolutePath(component) || path;
2321

2422
// No need to unset the value if it's undefined
2523
if (value === undefined) {
@@ -32,18 +30,18 @@ export const clearHiddenProcess: ProcessorFnSync<ClearHiddenScope> = (context) =
3230

3331
// Check if there's a conditional set for the component and if it's marked as conditionally hidden
3432
const isConditionallyHidden = (scope as ConditionsScope).conditionals?.find((cond) => {
35-
return absolutePath === cond.path && cond.conditionallyHidden;
33+
return path === cond.path && cond.conditionallyHidden;
3634
});
3735

3836
const shouldClearValueWhenHidden =
3937
!component.hasOwnProperty('clearOnHide') || component.clearOnHide;
4038

4139
if (
4240
shouldClearValueWhenHidden &&
43-
(isConditionallyHidden || component.hidden || component.ephemeralState?.conditionallyHidden)
41+
(isConditionallyHidden || component.hidden || component.scope?.conditionallyHidden)
4442
) {
45-
unset(data, absolutePath);
46-
scope.clearHidden[absolutePath] = true;
43+
unset(data, path);
44+
scope.clearHidden[path] = true;
4745
}
4846
};
4947

src/process/conditions/index.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
ProcessorInfo,
66
ConditionsContext,
77
} from 'types';
8-
import { registerEphemeralState } from 'utils';
8+
import { setComponentScope } from 'utils/formUtil';
99
import {
1010
checkCustomConditional,
1111
checkJsonConditional,
@@ -15,7 +15,6 @@ import {
1515
isSimpleConditional,
1616
isJSONConditional,
1717
} from 'utils/conditions';
18-
import { getComponentAbsolutePath } from 'utils/formUtil';
1918

2019
const hasCustomConditions = (context: ConditionsContext): boolean => {
2120
const { component } = context;
@@ -85,24 +84,23 @@ export type ConditionallyHidden = (context: ConditionsContext) => boolean;
8584

8685
export const conditionalProcess = (context: ConditionsContext, isHidden: ConditionallyHidden) => {
8786
const { scope, path, component } = context;
88-
const absolutePath = getComponentAbsolutePath(component) || path;
8987
if (!hasConditions(context)) {
9088
return;
9189
}
9290

9391
if (!scope.conditionals) {
9492
scope.conditionals = [];
9593
}
96-
let conditionalComp = scope.conditionals.find((cond) => cond.path === absolutePath);
94+
let conditionalComp = scope.conditionals.find((cond) => cond.path === path);
9795
if (!conditionalComp) {
98-
conditionalComp = { path: absolutePath, conditionallyHidden: false };
96+
conditionalComp = { path, conditionallyHidden: false };
9997
scope.conditionals.push(conditionalComp);
10098
}
10199

102100
conditionalComp.conditionallyHidden =
103101
conditionalComp.conditionallyHidden || isHidden(context) === true;
104102
if (conditionalComp.conditionallyHidden) {
105-
registerEphemeralState(context.component, 'conditionallyHidden', true);
103+
setComponentScope(component, 'conditionallyHidden', true);
106104
}
107105
};
108106

src/process/defaultValue/index.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
DefaultValueContext,
88
} from 'types';
99
import { set, has } from 'lodash';
10-
import { getComponentKey } from 'utils/formUtil';
10+
import { getComponentKey, normalizeContext } from 'utils/formUtil';
1111

1212
export const hasCustomDefaultValue = (context: DefaultValueContext): boolean => {
1313
const { component } = context;
@@ -48,7 +48,9 @@ export const customDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
4848
}
4949
let defaultValue = null;
5050
if (component.customDefaultValue) {
51-
const evalContextValue = evalContext ? evalContext(context) : context;
51+
const evalContextValue = evalContext
52+
? evalContext(normalizeContext(context))
53+
: normalizeContext(context);
5254
evalContextValue.value = null;
5355
defaultValue = JSONLogicEvaluator.evaluate(
5456
component.customDefaultValue,

src/process/fetch/index.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from 'types';
1010
import { get, set } from 'lodash';
1111
import { Evaluator } from 'utils';
12-
import { getComponentKey } from 'utils/formUtil';
12+
import { getComponentKey, normalizeContext } from 'utils/formUtil';
1313

1414
export const shouldFetch = (context: FetchContext): boolean => {
1515
const { component, config } = context;
@@ -38,7 +38,9 @@ export const fetchProcess: ProcessorFn<FetchScope> = async (context: FetchContex
3838
return;
3939
}
4040
if (!scope.fetched) scope.fetched = {};
41-
const evalContextValue = evalContext ? evalContext(context) : context;
41+
const evalContextValue = evalContext
42+
? evalContext(normalizeContext(context))
43+
: normalizeContext(context);
4244
const url = Evaluator.interpolateString(get(component, 'fetch.url', ''), evalContextValue);
4345
if (!url) {
4446
return;

src/process/filter/__tests__/filter.test.ts

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ describe('Filter processor', function () {
3535
type: 'editgrid',
3636
key: 'editGrid',
3737
input: true,
38-
path: 'editGrid',
3938
components: [
4039
{
4140
type: 'textfield',

src/process/filter/index.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,44 @@
11
import { FilterContext, FilterScope, ProcessorFn, ProcessorFnSync, ProcessorInfo } from 'types';
22
import { set } from 'lodash';
3-
import { Utils } from 'utils';
43
import { get, isObject } from 'lodash';
5-
import { getComponentAbsolutePath } from 'utils/formUtil';
4+
import { getModelType } from 'utils/formUtil';
65
export const filterProcessSync: ProcessorFnSync<FilterScope> = (context: FilterContext) => {
76
const { scope, component, path } = context;
87
const { value } = context;
9-
const absolutePath = getComponentAbsolutePath(component) || path;
108
if (!scope.filter) scope.filter = {};
119
if (value !== undefined) {
12-
const modelType = Utils.getModelType(component);
10+
const modelType = getModelType(component);
1311
switch (modelType) {
1412
case 'dataObject':
15-
scope.filter[absolutePath] = {
13+
scope.filter[path] = {
1614
compModelType: modelType,
1715
include: true,
1816
value: { data: {} },
1917
};
2018
break;
2119
case 'nestedArray':
22-
scope.filter[absolutePath] = {
20+
scope.filter[path] = {
2321
compModelType: modelType,
2422
include: true,
2523
value: [],
2624
};
2725
break;
2826
case 'nestedDataArray':
29-
scope.filter[absolutePath] = {
27+
scope.filter[path] = {
3028
compModelType: modelType,
3129
include: true,
3230
value: Array.isArray(value) ? value.map((v) => ({ ...v, data: {} })) : [],
3331
};
3432
break;
3533
case 'object':
36-
scope.filter[absolutePath] = {
34+
scope.filter[path] = {
3735
compModelType: modelType,
3836
include: true,
3937
value: component.type === 'address' ? false : {},
4038
};
4139
break;
4240
default:
43-
scope.filter[absolutePath] = {
41+
scope.filter[path] = {
4442
compModelType: modelType,
4543
include: true,
4644
};

src/process/hideChildren.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,24 @@ import {
66
ConditionsScope,
77
ProcessorFn,
88
} from 'types';
9-
import { registerEphemeralState } from 'utils';
10-
import { getComponentAbsolutePath } from 'utils/formUtil';
9+
import { setComponentScope } from 'utils/formUtil';
1110

1211
/**
1312
* This processor function checks components for the `hidden` property and, if children are present, sets them to hidden as well.
1413
*/
1514
export const hideChildrenProcessor: ProcessorFnSync<ConditionsScope> = (context) => {
1615
const { component, path, parent, scope } = context;
17-
const absolutePath = getComponentAbsolutePath(component) || path;
1816
// Check if there's a conditional set for the component and if it's marked as conditionally hidden
1917
const isConditionallyHidden = scope.conditionals?.find((cond) => {
20-
return absolutePath === cond.path && cond.conditionallyHidden;
18+
return path === cond.path && cond.conditionallyHidden;
2119
});
2220

2321
if (!scope.conditionals) {
2422
scope.conditionals = [];
2523
}
2624

27-
if (isConditionallyHidden || component.hidden || parent?.ephemeralState?.conditionallyHidden) {
28-
registerEphemeralState(component, 'conditionallyHidden', true);
25+
if (isConditionallyHidden || component.hidden || parent?.scope?.conditionallyHidden) {
26+
setComponentScope(component, 'conditionallyHidden', true);
2927
}
3028
};
3129

src/process/populate/index.ts

+11-13
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
1-
import { get, set } from 'lodash';
1+
import { set } from 'lodash';
22
import { PopulateContext, PopulateScope, ProcessorFnSync } from 'types';
3-
import { componentPath, getContextualRowPath, getModelType } from 'utils/formUtil';
3+
import { getModelType } from 'utils/formUtil';
44

55
// This processor ensures that a "linked" row context is provided to every component.
66
export const populateProcessSync: ProcessorFnSync<PopulateScope> = (context: PopulateContext) => {
7-
const { component, path, scope } = context;
7+
const { component, path, scope, value } = context;
88
const { data } = scope;
9-
const compDataPath = componentPath(component, getContextualRowPath(component, path));
10-
const compData: any = get(data, compDataPath);
119
if (!scope.populated) scope.populated = [];
1210
switch (getModelType(component)) {
1311
case 'nestedArray':
14-
if (!compData || !compData.length) {
15-
set(data, compDataPath, [{}]);
16-
scope.row = get(data, compDataPath)[0];
12+
if (!value || !value.length) {
13+
const newValue = [{}];
14+
set(data, path, newValue);
15+
scope.row = newValue[0];
1716
scope.populated.push({
1817
path,
19-
row: get(data, compDataPath)[0],
2018
});
2119
}
2220
break;
2321
case 'dataObject':
2422
case 'object':
25-
if (!compData || typeof compData !== 'object') {
26-
set(data, compDataPath, {});
27-
scope.row = get(data, compDataPath);
23+
if (!value || typeof value !== 'object') {
24+
const newValue = {};
25+
set(data, value, newValue);
26+
scope.row = newValue;
2827
scope.populated.push({
2928
path,
30-
row: get(data, compDataPath),
3129
});
3230
}
3331
break;

0 commit comments

Comments
 (0)