Skip to content

Commit 48ac775

Browse files
authored
Option for preserving unnecessary groups in jsonlogic export (#1077)
* Option for preserving unnecessary groups in jsonlogic export see issue #1074 * Tests added for exportPreserveGroups setting Config description also added. I also changed validation logic so that if removeEmptyGroupsOnLoad/removeEmptyGroups is false then no errors are added during validation. Logic being that if exporting empty groups can be proper then importing them should be seen as correct as well. We could also do it so that exportPreserveGroups itself being true would prevent errors during validation but it seemed more logical for removeEmptyGroupsOnLoad to toggle that. * Reverted changes to demo Demo is changed to original including config that now uses the default(false) setting for exportPreserveGroups
1 parent 29fcbe2 commit 48ac775

File tree

9 files changed

+63
-7
lines changed

9 files changed

+63
-7
lines changed

CONFIG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ Behaviour settings:
342342
NOTE: To preserve read-only state of rules in JsonLogic, please use `jsonLogic.add_operation("locked", v => v);` in your code
343343
|canDeleteLocked |false |Show "Delete" button for locked rule?
344344
|removeIncompleteRulesOnLoad |false |Remove incomplete rules (without field, operator, value, or if not all required args are present for functin) during initial validation of `value` prop passed to `<Query>`
345+
|exportPreserveGroups |false |Preserve unnecessary groups (ie. groups with only one rule or empty groups) during JsonLogic export
345346
|removeEmptyRulesOnLoad |true |Remove empty rules during initial validation of `value` prop passed to `<Query>`
346347
|removeEmptyGroupsOnLoad |true |Remove empty groups during initial validation of `value` prop passed to `<Query>`
347348
|removeInvalidMultiSelectValuesOnLoad |true |Remove values that are not in `listValues` during initial validation of `value` prop passed to `<Query>`? +

packages/core/modules/config/default.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const settings = {
2424
canDeleteLocked: false,
2525
canLeaveEmptyGroup: true,
2626
shouldCreateEmptyGroup: false,
27+
exportPreserveGroups: false,
2728
removeEmptyGroupsOnLoad: true,
2829
removeEmptyRulesOnLoad: true,
2930
removeIncompleteRulesOnLoad: false,

packages/core/modules/export/jsonLogic.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,19 @@ const formatGroup = (item, config, meta, _not = false, isRoot = false, parentFie
143143
.map((currentChild) => formatItem(currentChild, config, meta, revChildren, false, groupField))
144144
.filter((currentChild) => typeof currentChild !== "undefined");
145145

146+
// allows for unnecessary (ie. empty or only one rule) groups to be exported
147+
const shouldPreserveGroups = !!config.settings.exportPreserveGroups;
146148
if (isRuleGroupArray && !isGroup0) {
147149
// "count" rule can have no "having" children, but should have number value
148150
if (formattedValue == undefined)
149151
return undefined;
150152
} else {
151-
if (!list.size)
153+
if (!list.size && !shouldPreserveGroups)
152154
return undefined;
153155
}
154156

155157
let resultQuery = {};
156-
if (list.size == 1 && !isRoot)
158+
if (list.size == 1 && !isRoot && !shouldPreserveGroups)
157159
resultQuery = list.first();
158160
else
159161
resultQuery[conj] = list.toList().toJS();

packages/core/modules/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,7 @@ export interface BehaviourSettings {
13691369
maxNumberOfCases?: Number;
13701370
showErrorMessage?: boolean;
13711371
convertableWidgets?: TypedMap<Array<string>>;
1372+
exportPreserveGroups?: boolean;
13721373
removeEmptyGroupsOnLoad?: boolean;
13731374
removeEmptyRulesOnLoad?: boolean;
13741375
removeIncompleteRulesOnLoad?: boolean;

packages/core/modules/utils/validation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ function validateGroup (item, path, itemId, meta, c) {
401401
const cardinality = operator ? config.operators[operator]?.cardinality ?? 1 : undefined;
402402
// tip: for group operators some/none/all children ARE required, for group operator count children are NOT required
403403
// tip: default case should contain only value
404-
const childrenAreRequired = isCase ? !isDefaultCase : (isGroupExt ? cardinality == 0 : true);
404+
const childrenAreRequired = isCase ? !isDefaultCase : (isGroupExt ? cardinality == 0 : removeEmptyGroups);
405405
const canHaveValue = isGroupExt || isCase;
406406

407407
if (!id && itemId) {

packages/tests/specs/QueryWithGroupsAndStructs.test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,3 +1024,30 @@ describe("query with dot but without !struct", () => {
10241024
});
10251025

10261026
//////////////////////////////////////////////////////////////////////////////////////////
1027+
1028+
describe("query with empty and single rule groups", () => {
1029+
1030+
describe("should preserve unnecessary groups during export when preserveGroups is true", () => {
1031+
export_checks(configs.with_export_preserve_groups, inits.with_empty_and_single_rule_groups, "JsonLogic", {
1032+
"logic": inits.with_empty_and_single_rule_groups,
1033+
}, [], {
1034+
// Adding custom sanitization options here
1035+
sanitizeOptions: {
1036+
removeEmptyGroups: false
1037+
}
1038+
});
1039+
});
1040+
1041+
describe("should not preserve unnecessary groups during export when preserveGroups is false/default", () => {
1042+
export_checks(configs.with_allow_empty_groups_on_load, inits.with_empty_and_single_rule_groups, "JsonLogic", {
1043+
"logic":{ "or": [ {"==": [ { "var": "num" }, 1 ]} ]}
1044+
}, ["Group #2 (index path: 2) >> Empty group"], {
1045+
// Adding custom sanitization options here
1046+
sanitizeOptions: {
1047+
removeEmptyGroups: false
1048+
}
1049+
});
1050+
});
1051+
});
1052+
1053+
//////////////////////////////////////////////////////////////////////////////////////////

packages/tests/specs/Validation.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -974,8 +974,7 @@ describe("sanitizeTree", () => {
974974
"Number BETWEEN ? AND ? >> [rhs] Incomplete RHS",
975975
"? >> [lhs] Incomplete LHS",
976976
"Number > ? >> [rhs] Incomplete RHS",
977-
"Number < 100 >> [rhs 0] Value 100 should be from 0 to 10",
978-
"Group #3 (index path: 6) >> Empty group"
977+
"Number < 100 >> [rhs 0] Value 100 should be from 0 to 10"
979978
],
980979
sanitizeOptions: {
981980
// don't fix tree in `load_tree`
@@ -1966,8 +1965,7 @@ describe("checkTree (deprecated)", () => {
19661965
"Number BETWEEN ? AND ? >> [rhs] Incomplete RHS",
19671966
"? >> [lhs] Incomplete LHS",
19681967
"Number > ? >> [rhs] Incomplete RHS",
1969-
"Number < 100 >> [rhs 0] Value 100 should be from 0 to 10",
1970-
"Group #3 (index path: 6) >> Empty group"
1968+
"Number < 100 >> [rhs 0] Value 100 should be from 0 to 10"
19711969
],
19721970
sanitizeOptions: {
19731971
// don't fix tree in `load_tree`

packages/tests/support/configs.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,22 @@ export const with_dont_leave_empty_group = (BasicConfig) => ({
843843
}
844844
});
845845

846+
export const with_allow_empty_groups_on_load = (BasicConfig) => ({
847+
...simple_with_number(BasicConfig),
848+
settings: {
849+
...BasicConfig.settings,
850+
removeEmptyGroupsOnLoad: false
851+
}
852+
});
853+
854+
export const with_export_preserve_groups = (BasicConfig) => ({
855+
...with_allow_empty_groups_on_load(BasicConfig),
856+
settings: {
857+
...BasicConfig.settings,
858+
exportPreserveGroups: true
859+
}
860+
});
861+
846862
export const with_funcs_validation = (BasicConfig) => ({
847863
...BasicConfig,
848864
funcs: {

packages/tests/support/inits.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,16 @@ export const with_groups = {
866866
]
867867
};
868868

869+
export const with_empty_and_single_rule_groups = {
870+
"or": [
871+
{ "and": [
872+
{
873+
"==": [ { "var": "num" }, 1 ]
874+
}
875+
]}, { "and": []}
876+
]
877+
};
878+
869879
export const with_nested = {
870880
"and": [
871881
{ "==": [ { "var": "user.info.firstName" }, "abc" ] },

0 commit comments

Comments
 (0)