Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the component paths to ensure we are always referencing the correct path. #193

Merged
merged 6 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/error/FieldError.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getComponentErrorField } from 'process/validation/util';
import { ValidationContext } from 'types';
import { getComponentErrorField } from 'utils/formUtil';

type FieldErrorContext = ValidationContext & {
field?: string;
Expand Down
17 changes: 8 additions & 9 deletions src/modules/jsonlogic/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { BaseEvaluator, EvaluatorOptions } from 'utils';
import { normalizeContext } from 'utils/formUtil';
import { jsonLogic } from './jsonLogic';
import { BaseEvaluator, EvaluatorOptions, EvaluatorContext } from 'utils/Evaluator';
export class JSONLogicEvaluator extends BaseEvaluator {
public static evaluate(
func: any,

Check warning on line 6 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 6 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
args: any = {},

Check warning on line 7 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 7 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
ret: any = '',

Check warning on line 8 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 8 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
interpolate: boolean = false,
context: any = {},

Check warning on line 10 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 10 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
options: EvaluatorOptions = {},
) {
let returnVal = null;
Expand All @@ -24,13 +25,7 @@
}
}

export type EvaluatorContext = {
evalContext?: (context: any) => any;
instance?: any;
[key: string]: any;
};

export type EvaluatorFn = (context: EvaluatorContext) => any;

Check warning on line 28 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 28 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type

export function evaluate(
context: EvaluatorContext,
Expand All @@ -40,14 +35,16 @@
options: EvaluatorOptions = {},
) {
const { evalContext, instance } = context;
const evalContextValue = evalContext ? evalContext(context) : context;
const evalContextValue = evalContext
? evalContext(normalizeContext(context))
: normalizeContext(context);
if (evalContextFn) {
evalContextFn(evalContextValue);
}
if (instance && (instance as any).evaluate) {

Check warning on line 44 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 44 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
return (instance as any).evaluate(evaluation, evalContextValue, ret, false, options);

Check warning on line 45 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 45 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
}
return (JSONLogicEvaluator as any).evaluate(

Check warning on line 47 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / setup

Unexpected any. Specify a different type

Check warning on line 47 in src/modules/jsonlogic/index.ts

View workflow job for this annotation

GitHub Actions / publish

Unexpected any. Specify a different type
evaluation,
evalContextValue,
ret,
Expand All @@ -63,7 +60,9 @@
evalContextFn?: EvaluatorFn,
): string {
const { evalContext, instance } = context;
const evalContextValue = evalContext ? evalContext(context) : context;
const evalContextValue = evalContext
? evalContext(normalizeContext(context))
: normalizeContext(context);
if (evalContextFn) {
evalContextFn(evalContextValue);
}
Expand Down
9 changes: 5 additions & 4 deletions src/process/__tests__/process.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
skipValidForLogicallyHiddenComp,
skipValidWithHiddenParentComp,
} from './fixtures';
import { get } from 'lodash';
import _ from 'lodash';

/*
describe('Process Tests', () => {
Expand Down Expand Up @@ -959,6 +959,7 @@ describe('Process Tests', function () {

const errors: any = [];
const context = {
_,
form,
submission,
data: submission.data,
Expand Down Expand Up @@ -1114,8 +1115,8 @@ describe('Process Tests', function () {
submission.data = context.data;
context.processors = ProcessTargets.evaluator;
processSync(context);
assert.equal(get(context.submission.data, 'form1.data.form.data.textField'), 'one 1');
assert.equal(get(context.submission.data, 'form1.data.form.data.textField1'), 'two 2');
assert.equal(_.get(context.submission.data, 'form1.data.form.data.textField'), 'one 1');
assert.equal(_.get(context.submission.data, 'form1.data.form.data.textField1'), 'two 2');
});

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

it('Should allow the submission to go through without errors if there is no the subform reference value', async function () {
it('Should allow the submission to go through without errors if there is no subform reference value', async function () {
const form = {
_id: '66bc5cff7ca1729623a182db',
title: 'form2',
Expand Down
5 changes: 4 additions & 1 deletion src/process/calculation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ProcessorInfo,
} from 'types';
import { set } from 'lodash';
import { normalizeContext } from 'utils/formUtil';

export const shouldCalculate = (context: CalculationContext): boolean => {
const { component, config } = context;
Expand All @@ -23,7 +24,9 @@ export const calculateProcessSync: ProcessorFnSync<CalculationScope> = (
if (!shouldCalculate(context)) {
return;
}
const evalContextValue = evalContext ? evalContext(context) : context;
const evalContextValue = evalContext
? evalContext(normalizeContext(context))
: normalizeContext(context);
evalContextValue.value = value || null;
if (!scope.calculated) scope.calculated = [];
const newValue = JSONLogicEvaluator.evaluate(component.calculateValue, evalContextValue, 'value');
Expand Down
10 changes: 4 additions & 6 deletions src/process/clearHidden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ProcessorFnSync,
ConditionsScope,
} from 'types';
import { getComponentAbsolutePath } from 'utils/formUtil';

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

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

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

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

if (
shouldClearValueWhenHidden &&
(isConditionallyHidden || component.hidden || component.ephemeralState?.conditionallyHidden)
(isConditionallyHidden || component.hidden || component.scope?.conditionallyHidden)
) {
unset(data, absolutePath);
scope.clearHidden[absolutePath] = true;
unset(data, path);
scope.clearHidden[path] = true;
}
};

Expand Down
10 changes: 4 additions & 6 deletions src/process/conditions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ProcessorInfo,
ConditionsContext,
} from 'types';
import { registerEphemeralState } from 'utils';
import { setComponentScope } from 'utils/formUtil';
import {
checkCustomConditional,
checkJsonConditional,
Expand All @@ -15,7 +15,6 @@ import {
isSimpleConditional,
isJSONConditional,
} from 'utils/conditions';
import { getComponentAbsolutePath } from 'utils/formUtil';

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

export const conditionalProcess = (context: ConditionsContext, isHidden: ConditionallyHidden) => {
const { scope, path, component } = context;
const absolutePath = getComponentAbsolutePath(component) || path;
if (!hasConditions(context)) {
return;
}

if (!scope.conditionals) {
scope.conditionals = [];
}
let conditionalComp = scope.conditionals.find((cond) => cond.path === absolutePath);
let conditionalComp = scope.conditionals.find((cond) => cond.path === path);
if (!conditionalComp) {
conditionalComp = { path: absolutePath, conditionallyHidden: false };
conditionalComp = { path, conditionallyHidden: false };
scope.conditionals.push(conditionalComp);
}

conditionalComp.conditionallyHidden =
conditionalComp.conditionallyHidden || isHidden(context) === true;
if (conditionalComp.conditionallyHidden) {
registerEphemeralState(context.component, 'conditionallyHidden', true);
setComponentScope(component, 'conditionallyHidden', true);
}
};

Expand Down
6 changes: 4 additions & 2 deletions src/process/defaultValue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
DefaultValueContext,
} from 'types';
import { set, has } from 'lodash';
import { getComponentKey } from 'utils/formUtil';
import { getComponentKey, normalizeContext } from 'utils/formUtil';

export const hasCustomDefaultValue = (context: DefaultValueContext): boolean => {
const { component } = context;
Expand Down Expand Up @@ -48,7 +48,9 @@ export const customDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
}
let defaultValue = null;
if (component.customDefaultValue) {
const evalContextValue = evalContext ? evalContext(context) : context;
const evalContextValue = evalContext
? evalContext(normalizeContext(context))
: normalizeContext(context);
evalContextValue.value = null;
defaultValue = JSONLogicEvaluator.evaluate(
component.customDefaultValue,
Expand Down
6 changes: 4 additions & 2 deletions src/process/fetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from 'types';
import { get, set } from 'lodash';
import { Evaluator } from 'utils';
import { getComponentKey } from 'utils/formUtil';
import { getComponentKey, normalizeContext } from 'utils/formUtil';

export const shouldFetch = (context: FetchContext): boolean => {
const { component, config } = context;
Expand Down Expand Up @@ -38,7 +38,9 @@ export const fetchProcess: ProcessorFn<FetchScope> = async (context: FetchContex
return;
}
if (!scope.fetched) scope.fetched = {};
const evalContextValue = evalContext ? evalContext(context) : context;
const evalContextValue = evalContext
? evalContext(normalizeContext(context))
: normalizeContext(context);
const url = Evaluator.interpolateString(get(component, 'fetch.url', ''), evalContextValue);
if (!url) {
return;
Expand Down
1 change: 0 additions & 1 deletion src/process/filter/__tests__/filter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ describe('Filter processor', function () {
type: 'editgrid',
key: 'editGrid',
input: true,
path: 'editGrid',
components: [
{
type: 'textfield',
Expand Down
16 changes: 7 additions & 9 deletions src/process/filter/index.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,44 @@
import { FilterContext, FilterScope, ProcessorFn, ProcessorFnSync, ProcessorInfo } from 'types';
import { set } from 'lodash';
import { Utils } from 'utils';
import { get, isObject } from 'lodash';
import { getComponentAbsolutePath } from 'utils/formUtil';
import { getModelType } from 'utils/formUtil';
export const filterProcessSync: ProcessorFnSync<FilterScope> = (context: FilterContext) => {
const { scope, component, path } = context;
const { value } = context;
const absolutePath = getComponentAbsolutePath(component) || path;
if (!scope.filter) scope.filter = {};
if (value !== undefined) {
const modelType = Utils.getModelType(component);
const modelType = getModelType(component);
switch (modelType) {
case 'dataObject':
scope.filter[absolutePath] = {
scope.filter[path] = {
compModelType: modelType,
include: true,
value: { data: {} },
};
break;
case 'nestedArray':
scope.filter[absolutePath] = {
scope.filter[path] = {
compModelType: modelType,
include: true,
value: [],
};
break;
case 'nestedDataArray':
scope.filter[absolutePath] = {
scope.filter[path] = {
compModelType: modelType,
include: true,
value: Array.isArray(value) ? value.map((v) => ({ ...v, data: {} })) : [],
};
break;
case 'object':
scope.filter[absolutePath] = {
scope.filter[path] = {
compModelType: modelType,
include: true,
value: component.type === 'address' ? false : {},
};
break;
default:
scope.filter[absolutePath] = {
scope.filter[path] = {
compModelType: modelType,
include: true,
};
Expand Down
10 changes: 4 additions & 6 deletions src/process/hideChildren.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,24 @@ import {
ConditionsScope,
ProcessorFn,
} from 'types';
import { registerEphemeralState } from 'utils';
import { getComponentAbsolutePath } from 'utils/formUtil';
import { setComponentScope } from 'utils/formUtil';

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

if (!scope.conditionals) {
scope.conditionals = [];
}

if (isConditionallyHidden || component.hidden || parent?.ephemeralState?.conditionallyHidden) {
registerEphemeralState(component, 'conditionallyHidden', true);
if (isConditionallyHidden || component.hidden || parent?.scope?.conditionallyHidden) {
setComponentScope(component, 'conditionallyHidden', true);
}
};

Expand Down
24 changes: 11 additions & 13 deletions src/process/populate/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
import { get, set } from 'lodash';
import { set } from 'lodash';
import { PopulateContext, PopulateScope, ProcessorFnSync } from 'types';
import { componentPath, getContextualRowPath, getModelType } from 'utils/formUtil';
import { getModelType } from 'utils/formUtil';

// This processor ensures that a "linked" row context is provided to every component.
export const populateProcessSync: ProcessorFnSync<PopulateScope> = (context: PopulateContext) => {
const { component, path, scope } = context;
const { component, path, scope, value } = context;
const { data } = scope;
const compDataPath = componentPath(component, getContextualRowPath(component, path));
const compData: any = get(data, compDataPath);
if (!scope.populated) scope.populated = [];
switch (getModelType(component)) {
case 'nestedArray':
if (!compData || !compData.length) {
set(data, compDataPath, [{}]);
scope.row = get(data, compDataPath)[0];
if (!value || !value.length) {
const newValue = [{}];
set(data, path, newValue);
scope.row = newValue[0];
scope.populated.push({
path,
row: get(data, compDataPath)[0],
});
}
break;
case 'dataObject':
case 'object':
if (!compData || typeof compData !== 'object') {
set(data, compDataPath, {});
scope.row = get(data, compDataPath);
if (!value || typeof value !== 'object') {
const newValue = {};
set(data, value, newValue);
scope.row = newValue;
scope.populated.push({
path,
row: get(data, compDataPath),
});
}
break;
Expand Down
Loading
Loading