Skip to content
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
471 changes: 321 additions & 150 deletions src/process/__tests__/process.test.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/process/calculation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ export const calculateProcessSync: ProcessorFnSync<CalculationScope> = (
value: newValue,
});
set(data, path, newValue);
if (!scope.filter) scope.filter = {};
if (!(scope as any).clearHidden?.hasOwnProperty(path)) {
scope.filter[path] = true;
}
}
return;
};
Expand Down
41 changes: 29 additions & 12 deletions src/process/clearHidden/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { unset } from 'lodash';
import {
ProcessorScope,
ProcessorContext,
ProcessorInfo,
ProcessorFnSync,
ConditionsScope,
ProcessorFn,
FilterScope,
} from 'types';
import { getModelType, setComponentScope } from 'utils/formUtil';

type ClearHiddenScope = ProcessorScope & {
export type ClearHiddenScope = FilterScope & {
clearHidden: {
[path: string]: boolean;
};
Expand All @@ -18,21 +19,32 @@ type ClearHiddenScope = ProcessorScope & {
* This processor function checks components for the `hidden` property and unsets corresponding data
*/
export const clearHiddenProcessSync: ProcessorFnSync<ClearHiddenScope> = (context) => {
const { component, data, value, scope, path } = context;
const { component, data, value, scope, path, parent } = context;

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

if (isConditionallyHidden) {
setComponentScope(component, 'conditionallyHidden', true);
}

if (!scope.clearHidden) {
scope.clearHidden = {};
if (
parent?.scope?.intentionallyHidden ||
(component.hasOwnProperty('hidden') && !!component.hidden)
) {
setComponentScope(component, 'intentionallyHidden', true);
}

// 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 path === cond.path && cond.conditionallyHidden;
});
const compModel = getModelType(component);

// No need to unset the value if it's undefined or is a non-data component.
if (value === undefined || !component.type || compModel === 'none' || compModel === 'content') {
return;
}

const shouldClearValueWhenHidden =
!component.hasOwnProperty('clearOnHide') || component.clearOnHide;
Expand All @@ -42,7 +54,12 @@ export const clearHiddenProcessSync: ProcessorFnSync<ClearHiddenScope> = (contex
(isConditionallyHidden || component.scope?.conditionallyHidden)
) {
unset(data, path);
if (!scope.clearHidden) scope.clearHidden = {};
scope.clearHidden[path] = true;

// Make sure the filter does not include the value back.
if (!scope.filter) scope.filter = {};
scope.filter[path] = false;
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/process/conditions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,5 @@ export const conditionProcessInfo: ProcessorInfo<ConditionsContext, void> = {
name: 'conditions',
process: conditionProcess,
processSync: conditionProcessSync,
shouldProcess: hasSimpleConditions,
shouldProcess: hasConditions,
};
43 changes: 25 additions & 18 deletions src/process/defaultValue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from 'types';
import { set, has } from 'lodash';
import { evaluate } from 'utils';
import { getComponentKey } from 'utils/formUtil';
import { getComponentKey, getModelType } from 'utils/formUtil';

export const hasCustomDefaultValue = (context: DefaultValueContext): boolean => {
const { component } = context;
Expand Down Expand Up @@ -35,10 +35,29 @@ export const customDefaultValueProcess: ProcessorFn<ConditionsScope> = async (
return customDefaultValueProcessSync(context);
};

function setDefaultValue(context: DefaultValueContext, defaultValue: any) {
const { component, data, scope, path } = context;
if (defaultValue === null || defaultValue === undefined) {
return;
}
if (!scope.defaultValues) scope.defaultValues = [];
scope.defaultValues.push({
path,
value: defaultValue,
});
set(data, path, defaultValue);

// If this component is not already included in the filter and is not a number, then include it from the default.
if (!scope.filter) scope.filter = {};
if (!(scope as any).clearHidden?.hasOwnProperty(path) && getModelType(component) !== 'number') {
scope.filter[path] = true;
}
}

export const customDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
context: DefaultValueContext,
) => {
const { component, row, data, scope, path } = context;
const { component, row, scope } = context;
if (!hasCustomDefaultValue(context)) {
return;
}
Expand All @@ -58,14 +77,8 @@ export const customDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
if (component.multiple && !Array.isArray(defaultValue)) {
defaultValue = defaultValue ? [defaultValue] : [];
}
scope.defaultValues.push({
path,
value: defaultValue,
});
}
if (defaultValue !== null && defaultValue !== undefined) {
set(data, path, defaultValue);
}
setDefaultValue(context, defaultValue);
};

export const serverDefaultValueProcess: ProcessorFn<ConditionsScope> = async (
Expand All @@ -77,7 +90,7 @@ export const serverDefaultValueProcess: ProcessorFn<ConditionsScope> = async (
export const serverDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
context: DefaultValueContext,
) => {
const { component, row, data, scope, path } = context;
const { component, row, scope } = context;
if (!hasServerDefaultValue(context)) {
return;
}
Expand All @@ -86,19 +99,13 @@ export const serverDefaultValueProcessSync: ProcessorFnSync<ConditionsScope> = (
return;
}
let defaultValue = null;
if (component.defaultValue !== undefined && component.defaultValue !== null) {
if (component.defaultValue) {
defaultValue = component.defaultValue;
if (component.multiple && !Array.isArray(defaultValue)) {
defaultValue = defaultValue ? [defaultValue] : [];
}
scope.defaultValues.push({
path,
value: defaultValue,
});
}
if (defaultValue !== null && defaultValue !== undefined) {
set(data, path, defaultValue);
}
setDefaultValue(context, defaultValue);
};

export const defaultValueProcess: ProcessorFn<ConditionsScope> = async (
Expand Down
7 changes: 4 additions & 3 deletions src/process/fetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
FetchScope,
FetchFn,
DataSourceComponent,
FilterContext,
} from 'types';
import { get, set } from 'lodash';
import { evaluate, interpolate } from 'utils';
Expand Down Expand Up @@ -102,8 +101,10 @@ export const fetchProcess: ProcessorFn<FetchScope> = async (context: FetchContex
);

// Make sure the value does not get filtered for now...
if (!(scope as FilterContext).filter) (scope as FilterContext).filter = {};
(scope as FilterContext).filter[path] = true;
if (!scope.filter) scope.filter = {};
if (!(scope as any).clearHidden?.hasOwnProperty(path)) {
scope.filter[path] = true;
}
scope.fetched[path] = get(row, key);
} catch (err: any) {
console.log(err.message);
Expand Down
71 changes: 36 additions & 35 deletions src/process/filter/__tests__/filter.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { expect } from 'chai';

import { filterProcessSync } from '../';
import { filterProcessSync, filterPostProcess } from '../';
import { generateProcessorContext } from '../../__tests__/fixtures/util';
import { FilterScope, ProcessorContext } from 'types';

const filterProcess = async (context: ProcessorContext<FilterScope>) => {
filterProcessSync(context);
filterPostProcess(context);
};

describe('Filter processor', function () {
it('Should not filter empty array value for dataGrid component', async function () {
const dataGridComp = {
Expand All @@ -24,9 +29,9 @@ describe('Filter processor', function () {
dataGrid: [],
};
const context: any = generateProcessorContext(dataGridComp, data);
filterProcessSync(context);
filterProcess(context);
expect(context.scope.filter).to.deep.equal({
dataGrid: { compModelType: 'nestedArray', include: true, value: [] },
dataGrid: true,
});
});

Expand All @@ -48,9 +53,9 @@ describe('Filter processor', function () {
editGrid: [],
};
const context: any = generateProcessorContext(editGridComp, data);
filterProcessSync(context);
filterProcess(context);
expect(context.scope.filter).to.deep.equal({
editGrid: { compModelType: 'nestedArray', include: true, value: [] },
editGrid: true,
});
});

Expand All @@ -73,9 +78,9 @@ describe('Filter processor', function () {
dataTable: [],
};
const context: any = generateProcessorContext(dataTableComp, data);
filterProcessSync(context);
filterProcess(context);
expect(context.scope.filter).to.deep.equal({
dataTable: { compModelType: 'nestedArray', include: true, value: [] },
dataTable: true,
});
});

Expand Down Expand Up @@ -128,32 +133,28 @@ describe('Filter processor', function () {
],
};
const context: any = generateProcessorContext(tagpadComp, data);
filterProcessSync(context);
expect(context.scope.filter).to.deep.equal({
tagpad: {
compModelType: 'nestedDataArray',
include: true,
value: [
{
coordinate: {
x: 83,
y: 61,
width: 280,
height: 133,
},
data: {},
filterProcess(context);
expect(context.scope.filtered).to.deep.equal({
tagpad: [
{
coordinate: {
x: 83,
y: 61,
width: 280,
height: 133,
},
{
coordinate: {
x: 194,
y: 93,
width: 280,
height: 133,
},
data: {},
data: {},
},
{
coordinate: {
x: 194,
y: 93,
width: 280,
height: 133,
},
],
},
data: {},
},
],
});
});

Expand Down Expand Up @@ -184,11 +185,11 @@ describe('Filter processor', function () {
};

const context: ProcessorContext<FilterScope> = generateProcessorContext(dataMapComp, data);
filterProcessSync(context);
expect(context.scope.filter).to.deep.equal({
filterProcess(context);
expect(context.scope.filtered).to.deep.equal({
dataMap: {
compModelType: 'map',
include: true,
foo: 'bar',
baz: 'biz',
},
});
});
Expand Down
Loading
Loading