Skip to content

Commit

Permalink
feat: possibility to add custom operators for groups (#462)
Browse files Browse the repository at this point in the history
Co-authored-by: naube <[email protected]>
  • Loading branch information
bnau and naube authored Aug 8, 2021
1 parent eda9a14 commit 9ba033c
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 5 deletions.
1 change: 1 addition & 0 deletions CONFIG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ Behaviour settings:
|canCompareFieldWithField | |For `<ValueFieldWidget>` - Function for building right list of fields to compare field with field +
`(string leftField, Object leftFieldConfig, string rightField, Object rightFieldConfig) => boolean` +
For type == `select`/`multiselect` you can optionally check `listValues`
|groupOperators |`['all', 'some', 'none']` |Operators usable in `!group` fields with `array` mode
|===

TIP: For fully read-only mode use these settings:
Expand Down
2 changes: 1 addition & 1 deletion examples/demo/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export default (skin: string) => {
"none",
],
defaultOperator: "some",
initialEmptyWhere: true, // if default operator is not some/all/none, true - to set no children, false - to add 1 empty
initialEmptyWhere: true, // if default operator is not in config.settings.groupOperators, true - to set no children, false - to add 1 empty

subfields: {
vendor: {
Expand Down
1 change: 1 addition & 0 deletions modules/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const settings = {
canShortMongoQuery: true,
groupActionsPosition: "topRight", // oneOf [topLeft, topCenter, topRight, bottomLeft, bottomCenter, bottomRight]
setOpOnChangeField: ["keep", "default"], // 'default' (default if present), 'keep' (keep prev from last field), 'first', 'none'
groupOperators: ["some", "all", "none"],

convertableWidgets: {
"number": ["slider", "rangeslider"],
Expand Down
2 changes: 1 addition & 1 deletion modules/export/jsonLogic.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const formatGroup = (item, config, meta, isRoot, parentField = null) => {
// rule_group (issue #246)
if (isRuleGroup && mode != "struct") {
if (isGroup0) {
// all / some / none
// config.settings.groupOperators
const op = groupOperator || "some";
resultQuery = {
[op]: [
Expand Down
4 changes: 2 additions & 2 deletions modules/import/jsonLogic.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,10 @@ const parseRule = (op, arity, vals, parentField, conv, config, meta) => {
};

const _parseRule = (op, arity, vals, parentField, conv, config, errors, isRevArgs) => {
// some/all/none is used for group count (cardinality = 0 is exception)
// config.settings.groupOperators are used for group count (cardinality = 0 is exception)
// but don't confuse with "all-in" for multiselect
const isAllInForMultiselect = op == "all" && isJsonLogic(vals[1]) && Object.keys(vals[1])[0] == "in";
const isGroup0 = !isAllInForMultiselect && ["some", "all", "none"].includes(op);
const isGroup0 = !isAllInForMultiselect && config.settings.groupOperators.includes(op);
const cardinality = isGroup0 ? 0 : arity - 1;

const opk = op + "/" + cardinality;
Expand Down
15 changes: 15 additions & 0 deletions tests/specs/InteractionsVanilla.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ describe("interactions on vanilla", () => {
});
});

it("change field from group_ext to simple with custom operator", () => {
with_qb(configs.with_group_array_custom_operator, inits.with_group_array_custom_operator, "JsonLogic", (qb, onChange) => {
qb
.find(".rule_group_ext .group--field--count--rule .rule--field select")
.simulate("change", { target: { value: "str" } });
const changedTree = getTree(onChange.getCall(0).args[0]);
const childKeys = Object.keys(changedTree.children1);
expect(childKeys.length).to.equal(1);
const child = changedTree.children1[childKeys[0]];
expect(child.properties.field).to.equal("str");
expect(child.properties.operator).to.equal("equal");
expect(child.properties.value).to.eql([undefined]);
});
});

it("change field from simple to group_ext", () => {
with_qb(configs.with_group_array, inits.with_text, "JsonLogic", (qb, onChange) => {
qb
Expand Down
24 changes: 24 additions & 0 deletions tests/specs/QueryWithGroupsAndStructs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,30 @@ describe("query with !struct and !group", () => {
expect(qb.find(".query-builder")).to.have.length(1);
});
});
it("should handle custom operator in !group arrays", () => {
with_qb_skins(configs.with_group_array_custom_operator, inits.with_group_array_custom_operator, "JsonLogic", (qb, onChange, {expect_jlogic, expect_checks}) => {
expect_checks({
"logic": {
"and": [
{
"custom_group_operator": [
{"var": "cars"},
{
"and": [
{
"==": [{"var": "vendor"}, "Toyota"]
}, {
">=": [{"var": "year"}, 2010]
}
]
}
]
}
]
}
});
});
});
});

describe("export", () => {
Expand Down
55 changes: 54 additions & 1 deletion tests/support/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ export const with_group_array = (BasicConfig) => ({
"none",
],
defaultOperator: "some",
initialEmptyWhere: true, // if default operator is not some/all/none, true - to set no children, false - to add 1 empty
initialEmptyWhere: true, // if default operator is not in config.settings.groupOperators, true - to set no children, false - to add 1 empty

subfields: {
vendor: {
Expand All @@ -667,6 +667,59 @@ export const with_group_array = (BasicConfig) => ({
}
});

export const with_group_array_custom_operator = (BasicConfig) => ({
...BasicConfig,
fields: {
str: {
label: "String",
type: "text",
},
cars: {
label: "Cars",
type: "!group",
mode: "array",
conjunctions: ["AND", "OR"],
showNot: true,
operators: [
"custom_group_operator"
],
defaultOperator: "some",
initialEmptyWhere: true, // if default operator is not in config.settings.groupOperators, true - to set no children, false - to add 1 empty

subfields: {
vendor: {
type: "select",
fieldSettings: {
listValues: ["Ford", "Toyota", "Tesla"],
},
valueSources: ["value"],
},
year: {
type: "number",
fieldSettings: {
min: 1990,
max: 2020,
},
valueSources: ["value"],
}
}
},
},
settings: {
...BasicConfig.settings,
groupOperators: [...BasicConfig.settings.groupOperators, "custom_group_operator"]
},
operators: {
...BasicConfig.operators,
custom_group_operator: {
label: "custom_group_operator",
labelForFormat: "custom_group_operator",
cardinality: 0,
jsonLogic: "custom_group_operator",
},
}
});

// rare
export const with_fieldName = (BasicConfig) => ({
...BasicConfig,
Expand Down
15 changes: 15 additions & 0 deletions tests/support/inits.js
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,21 @@ export const with_group_array = {
]
};

export const with_group_array_custom_operator = {
"and": [
{ "custom_group_operator": [
{ "var": "cars" },
{ "and": [
{
"==": [ { "var": "vendor" }, "Toyota" ]
}, {
">=": [ { "var": "year" }, 2010 ]
}
] }
] }
]
};

// rare
export const with_fieldName = {
"and": [{
Expand Down

0 comments on commit 9ba033c

Please sign in to comment.