@react-awesome-query-builder/core
Advanced tools
Comparing version 6.6.2 to 6.6.3
@@ -175,4 +175,21 @@ "use strict"; | ||
} | ||
// I any of these conditions are true then we cannot remove group | ||
var preserveSingleRuleGroup = isRoot || shouldPreserveGroups || list.size != 1; | ||
// If preserveSingleRuleGroup is already true then there is no point to even check also if its not a negation group | ||
// then this does not matter | ||
if (!preserveSingleRuleGroup && origNot && !revChildren) { | ||
// We check all children even thuogh there should be only one in case the formatting of one of them failed. | ||
// From config we see if exclamation is part of reverse operator definition and if so then we cannot ever remove a negation single | ||
// rule group because then this combination would be identical to that reverse operator. see issue #1084 | ||
preserveSingleRuleGroup = children.some(function (currentChild) { | ||
var _currentChild$get, _config$operators, _config$operators$rev, _config$operators2; | ||
var op = (_currentChild$get = currentChild.get("properties")) === null || _currentChild$get === void 0 ? void 0 : _currentChild$get.get("operator"); | ||
var revOp = (_config$operators = config["operators"]) === null || _config$operators === void 0 || (_config$operators = _config$operators[op]) === null || _config$operators === void 0 ? void 0 : _config$operators.reversedOp; | ||
return (_config$operators$rev = (_config$operators2 = config.operators) === null || _config$operators2 === void 0 || (_config$operators2 = _config$operators2[revOp]) === null || _config$operators2 === void 0 ? void 0 : _config$operators2._jsonLogicIsExclamationOp) !== null && _config$operators$rev !== void 0 ? _config$operators$rev : false; | ||
}); | ||
} | ||
var resultQuery = {}; | ||
if (list.size == 1 && !isRoot && !shouldPreserveGroups) resultQuery = list.first();else resultQuery[conj] = list.toList().toJS(); | ||
if (preserveSingleRuleGroup) resultQuery[conj] = list.toList().toJS();else resultQuery = list.first(); | ||
@@ -529,6 +546,4 @@ // reverse filter | ||
var buildFnToFormatOp = function buildFnToFormatOp(operator, operatorDefinition, formattedField, formattedValue) { | ||
var _operatorDefinition$_; | ||
var formatteOp = operator; | ||
var cardinality = (0, _stuff.getOpCardinality)(operatorDefinition); | ||
var isReverseArgs = (_operatorDefinition$_ = operatorDefinition._jsonLogicIsRevArgs) !== null && _operatorDefinition$_ !== void 0 ? _operatorDefinition$_ : false; | ||
if (typeof operatorDefinition.jsonLogic == "string") formatteOp = operatorDefinition.jsonLogic; | ||
@@ -538,3 +553,3 @@ var rangeOps = ["<", "<=", ">", ">="]; | ||
var fn = function fn(field, op, val, opDef, opOpts) { | ||
if (cardinality == 0 && eqOps.includes(formatteOp)) return (0, _defineProperty2["default"])({}, formatteOp, [formattedField, null]);else if (cardinality == 0) return (0, _defineProperty2["default"])({}, formatteOp, formattedField);else if (cardinality == 1 && isReverseArgs) return (0, _defineProperty2["default"])({}, formatteOp, [formattedValue, formattedField]);else if (cardinality == 1) return (0, _defineProperty2["default"])({}, formatteOp, [formattedField, formattedValue]);else if (cardinality == 2 && rangeOps.includes(formatteOp)) return (0, _defineProperty2["default"])({}, formatteOp, [formattedValue[0], formattedField, formattedValue[1]]);else return (0, _defineProperty2["default"])({}, formatteOp, [formattedField].concat((0, _toConsumableArray2["default"])(formattedValue))); | ||
if (cardinality == 0 && eqOps.includes(formatteOp)) return (0, _defineProperty2["default"])({}, formatteOp, [formattedField, null]);else if (cardinality == 0) return (0, _defineProperty2["default"])({}, formatteOp, formattedField);else if (cardinality == 1) return (0, _defineProperty2["default"])({}, formatteOp, [formattedField, formattedValue]);else if (cardinality == 2 && rangeOps.includes(formatteOp)) return (0, _defineProperty2["default"])({}, formatteOp, [formattedValue[0], formattedField, formattedValue[1]]);else return (0, _defineProperty2["default"])({}, formatteOp, [formattedField].concat((0, _toConsumableArray2["default"])(formattedValue))); | ||
}; | ||
@@ -541,0 +556,0 @@ return fn; |
@@ -18,8 +18,2 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "checkTree", { | ||
enumerable: true, | ||
get: function get() { | ||
return _tree.checkTree; | ||
} | ||
}); | ||
Object.defineProperty(exports, "getTree", { | ||
@@ -49,8 +43,2 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(exports, "isValidTree", { | ||
enumerable: true, | ||
get: function get() { | ||
return _tree.isValidTree; | ||
} | ||
}); | ||
Object.defineProperty(exports, "jsToImmutable", { | ||
@@ -57,0 +45,0 @@ enumerable: true, |
@@ -8,5 +8,6 @@ "use strict"; | ||
exports.loadFromJsonLogic = exports._loadFromJsonLogic = void 0; | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); | ||
var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray")); | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); | ||
@@ -20,7 +21,7 @@ var _uuid = _interopRequireDefault(require("../utils/uuid")); | ||
var _moment = _interopRequireDefault(require("moment")); | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } | ||
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } | ||
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
// http://jsonlogic.com/ | ||
@@ -32,10 +33,9 @@ | ||
}; | ||
var arrayToObject = function arrayToObject(arr) { | ||
return arr.reduce(function (acc, _ref) { | ||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2), | ||
f = _ref2[0], | ||
fc = _ref2[1]; | ||
return _objectSpread(_objectSpread({}, acc), {}, (0, _defineProperty2["default"])({}, f, fc)); | ||
}, {}); | ||
}; | ||
// constants | ||
var jlFieldMarker = "jlField"; | ||
var jlArgsMarker = "jlArgs"; | ||
var jlEqOps = ["==", "!="]; | ||
var jlRangeOps = ["<", "<=", ">", ">="]; | ||
var multiselectOps = ["multiselect_equals", "multiselect_not_equals", "multiselect_contains", "multiselect_not_contains"]; | ||
var createMeta = function createMeta(parentMeta) { | ||
@@ -71,2 +71,3 @@ return { | ||
var operators = {}; | ||
var combinationOperators = {}; | ||
for (var opKey in config.operators) { | ||
@@ -76,3 +77,3 @@ var opConfig = config.operators[opKey]; | ||
// example: "</2", "#in/1" | ||
var opk = (opConfig._jsonLogicIsRevArgs ? "#" : "") + opConfig.jsonLogic + "/" + (0, _stuff.getOpCardinality)(opConfig); | ||
var opk = opConfig.jsonLogic + "/" + (0, _stuff.getOpCardinality)(opConfig); | ||
if (!operators[opk]) operators[opk] = []; | ||
@@ -85,2 +86,8 @@ operators[opk].push(opKey); | ||
operators[_opk].push(opKey); | ||
if (!combinationOperators[opKey]) combinationOperators[opKey] = {}; | ||
combinationOperators[opKey] = { | ||
"template": opConfig.jsonLogic(jlFieldMarker, opKey, jlArgsMarker), | ||
"jsonLogic2": opConfig.jsonLogic2, | ||
"_jsonLogicIsExclamationOp": !!opConfig._jsonLogicIsExclamationOp | ||
}; | ||
} | ||
@@ -125,6 +132,99 @@ } | ||
funcs: funcs, | ||
varKeys: ["var", groupVarKey, altVarKey] | ||
varKeys: ["var", groupVarKey, altVarKey], | ||
combinationOperators: combinationOperators | ||
}; | ||
}; | ||
/** | ||
* This function checks a given jsonlogic object against a set of templates defined in 'conv'. | ||
* It determines if the jsonlogic object matches any of the specified templates. | ||
* | ||
* @param {*} jsonlogic The jsonlogic object to be matched against the templates. | ||
* @param {*} conv The object containing all potential templates and their associated logic for matching. | ||
* It is expected to have a 'combinationOperators' property that houses the templates. | ||
* @param {*} meta An object where any errors or metadata during the processing are stored. It's modified by reference. | ||
* @param {*} operatorsToCheck An optional array of operator keys that limits which operators in 'conv' are checked. | ||
* If null, all operators in 'conv' are considered. | ||
* @returns {Object|null} The response object containing the match result, and any relevant matched fields and | ||
* arguments if a match is found. Returns null if no match is found. | ||
*/ | ||
var matchAgainstTemplates = function matchAgainstTemplates(jsonlogic, conv, meta) { | ||
var operatorsToCheck = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var response; | ||
if (conv !== null && conv !== void 0 && conv.combinationOperators) { | ||
for (var _i = 0, _Object$entries = Object.entries(conv.combinationOperators); _i < _Object$entries.length; _i++) { | ||
var _Object$entries$_i = (0, _slicedToArray2["default"])(_Object$entries[_i], 2), | ||
key = _Object$entries$_i[0], | ||
value = _Object$entries$_i[1]; | ||
if (operatorsToCheck == null || operatorsToCheck.includes(key)) { | ||
var tempResponse = isTemplateMatch(value.template, jsonlogic); | ||
// Found a match | ||
if (tempResponse.match) { | ||
if (!response) response = tempResponse; | ||
// Templates should be spesific enough that only one match can be found. This should not happen | ||
else meta.errors.push("Operator matched against 2 templates: ".concat(response.newOp, " and ").concat(key)); | ||
// New op that is used to represent operator that is combosed of multiple operators | ||
response["newOp"] = value.jsonLogic2; | ||
} | ||
} | ||
} | ||
} | ||
// Returns undefined if no matches found | ||
return response; | ||
}; | ||
/** | ||
* This function recursively compares a jsonlogic object against a template to determine if they match structurally and content-wise. | ||
* It is used to support complex template matching where the template can include special markers indicating variable fields and arguments. | ||
* | ||
* @param {*} template The template object to match against, which can include special markers to denote fields and arguments. | ||
* @param {*} jsonlogic The jsonlogic object to test against the template. | ||
* @param {*} response An object to accumulate results such as whether a match is found, and to collect any fields or arguments identified | ||
* by the template markers. Default is initialized to a match state with empty fields and arguments. | ||
* @returns {Object} The updated response object after checking the current template level. It includes whether the current level | ||
* matches (match: true/false), any identified fields (jlField), and any arguments (jlArgs). | ||
*/ | ||
var isTemplateMatch = function isTemplateMatch(template, jsonlogic) { | ||
var response = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { | ||
"match": true, | ||
"jlField": null, | ||
"jlArgs": [] | ||
}; | ||
if (template == undefined || jsonlogic == undefined) { | ||
response.match = false; | ||
return response; | ||
} | ||
// This lets us compare order easily | ||
var tKeys = Object.keys(template); | ||
var jKeys = Object.keys(jsonlogic); | ||
if (tKeys.length !== jKeys.length) { | ||
// Both have same length | ||
response.match = false; | ||
return response; | ||
} | ||
for (var index = 0; index < tKeys.length; index++) { | ||
var key = tKeys[index]; | ||
var value = template[key]; | ||
if (key !== jKeys[index]) { | ||
// Checks that both have exact same key at exact same place. Kind of pointless for arrays but whatever | ||
response.match = false; | ||
return response; | ||
} else if (value === jlFieldMarker && (0, _stuff.isJsonLogic)(jsonlogic[key])) { | ||
// If jlFieldMarker is found in template AND it's field or func we take the value from corresponding place in jsonlogic | ||
response.jlField = jsonlogic[key]; | ||
} else if (value === jlArgsMarker) { | ||
// If jlArgsMarker is found in template we take the value from corresponding place in jsonlogic | ||
response.jlArgs.push(jsonlogic[key]); | ||
} else if ((0, _typeof2["default"])(value) === "object" && value !== null || Array.isArray(value)) { | ||
// Here we recurse thru objects and arrays of template until we have gone thru it completely | ||
response = isTemplateMatch(value, jsonlogic[key], response); | ||
} else if (value !== jsonlogic[key]) { | ||
// This is for cases of {var: ""}, which should be only case in default config that leads here | ||
response.match = false; | ||
return response; | ||
} | ||
} | ||
return response; | ||
}; | ||
// expectedTypes - "val", "rule", "group", "switch", "case_val" | ||
@@ -147,2 +247,14 @@ var convertFromLogic = function convertFromLogic(logic, conv, config, expectedTypes, meta) { | ||
var isEmptyOp = op == "!" && vals.length == 1 && vals[0] && (0, _stuff.isJsonLogic)(vals[0]) && conv.varKeys.includes(Object.keys(vals[0])[0]); | ||
// If matchAgainstTemplates returns match then op is replaced with special jsonlogic2 value | ||
var match = matchAgainstTemplates(logic, conv, meta); | ||
if (match) { | ||
// We reset vals if match found | ||
vals = []; | ||
vals[0] = match.jlField; | ||
match.jlArgs.forEach(function (arg) { | ||
return vals.push(arg); | ||
}); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
op = match.newOp; | ||
} | ||
var isNot = op == "!" && !isEmptyOp; | ||
@@ -505,6 +617,6 @@ var isLocked = lockedOp && op == lockedOp; | ||
return [fp.join(fieldSeparator), (0, _configUtils.getFieldConfig)(config, fp)]; | ||
}).filter(function (_ref3) { | ||
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), | ||
_f = _ref4[0], | ||
fc = _ref4[1]; | ||
}).filter(function (_ref) { | ||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2), | ||
_f = _ref2[0], | ||
fc = _ref2[1]; | ||
return (fc === null || fc === void 0 ? void 0 : fc.type) == "!group"; | ||
@@ -528,6 +640,6 @@ })); | ||
var groupToId = {}; | ||
Object.entries(children).map(function (_ref5) { | ||
var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2), | ||
k = _ref6[0], | ||
v = _ref6[1]; | ||
Object.entries(children).map(function (_ref3) { | ||
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), | ||
k = _ref4[0], | ||
v = _ref4[1]; | ||
if ((v === null || v === void 0 ? void 0 : v.type) == "group" || (v === null || v === void 0 ? void 0 : v.type) == "rule_group") { | ||
@@ -560,9 +672,9 @@ // put as-is | ||
}; | ||
}).filter(function (_ref7) { | ||
var fc = _ref7.fc; | ||
}).filter(function (_ref5) { | ||
var fc = _ref5.fc; | ||
return fc.type != "!struct"; | ||
}); | ||
traverseGroupFields.map(function (_ref8, i) { | ||
var gf = _ref8.f, | ||
gfc = _ref8.fc; | ||
traverseGroupFields.map(function (_ref6, i) { | ||
var gf = _ref6.f, | ||
gfc = _ref6.fc; | ||
var groupId = groupToId[gf]; | ||
@@ -647,8 +759,4 @@ if (!groupId) { | ||
var submeta = createMeta(meta); | ||
var res = _parseRule(op, arity, vals, parentField, conv, config, false, submeta); | ||
var res = _parseRule(op, arity, vals, parentField, conv, config, submeta); | ||
if (!res) { | ||
// try reverse | ||
res = _parseRule(op, arity, vals, parentField, conv, config, true, createMeta(meta)); | ||
} | ||
if (!res) { | ||
meta.errors.push(submeta.errors.join("; ") || "Unknown op ".concat(op, "/").concat(arity)); | ||
@@ -659,11 +767,13 @@ return undefined; | ||
}; | ||
var _parseRule = function _parseRule(op, arity, vals, parentField, conv, config, isRevArgs, meta) { | ||
var _vals$1$in$, _meta$settings2; | ||
var _parseRule = function _parseRule(op, arity, vals, parentField, conv, config, meta) { | ||
var _meta$settings2; | ||
// config.settings.groupOperators are used for group count (cardinality = 0 is exception) | ||
// but don't confuse with "all-in" or "some-in" for multiselect | ||
var isAllOrSomeInForMultiselect = (op === "all" || op === "some") && (0, _stuff.isJsonLogic)(vals[1]) && Object.keys(vals[1])[0] == "in" && ((_vals$1$in$ = vals[1]["in"][0]) === null || _vals$1$in$ === void 0 ? void 0 : _vals$1$in$["var"]) === ""; | ||
var isGroup0 = !isAllOrSomeInForMultiselect && config.settings.groupOperators.includes(op); | ||
var eqOps = ["==", "!="]; | ||
var isAllOrSomeInForMultiselect = multiselectOps.map(function (opName) { | ||
var _config$operators$opN; | ||
return (_config$operators$opN = config.operators[opName]) === null || _config$operators$opN === void 0 ? void 0 : _config$operators$opN.jsonLogic2; | ||
}).includes(op); | ||
var isGroup0 = config.settings.groupOperators.includes(op) && !isAllOrSomeInForMultiselect; | ||
var cardinality = isGroup0 ? 0 : arity - 1; | ||
if (isGroup0) cardinality = 0;else if (eqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
if (isGroup0) cardinality = 0;else if (jlEqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
arity = 1; | ||
@@ -674,13 +784,9 @@ cardinality = 0; | ||
var opk = op + "/" + cardinality; | ||
var opKeys = conv.operators[(isRevArgs ? "#" : "") + opk]; | ||
var opKeys = conv.operators[opk]; | ||
if (!opKeys) return; | ||
var jlField, | ||
jlArgs = []; | ||
var rangeOps = ["<", "<=", ">", ">="]; | ||
if (rangeOps.includes(op) && arity == 3) { | ||
if (jlRangeOps.includes(op) && arity == 3) { | ||
jlField = vals[1]; | ||
jlArgs = [vals[0], vals[2]]; | ||
} else if (isRevArgs) { | ||
jlField = vals[1]; | ||
jlArgs = [vals[0]]; | ||
} else { | ||
@@ -734,13 +840,7 @@ var _vals2 = vals; | ||
if (!op) return undefined; | ||
var jlConjs = Object.values(config.conjunctions).map(function (_ref7) { | ||
var jsonLogicConj = _ref7.jsonLogicConj; | ||
return jsonLogicConj; | ||
}); | ||
var arity = vals.length; | ||
if ((op === "all" || op === "some") && (0, _stuff.isJsonLogic)(vals[1])) { | ||
var _vals$1$op2$; | ||
// special case for "all-in" and "some-in" | ||
var op2 = Object.keys(vals[1])[0]; | ||
var isEmptyVar = ((_vals$1$op2$ = vals[1][op2][0]) === null || _vals$1$op2$ === void 0 ? void 0 : _vals$1$op2$["var"]) === ""; | ||
if (op2 === "in" && isEmptyVar) { | ||
vals = [vals[0], vals[1][op2][1]]; | ||
op = op + "-" + op2; // "all-in" and "some-in" | ||
} | ||
} | ||
var parseRes = parseRule(op, arity, vals, parentField, conv, config, meta); | ||
@@ -775,2 +875,3 @@ if (!parseRes) return undefined; | ||
var havingNot = false; | ||
var canRevHaving = !!config.settings.reverseOperatorsForNot; | ||
if ((fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.type) == "!group" && having) { | ||
@@ -783,3 +884,6 @@ conj = Object.keys(having)[0]; | ||
// Eg. use `not_equal` instead of `not` `equal` | ||
while (conj == "!") { | ||
// We look for template matches here to make sure we dont reverse when "!" is | ||
// part of operator | ||
var match = matchAgainstTemplates(having, conv, meta); | ||
while (conj == "!" && !match) { | ||
var isEmptyOp = conj == "!" && havingVals.length == 1 && havingVals[0] && (0, _stuff.isJsonLogic)(havingVals[0]) && conv.varKeys.includes(Object.keys(havingVals[0])[0]); | ||
@@ -793,2 +897,11 @@ if (isEmptyOp) { | ||
havingVals = having[conj]; | ||
// Negation group with single rule is to be treated the same as ! | ||
if (canRevHaving && jlConjs.includes(conj) && havingVals.length == 1) { | ||
having = having[conj][0]; | ||
conj = Object.keys(having)[0]; | ||
havingVals = having[conj]; | ||
} | ||
// Another template matching | ||
var matchTemp = matchAgainstTemplates(having, conv, meta); | ||
match = matchTemp ? matchTemp : match; | ||
} | ||
@@ -798,2 +911,13 @@ if (!Array.isArray(havingVals)) { | ||
} | ||
// If template match found we act accordingly | ||
if (match) { | ||
// We reset vals if match found | ||
havingVals = []; | ||
havingVals[0] = match.jlField; | ||
match.jlArgs.forEach(function (arg) { | ||
return havingVals.push(arg); | ||
}); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
conj = match.newOp; | ||
} | ||
} | ||
@@ -931,12 +1055,12 @@ | ||
var flat = flatizeTernary(vals); | ||
var cases = flat.map(function (_ref9) { | ||
var _ref10 = (0, _slicedToArray2["default"])(_ref9, 2), | ||
cond = _ref10[0], | ||
val = _ref10[1]; | ||
var cases = flat.map(function (_ref8) { | ||
var _ref9 = (0, _slicedToArray2["default"])(_ref8, 2), | ||
cond = _ref9[0], | ||
val = _ref9[1]; | ||
return [cond ? convertFromLogic(cond, conv, config, ["rule", "group"], meta, false, null, null, parentField) : null, buildCaseValProperties(config, meta, conv, val)]; | ||
}); | ||
var children1 = cases.map(function (_ref11) { | ||
var _ref12 = (0, _slicedToArray2["default"])(_ref11, 2), | ||
cond = _ref12[0], | ||
val = _ref12[1]; | ||
var children1 = cases.map(function (_ref10) { | ||
var _ref11 = (0, _slicedToArray2["default"])(_ref10, 2), | ||
cond = _ref11[0], | ||
val = _ref11[1]; | ||
return wrapInCase(cond, val, config, meta); | ||
@@ -943,0 +1067,0 @@ }); |
@@ -8,8 +8,2 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "checkTree", { | ||
enumerable: true, | ||
get: function get() { | ||
return _validation.checkTree; | ||
} | ||
}); | ||
exports.isImmutableTree = exports.getTree = void 0; | ||
@@ -23,8 +17,2 @@ Object.defineProperty(exports, "isJsonLogic", { | ||
exports.isTree = void 0; | ||
Object.defineProperty(exports, "isValidTree", { | ||
enumerable: true, | ||
get: function get() { | ||
return _validation.isValidTree; | ||
} | ||
}); | ||
exports.jsToImmutable = jsToImmutable; | ||
@@ -34,3 +22,2 @@ exports.loadTree = void 0; | ||
var _immutable = _interopRequireWildcard(require("immutable")); | ||
var _validation = require("../utils/validation"); | ||
var _treeUtils = require("../utils/treeUtils"); | ||
@@ -37,0 +24,0 @@ var _stuff = require("../utils/stuff"); |
@@ -488,2 +488,7 @@ /* eslint-disable no-extra-semi */ | ||
translateValidation(key: Translatable["key"], args?: Translatable["args"]): string; | ||
/** | ||
* @deprecated Use Utils.Validation.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
} | ||
@@ -497,10 +502,2 @@ | ||
loadTree(jsonTree: OldJsonTree): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.Validation.isValidTree() | ||
*/ | ||
isValidTree(tree: ImmutableTree, config: Config): boolean; | ||
isImmutableTree(tree: any): boolean; | ||
@@ -603,6 +600,2 @@ isTree(tree: any): boolean; // is JsonTree ? | ||
getTotalRulesCountInTree(tree: ImmutableTree): number; | ||
/** | ||
* @deprecated | ||
*/ | ||
getTreeBadFields(tree: ImmutableTree, config: Config): Array<FieldPath>; | ||
isEmptyTree(tree: ImmutableTree): boolean; | ||
@@ -629,4 +622,4 @@ // case mode | ||
export interface Utils extends Omit<Import, "isValidTree">, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree">, | ||
export interface Utils extends Import, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree" | "checkTree">, | ||
Pick<ConfigUtils, "compressConfig" | "decompressConfig">, | ||
@@ -1075,3 +1068,4 @@ Pick<OtherUtils, "uuid">, | ||
jsonLogic?: string | JsonLogicFormatOperator | JsonLogicFunction; | ||
_jsonLogicIsRevArgs?: boolean; | ||
jsonLogic2?: string; | ||
_jsonLogicIsExclamationOp?: boolean; | ||
elasticSearchQueryType?: ElasticSearchQueryType | ElasticSearchFormatQueryType | JsonLogicFunction; | ||
@@ -1166,2 +1160,3 @@ valueSources?: Array<ValueSource>; | ||
validateValue?: ValidateValue<V> | SerializedFunction; | ||
valuePlaceholder?: string; | ||
} | ||
@@ -1189,2 +1184,3 @@ export interface TextFieldSettings<V = string> extends BasicFieldSettings<V> { | ||
showSearch?: boolean; | ||
searchPlaceholder?: string; | ||
showCheckboxes?: boolean; | ||
@@ -1191,0 +1187,0 @@ asyncFetch?: AsyncFetchListValuesFn | SerializedFunction; |
@@ -7,10 +7,3 @@ "use strict"; | ||
}); | ||
exports.getTotalRulesCountInTree = exports.getTotalReordableNodesCountInTree = exports.getSwitchValues = exports.getLightTree = exports.getItemByPath = exports.getFlatTree = exports.fixPathsInTree = exports.fixEmptyGroupsInTree = exports.expandTreeSubpath = exports.expandTreePath = exports._fixImmutableValue = void 0; | ||
Object.defineProperty(exports, "getTreeBadFields", { | ||
enumerable: true, | ||
get: function get() { | ||
return _validation.getTreeBadFields; | ||
} | ||
}); | ||
exports.hasChildren = void 0; | ||
exports.hasChildren = exports.getTotalRulesCountInTree = exports.getTotalReordableNodesCountInTree = exports.getSwitchValues = exports.getLightTree = exports.getItemByPath = exports.getFlatTree = exports.fixPathsInTree = exports.fixEmptyGroupsInTree = exports.expandTreeSubpath = exports.expandTreePath = exports._fixImmutableValue = void 0; | ||
Object.defineProperty(exports, "immutableToJs", { | ||
@@ -46,3 +39,2 @@ enumerable: true, | ||
var _stuff = require("./stuff"); | ||
var _validation = require("./validation"); | ||
var _tree = require("../import/tree"); | ||
@@ -49,0 +41,0 @@ var _uuid = _interopRequireDefault(require("./uuid")); |
@@ -169,4 +169,21 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; | ||
} | ||
// I any of these conditions are true then we cannot remove group | ||
var preserveSingleRuleGroup = isRoot || shouldPreserveGroups || list.size != 1; | ||
// If preserveSingleRuleGroup is already true then there is no point to even check also if its not a negation group | ||
// then this does not matter | ||
if (!preserveSingleRuleGroup && origNot && !revChildren) { | ||
// We check all children even thuogh there should be only one in case the formatting of one of them failed. | ||
// From config we see if exclamation is part of reverse operator definition and if so then we cannot ever remove a negation single | ||
// rule group because then this combination would be identical to that reverse operator. see issue #1084 | ||
preserveSingleRuleGroup = children.some(function (currentChild) { | ||
var _currentChild$get, _config$operators, _config$operators$rev, _config$operators2; | ||
var op = (_currentChild$get = currentChild.get("properties")) === null || _currentChild$get === void 0 ? void 0 : _currentChild$get.get("operator"); | ||
var revOp = (_config$operators = config["operators"]) === null || _config$operators === void 0 || (_config$operators = _config$operators[op]) === null || _config$operators === void 0 ? void 0 : _config$operators.reversedOp; | ||
return (_config$operators$rev = (_config$operators2 = config.operators) === null || _config$operators2 === void 0 || (_config$operators2 = _config$operators2[revOp]) === null || _config$operators2 === void 0 ? void 0 : _config$operators2._jsonLogicIsExclamationOp) !== null && _config$operators$rev !== void 0 ? _config$operators$rev : false; | ||
}); | ||
} | ||
var resultQuery = {}; | ||
if (list.size == 1 && !isRoot && !shouldPreserveGroups) resultQuery = list.first();else resultQuery[conj] = list.toList().toJS(); | ||
if (preserveSingleRuleGroup) resultQuery[conj] = list.toList().toJS();else resultQuery = list.first(); | ||
@@ -523,6 +540,4 @@ // reverse filter | ||
var buildFnToFormatOp = function buildFnToFormatOp(operator, operatorDefinition, formattedField, formattedValue) { | ||
var _operatorDefinition$_; | ||
var formatteOp = operator; | ||
var cardinality = getOpCardinality(operatorDefinition); | ||
var isReverseArgs = (_operatorDefinition$_ = operatorDefinition._jsonLogicIsRevArgs) !== null && _operatorDefinition$_ !== void 0 ? _operatorDefinition$_ : false; | ||
if (typeof operatorDefinition.jsonLogic == "string") formatteOp = operatorDefinition.jsonLogic; | ||
@@ -532,3 +547,3 @@ var rangeOps = ["<", "<=", ">", ">="]; | ||
var fn = function fn(field, op, val, opDef, opOpts) { | ||
if (cardinality == 0 && eqOps.includes(formatteOp)) return _defineProperty({}, formatteOp, [formattedField, null]);else if (cardinality == 0) return _defineProperty({}, formatteOp, formattedField);else if (cardinality == 1 && isReverseArgs) return _defineProperty({}, formatteOp, [formattedValue, formattedField]);else if (cardinality == 1) return _defineProperty({}, formatteOp, [formattedField, formattedValue]);else if (cardinality == 2 && rangeOps.includes(formatteOp)) return _defineProperty({}, formatteOp, [formattedValue[0], formattedField, formattedValue[1]]);else return _defineProperty({}, formatteOp, [formattedField].concat(_toConsumableArray(formattedValue))); | ||
if (cardinality == 0 && eqOps.includes(formatteOp)) return _defineProperty({}, formatteOp, [formattedField, null]);else if (cardinality == 0) return _defineProperty({}, formatteOp, formattedField);else if (cardinality == 1) return _defineProperty({}, formatteOp, [formattedField, formattedValue]);else if (cardinality == 2 && rangeOps.includes(formatteOp)) return _defineProperty({}, formatteOp, [formattedValue[0], formattedField, formattedValue[1]]);else return _defineProperty({}, formatteOp, [formattedField].concat(_toConsumableArray(formattedValue))); | ||
}; | ||
@@ -535,0 +550,0 @@ return fn; |
export { getTree, loadTree, | ||
// for backward compatibility: | ||
checkTree, isValidTree, | ||
// candidates for moving to utils | ||
@@ -5,0 +3,0 @@ isImmutableTree, isTree, isJsonLogic, jsToImmutable } from "./tree"; |
@@ -0,10 +1,11 @@ | ||
import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; | ||
import _toArray from "@babel/runtime/helpers/toArray"; | ||
import _defineProperty from "@babel/runtime/helpers/defineProperty"; | ||
import _typeof from "@babel/runtime/helpers/typeof"; | ||
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } | ||
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } | ||
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } | ||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } | ||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } | ||
import uuid from "../utils/uuid"; | ||
@@ -24,10 +25,9 @@ import { getOpCardinality, isJsonLogic, shallowEqual, logger } from "../utils/stuff"; | ||
}; | ||
var arrayToObject = function arrayToObject(arr) { | ||
return arr.reduce(function (acc, _ref) { | ||
var _ref2 = _slicedToArray(_ref, 2), | ||
f = _ref2[0], | ||
fc = _ref2[1]; | ||
return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, f, fc)); | ||
}, {}); | ||
}; | ||
// constants | ||
var jlFieldMarker = "jlField"; | ||
var jlArgsMarker = "jlArgs"; | ||
var jlEqOps = ["==", "!="]; | ||
var jlRangeOps = ["<", "<=", ">", ">="]; | ||
var multiselectOps = ["multiselect_equals", "multiselect_not_equals", "multiselect_contains", "multiselect_not_contains"]; | ||
var createMeta = function createMeta(parentMeta) { | ||
@@ -63,2 +63,3 @@ return { | ||
var operators = {}; | ||
var combinationOperators = {}; | ||
for (var opKey in config.operators) { | ||
@@ -68,3 +69,3 @@ var opConfig = config.operators[opKey]; | ||
// example: "</2", "#in/1" | ||
var opk = (opConfig._jsonLogicIsRevArgs ? "#" : "") + opConfig.jsonLogic + "/" + getOpCardinality(opConfig); | ||
var opk = opConfig.jsonLogic + "/" + getOpCardinality(opConfig); | ||
if (!operators[opk]) operators[opk] = []; | ||
@@ -77,2 +78,8 @@ operators[opk].push(opKey); | ||
operators[_opk].push(opKey); | ||
if (!combinationOperators[opKey]) combinationOperators[opKey] = {}; | ||
combinationOperators[opKey] = { | ||
"template": opConfig.jsonLogic(jlFieldMarker, opKey, jlArgsMarker), | ||
"jsonLogic2": opConfig.jsonLogic2, | ||
"_jsonLogicIsExclamationOp": !!opConfig._jsonLogicIsExclamationOp | ||
}; | ||
} | ||
@@ -117,6 +124,99 @@ } | ||
funcs: funcs, | ||
varKeys: ["var", groupVarKey, altVarKey] | ||
varKeys: ["var", groupVarKey, altVarKey], | ||
combinationOperators: combinationOperators | ||
}; | ||
}; | ||
/** | ||
* This function checks a given jsonlogic object against a set of templates defined in 'conv'. | ||
* It determines if the jsonlogic object matches any of the specified templates. | ||
* | ||
* @param {*} jsonlogic The jsonlogic object to be matched against the templates. | ||
* @param {*} conv The object containing all potential templates and their associated logic for matching. | ||
* It is expected to have a 'combinationOperators' property that houses the templates. | ||
* @param {*} meta An object where any errors or metadata during the processing are stored. It's modified by reference. | ||
* @param {*} operatorsToCheck An optional array of operator keys that limits which operators in 'conv' are checked. | ||
* If null, all operators in 'conv' are considered. | ||
* @returns {Object|null} The response object containing the match result, and any relevant matched fields and | ||
* arguments if a match is found. Returns null if no match is found. | ||
*/ | ||
var matchAgainstTemplates = function matchAgainstTemplates(jsonlogic, conv, meta) { | ||
var operatorsToCheck = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | ||
var response; | ||
if (conv !== null && conv !== void 0 && conv.combinationOperators) { | ||
for (var _i = 0, _Object$entries = Object.entries(conv.combinationOperators); _i < _Object$entries.length; _i++) { | ||
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), | ||
key = _Object$entries$_i[0], | ||
value = _Object$entries$_i[1]; | ||
if (operatorsToCheck == null || operatorsToCheck.includes(key)) { | ||
var tempResponse = isTemplateMatch(value.template, jsonlogic); | ||
// Found a match | ||
if (tempResponse.match) { | ||
if (!response) response = tempResponse; | ||
// Templates should be spesific enough that only one match can be found. This should not happen | ||
else meta.errors.push("Operator matched against 2 templates: ".concat(response.newOp, " and ").concat(key)); | ||
// New op that is used to represent operator that is combosed of multiple operators | ||
response["newOp"] = value.jsonLogic2; | ||
} | ||
} | ||
} | ||
} | ||
// Returns undefined if no matches found | ||
return response; | ||
}; | ||
/** | ||
* This function recursively compares a jsonlogic object against a template to determine if they match structurally and content-wise. | ||
* It is used to support complex template matching where the template can include special markers indicating variable fields and arguments. | ||
* | ||
* @param {*} template The template object to match against, which can include special markers to denote fields and arguments. | ||
* @param {*} jsonlogic The jsonlogic object to test against the template. | ||
* @param {*} response An object to accumulate results such as whether a match is found, and to collect any fields or arguments identified | ||
* by the template markers. Default is initialized to a match state with empty fields and arguments. | ||
* @returns {Object} The updated response object after checking the current template level. It includes whether the current level | ||
* matches (match: true/false), any identified fields (jlField), and any arguments (jlArgs). | ||
*/ | ||
var isTemplateMatch = function isTemplateMatch(template, jsonlogic) { | ||
var response = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { | ||
"match": true, | ||
"jlField": null, | ||
"jlArgs": [] | ||
}; | ||
if (template == undefined || jsonlogic == undefined) { | ||
response.match = false; | ||
return response; | ||
} | ||
// This lets us compare order easily | ||
var tKeys = Object.keys(template); | ||
var jKeys = Object.keys(jsonlogic); | ||
if (tKeys.length !== jKeys.length) { | ||
// Both have same length | ||
response.match = false; | ||
return response; | ||
} | ||
for (var index = 0; index < tKeys.length; index++) { | ||
var key = tKeys[index]; | ||
var value = template[key]; | ||
if (key !== jKeys[index]) { | ||
// Checks that both have exact same key at exact same place. Kind of pointless for arrays but whatever | ||
response.match = false; | ||
return response; | ||
} else if (value === jlFieldMarker && isJsonLogic(jsonlogic[key])) { | ||
// If jlFieldMarker is found in template AND it's field or func we take the value from corresponding place in jsonlogic | ||
response.jlField = jsonlogic[key]; | ||
} else if (value === jlArgsMarker) { | ||
// If jlArgsMarker is found in template we take the value from corresponding place in jsonlogic | ||
response.jlArgs.push(jsonlogic[key]); | ||
} else if (_typeof(value) === "object" && value !== null || Array.isArray(value)) { | ||
// Here we recurse thru objects and arrays of template until we have gone thru it completely | ||
response = isTemplateMatch(value, jsonlogic[key], response); | ||
} else if (value !== jsonlogic[key]) { | ||
// This is for cases of {var: ""}, which should be only case in default config that leads here | ||
response.match = false; | ||
return response; | ||
} | ||
} | ||
return response; | ||
}; | ||
// expectedTypes - "val", "rule", "group", "switch", "case_val" | ||
@@ -139,2 +239,14 @@ var convertFromLogic = function convertFromLogic(logic, conv, config, expectedTypes, meta) { | ||
var isEmptyOp = op == "!" && vals.length == 1 && vals[0] && isJsonLogic(vals[0]) && conv.varKeys.includes(Object.keys(vals[0])[0]); | ||
// If matchAgainstTemplates returns match then op is replaced with special jsonlogic2 value | ||
var match = matchAgainstTemplates(logic, conv, meta); | ||
if (match) { | ||
// We reset vals if match found | ||
vals = []; | ||
vals[0] = match.jlField; | ||
match.jlArgs.forEach(function (arg) { | ||
return vals.push(arg); | ||
}); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
op = match.newOp; | ||
} | ||
var isNot = op == "!" && !isEmptyOp; | ||
@@ -497,6 +609,6 @@ var isLocked = lockedOp && op == lockedOp; | ||
return [fp.join(fieldSeparator), getFieldConfig(config, fp)]; | ||
}).filter(function (_ref3) { | ||
var _ref4 = _slicedToArray(_ref3, 2), | ||
_f = _ref4[0], | ||
fc = _ref4[1]; | ||
}).filter(function (_ref) { | ||
var _ref2 = _slicedToArray(_ref, 2), | ||
_f = _ref2[0], | ||
fc = _ref2[1]; | ||
return (fc === null || fc === void 0 ? void 0 : fc.type) == "!group"; | ||
@@ -520,6 +632,6 @@ })); | ||
var groupToId = {}; | ||
Object.entries(children).map(function (_ref5) { | ||
var _ref6 = _slicedToArray(_ref5, 2), | ||
k = _ref6[0], | ||
v = _ref6[1]; | ||
Object.entries(children).map(function (_ref3) { | ||
var _ref4 = _slicedToArray(_ref3, 2), | ||
k = _ref4[0], | ||
v = _ref4[1]; | ||
if ((v === null || v === void 0 ? void 0 : v.type) == "group" || (v === null || v === void 0 ? void 0 : v.type) == "rule_group") { | ||
@@ -552,9 +664,9 @@ // put as-is | ||
}; | ||
}).filter(function (_ref7) { | ||
var fc = _ref7.fc; | ||
}).filter(function (_ref5) { | ||
var fc = _ref5.fc; | ||
return fc.type != "!struct"; | ||
}); | ||
traverseGroupFields.map(function (_ref8, i) { | ||
var gf = _ref8.f, | ||
gfc = _ref8.fc; | ||
traverseGroupFields.map(function (_ref6, i) { | ||
var gf = _ref6.f, | ||
gfc = _ref6.fc; | ||
var groupId = groupToId[gf]; | ||
@@ -639,8 +751,4 @@ if (!groupId) { | ||
var submeta = createMeta(meta); | ||
var res = _parseRule(op, arity, vals, parentField, conv, config, false, submeta); | ||
var res = _parseRule(op, arity, vals, parentField, conv, config, submeta); | ||
if (!res) { | ||
// try reverse | ||
res = _parseRule(op, arity, vals, parentField, conv, config, true, createMeta(meta)); | ||
} | ||
if (!res) { | ||
meta.errors.push(submeta.errors.join("; ") || "Unknown op ".concat(op, "/").concat(arity)); | ||
@@ -651,11 +759,13 @@ return undefined; | ||
}; | ||
var _parseRule = function _parseRule(op, arity, vals, parentField, conv, config, isRevArgs, meta) { | ||
var _vals$1$in$, _meta$settings2; | ||
var _parseRule = function _parseRule(op, arity, vals, parentField, conv, config, meta) { | ||
var _meta$settings2; | ||
// config.settings.groupOperators are used for group count (cardinality = 0 is exception) | ||
// but don't confuse with "all-in" or "some-in" for multiselect | ||
var isAllOrSomeInForMultiselect = (op === "all" || op === "some") && isJsonLogic(vals[1]) && Object.keys(vals[1])[0] == "in" && ((_vals$1$in$ = vals[1]["in"][0]) === null || _vals$1$in$ === void 0 ? void 0 : _vals$1$in$["var"]) === ""; | ||
var isGroup0 = !isAllOrSomeInForMultiselect && config.settings.groupOperators.includes(op); | ||
var eqOps = ["==", "!="]; | ||
var isAllOrSomeInForMultiselect = multiselectOps.map(function (opName) { | ||
var _config$operators$opN; | ||
return (_config$operators$opN = config.operators[opName]) === null || _config$operators$opN === void 0 ? void 0 : _config$operators$opN.jsonLogic2; | ||
}).includes(op); | ||
var isGroup0 = config.settings.groupOperators.includes(op) && !isAllOrSomeInForMultiselect; | ||
var cardinality = isGroup0 ? 0 : arity - 1; | ||
if (isGroup0) cardinality = 0;else if (eqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
if (isGroup0) cardinality = 0;else if (jlEqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
arity = 1; | ||
@@ -666,13 +776,9 @@ cardinality = 0; | ||
var opk = op + "/" + cardinality; | ||
var opKeys = conv.operators[(isRevArgs ? "#" : "") + opk]; | ||
var opKeys = conv.operators[opk]; | ||
if (!opKeys) return; | ||
var jlField, | ||
jlArgs = []; | ||
var rangeOps = ["<", "<=", ">", ">="]; | ||
if (rangeOps.includes(op) && arity == 3) { | ||
if (jlRangeOps.includes(op) && arity == 3) { | ||
jlField = vals[1]; | ||
jlArgs = [vals[0], vals[2]]; | ||
} else if (isRevArgs) { | ||
jlField = vals[1]; | ||
jlArgs = [vals[0]]; | ||
} else { | ||
@@ -726,13 +832,7 @@ var _vals2 = vals; | ||
if (!op) return undefined; | ||
var jlConjs = Object.values(config.conjunctions).map(function (_ref7) { | ||
var jsonLogicConj = _ref7.jsonLogicConj; | ||
return jsonLogicConj; | ||
}); | ||
var arity = vals.length; | ||
if ((op === "all" || op === "some") && isJsonLogic(vals[1])) { | ||
var _vals$1$op2$; | ||
// special case for "all-in" and "some-in" | ||
var op2 = Object.keys(vals[1])[0]; | ||
var isEmptyVar = ((_vals$1$op2$ = vals[1][op2][0]) === null || _vals$1$op2$ === void 0 ? void 0 : _vals$1$op2$["var"]) === ""; | ||
if (op2 === "in" && isEmptyVar) { | ||
vals = [vals[0], vals[1][op2][1]]; | ||
op = op + "-" + op2; // "all-in" and "some-in" | ||
} | ||
} | ||
var parseRes = parseRule(op, arity, vals, parentField, conv, config, meta); | ||
@@ -767,2 +867,3 @@ if (!parseRes) return undefined; | ||
var havingNot = false; | ||
var canRevHaving = !!config.settings.reverseOperatorsForNot; | ||
if ((fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.type) == "!group" && having) { | ||
@@ -775,3 +876,6 @@ conj = Object.keys(having)[0]; | ||
// Eg. use `not_equal` instead of `not` `equal` | ||
while (conj == "!") { | ||
// We look for template matches here to make sure we dont reverse when "!" is | ||
// part of operator | ||
var match = matchAgainstTemplates(having, conv, meta); | ||
while (conj == "!" && !match) { | ||
var isEmptyOp = conj == "!" && havingVals.length == 1 && havingVals[0] && isJsonLogic(havingVals[0]) && conv.varKeys.includes(Object.keys(havingVals[0])[0]); | ||
@@ -785,2 +889,11 @@ if (isEmptyOp) { | ||
havingVals = having[conj]; | ||
// Negation group with single rule is to be treated the same as ! | ||
if (canRevHaving && jlConjs.includes(conj) && havingVals.length == 1) { | ||
having = having[conj][0]; | ||
conj = Object.keys(having)[0]; | ||
havingVals = having[conj]; | ||
} | ||
// Another template matching | ||
var matchTemp = matchAgainstTemplates(having, conv, meta); | ||
match = matchTemp ? matchTemp : match; | ||
} | ||
@@ -790,2 +903,13 @@ if (!Array.isArray(havingVals)) { | ||
} | ||
// If template match found we act accordingly | ||
if (match) { | ||
// We reset vals if match found | ||
havingVals = []; | ||
havingVals[0] = match.jlField; | ||
match.jlArgs.forEach(function (arg) { | ||
return havingVals.push(arg); | ||
}); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
conj = match.newOp; | ||
} | ||
} | ||
@@ -923,12 +1047,12 @@ | ||
var flat = flatizeTernary(vals); | ||
var cases = flat.map(function (_ref9) { | ||
var _ref10 = _slicedToArray(_ref9, 2), | ||
cond = _ref10[0], | ||
val = _ref10[1]; | ||
var cases = flat.map(function (_ref8) { | ||
var _ref9 = _slicedToArray(_ref8, 2), | ||
cond = _ref9[0], | ||
val = _ref9[1]; | ||
return [cond ? convertFromLogic(cond, conv, config, ["rule", "group"], meta, false, null, null, parentField) : null, buildCaseValProperties(config, meta, conv, val)]; | ||
}); | ||
var children1 = cases.map(function (_ref11) { | ||
var _ref12 = _slicedToArray(_ref11, 2), | ||
cond = _ref12[0], | ||
val = _ref12[1]; | ||
var children1 = cases.map(function (_ref10) { | ||
var _ref11 = _slicedToArray(_ref10, 2), | ||
cond = _ref11[0], | ||
val = _ref11[1]; | ||
return wrapInCase(cond, val, config, meta); | ||
@@ -935,0 +1059,0 @@ }); |
import _typeof from "@babel/runtime/helpers/typeof"; | ||
import Immutable, { fromJS, Map } from "immutable"; | ||
import { checkTree, isValidTree } from "../utils/validation"; | ||
import { getLightTree, _fixImmutableValue, fixPathsInTree } from "../utils/treeUtils"; | ||
import { isJsonLogic } from "../utils/stuff"; | ||
import uuid from "../utils/uuid"; | ||
export { isJsonLogic, | ||
// for backward compatibility: | ||
checkTree, isValidTree }; | ||
export { isJsonLogic }; | ||
export var getTree = function getTree(immutableTree) { | ||
@@ -11,0 +8,0 @@ var light = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; |
@@ -488,2 +488,7 @@ /* eslint-disable no-extra-semi */ | ||
translateValidation(key: Translatable["key"], args?: Translatable["args"]): string; | ||
/** | ||
* @deprecated Use Utils.Validation.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
} | ||
@@ -497,10 +502,2 @@ | ||
loadTree(jsonTree: OldJsonTree): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.Validation.isValidTree() | ||
*/ | ||
isValidTree(tree: ImmutableTree, config: Config): boolean; | ||
isImmutableTree(tree: any): boolean; | ||
@@ -603,6 +600,2 @@ isTree(tree: any): boolean; // is JsonTree ? | ||
getTotalRulesCountInTree(tree: ImmutableTree): number; | ||
/** | ||
* @deprecated | ||
*/ | ||
getTreeBadFields(tree: ImmutableTree, config: Config): Array<FieldPath>; | ||
isEmptyTree(tree: ImmutableTree): boolean; | ||
@@ -629,4 +622,4 @@ // case mode | ||
export interface Utils extends Omit<Import, "isValidTree">, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree">, | ||
export interface Utils extends Import, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree" | "checkTree">, | ||
Pick<ConfigUtils, "compressConfig" | "decompressConfig">, | ||
@@ -1075,3 +1068,4 @@ Pick<OtherUtils, "uuid">, | ||
jsonLogic?: string | JsonLogicFormatOperator | JsonLogicFunction; | ||
_jsonLogicIsRevArgs?: boolean; | ||
jsonLogic2?: string; | ||
_jsonLogicIsExclamationOp?: boolean; | ||
elasticSearchQueryType?: ElasticSearchQueryType | ElasticSearchFormatQueryType | JsonLogicFunction; | ||
@@ -1166,2 +1160,3 @@ valueSources?: Array<ValueSource>; | ||
validateValue?: ValidateValue<V> | SerializedFunction; | ||
valuePlaceholder?: string; | ||
} | ||
@@ -1189,2 +1184,3 @@ export interface TextFieldSettings<V = string> extends BasicFieldSettings<V> { | ||
showSearch?: boolean; | ||
searchPlaceholder?: string; | ||
showCheckboxes?: boolean; | ||
@@ -1191,0 +1187,0 @@ asyncFetch?: AsyncFetchListValuesFn | SerializedFunction; |
@@ -5,8 +5,5 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; | ||
import { toImmutableList, isImmutable, applyToJS as immutableToJs } from "./stuff"; | ||
import { getTreeBadFields } from "./validation"; | ||
import { jsToImmutable } from "../import/tree"; | ||
import uuid from "./uuid"; | ||
export { toImmutableList, jsToImmutable, immutableToJs, isImmutable, | ||
// for backward compatibility | ||
getTreeBadFields }; | ||
export { toImmutableList, jsToImmutable, immutableToJs, isImmutable }; | ||
@@ -13,0 +10,0 @@ /** |
@@ -168,5 +168,4 @@ import {settings as defaultSettings} from "./default"; | ||
mongoFormatOp: function(...args) { return this.utils.mongoFormatOp1("$regex", v => (typeof v == "string" ? this.utils.escapeRegExp(v) : undefined), false, ...args); }, | ||
//jsonLogic: (field, op, val) => ({ "in": [val, field] }), | ||
jsonLogic: "in", | ||
_jsonLogicIsRevArgs: true, | ||
jsonLogic: (field, op, val) => ({ "in": [val, field] }), | ||
jsonLogic2: "#in", | ||
valueSources: ["value"], | ||
@@ -182,2 +181,5 @@ elasticSearchQueryType: "regexp", | ||
mongoFormatOp: function(...args) { return this.utils.mongoFormatOp1("$regex", v => (typeof v == "string" ? this.utils.escapeRegExp(v) : undefined), true, ...args); }, | ||
jsonLogic: (field, op, val) => ({"!": { "in": [val, field] }}), | ||
jsonLogic2: "#!in", | ||
_jsonLogicIsExclamationOp: true, | ||
valueSources: ["value"], | ||
@@ -271,2 +273,5 @@ }, | ||
reversedOp: "between", | ||
jsonLogic: (field, op, val) => ({"!": { "<=": [Array.isArray(val) ? val[0] : val, field, Array.isArray(val) ? val[1] : val] }}), | ||
jsonLogic2: "!<=", | ||
_jsonLogicIsExclamationOp: true, | ||
validateValues: (values) => { | ||
@@ -421,2 +426,5 @@ if (values[0] != undefined && values[1] != undefined) { | ||
reversedOp: "select_any_in", | ||
jsonLogic: (field, op, val) => ({"!": { "in": [field, val] }}), | ||
jsonLogic2: "!in", | ||
_jsonLogicIsExclamationOp: true, | ||
}, | ||
@@ -453,3 +461,8 @@ // it's not "contains all", but "contains any" operator | ||
}, | ||
reversedOp: "multiselect_contains" | ||
reversedOp: "multiselect_contains", | ||
jsonLogic2: "!some-in", | ||
jsonLogic: (field, op, vals) => ({ | ||
"!": { "some": [ field, {"in": [{"var": ""}, vals]} ]} | ||
}), | ||
_jsonLogicIsExclamationOp: true, | ||
}, | ||
@@ -504,2 +517,8 @@ multiselect_equals: { | ||
reversedOp: "multiselect_equals", | ||
jsonLogic2: "!all-in", | ||
jsonLogic: (field, op, vals) => ({ | ||
// it's not "equals", but "includes" operator - just for example | ||
"!": { "all": [ field, {"in": [{"var": ""}, vals]} ]} | ||
}), | ||
_jsonLogicIsExclamationOp: true, | ||
}, | ||
@@ -506,0 +525,0 @@ proximity: { |
@@ -157,8 +157,24 @@ import {getOpCardinality, widgetDefKeysToOmit, opDefKeysToOmit, omit} from "../utils/stuff"; | ||
// I any of these conditions are true then we cannot remove group | ||
let preserveSingleRuleGroup = isRoot || shouldPreserveGroups || list.size != 1; | ||
// If preserveSingleRuleGroup is already true then there is no point to even check also if its not a negation group | ||
// then this does not matter | ||
if (!preserveSingleRuleGroup && origNot && !revChildren) { | ||
// We check all children even thuogh there should be only one in case the formatting of one of them failed. | ||
// From config we see if exclamation is part of reverse operator definition and if so then we cannot ever remove a negation single | ||
// rule group because then this combination would be identical to that reverse operator. see issue #1084 | ||
preserveSingleRuleGroup = children.some((currentChild) => { | ||
const op = currentChild.get("properties")?.get("operator"); | ||
const revOp = config["operators"]?.[op]?.reversedOp; | ||
return config.operators?.[revOp]?._jsonLogicIsExclamationOp ?? false; | ||
}); | ||
} | ||
let resultQuery = {}; | ||
if (list.size == 1 && !isRoot && !shouldPreserveGroups) | ||
if (preserveSingleRuleGroup) | ||
resultQuery[conj] = list.toList().toJS(); | ||
else | ||
resultQuery = list.first(); | ||
else | ||
resultQuery[conj] = list.toList().toJS(); | ||
// reverse filter | ||
@@ -529,3 +545,2 @@ if (filterNot) { | ||
const cardinality = getOpCardinality(operatorDefinition); | ||
const isReverseArgs = operatorDefinition._jsonLogicIsRevArgs ?? false; | ||
if (typeof operatorDefinition.jsonLogic == "string") | ||
@@ -540,4 +555,2 @@ formatteOp = operatorDefinition.jsonLogic; | ||
return { [formatteOp]: formattedField }; | ||
else if (cardinality == 1 && isReverseArgs) | ||
return { [formatteOp]: [formattedValue, formattedField] }; | ||
else if (cardinality == 1) | ||
@@ -544,0 +557,0 @@ return { [formatteOp]: [formattedField, formattedValue] }; |
export { | ||
getTree, loadTree, | ||
// for backward compatibility: | ||
checkTree, isValidTree, | ||
// candidates for moving to utils | ||
@@ -6,0 +4,0 @@ isImmutableTree, isTree, isJsonLogic, jsToImmutable |
@@ -14,4 +14,13 @@ import uuid from "../utils/uuid"; | ||
const arrayUniq = (arr) => Array.from(new Set(arr)); | ||
const arrayToObject = (arr) => arr.reduce((acc, [f, fc]) => ({ ...acc, [f]: fc }), {}); | ||
// constants | ||
const jlFieldMarker = "jlField"; | ||
const jlArgsMarker = "jlArgs"; | ||
const jlEqOps = ["==", "!="]; | ||
const jlRangeOps = ["<", "<=", ">", ">="]; | ||
const multiselectOps = [ | ||
"multiselect_equals", "multiselect_not_equals", | ||
"multiselect_contains", "multiselect_not_contains" | ||
]; | ||
const createMeta = (parentMeta) => { | ||
@@ -52,2 +61,3 @@ return { | ||
let operators = {}; | ||
let combinationOperators = {}; | ||
for (let opKey in config.operators) { | ||
@@ -57,3 +67,3 @@ const opConfig = config.operators[opKey]; | ||
// example: "</2", "#in/1" | ||
const opk = (opConfig._jsonLogicIsRevArgs ? "#" : "") + opConfig.jsonLogic + "/" + getOpCardinality(opConfig); | ||
const opk = opConfig.jsonLogic + "/" + getOpCardinality(opConfig); | ||
if (!operators[opk]) | ||
@@ -68,2 +78,10 @@ operators[opk] = []; | ||
operators[opk].push(opKey); | ||
if (!combinationOperators[opKey]) | ||
combinationOperators[opKey] = {}; | ||
combinationOperators[opKey] = { | ||
"template": opConfig.jsonLogic(jlFieldMarker, opKey, jlArgsMarker), | ||
"jsonLogic2": opConfig.jsonLogic2, | ||
"_jsonLogicIsExclamationOp": !!opConfig._jsonLogicIsExclamationOp | ||
}; | ||
} | ||
@@ -101,5 +119,89 @@ } | ||
varKeys: ["var", groupVarKey, altVarKey], | ||
combinationOperators, | ||
}; | ||
}; | ||
/** | ||
* This function checks a given jsonlogic object against a set of templates defined in 'conv'. | ||
* It determines if the jsonlogic object matches any of the specified templates. | ||
* | ||
* @param {*} jsonlogic The jsonlogic object to be matched against the templates. | ||
* @param {*} conv The object containing all potential templates and their associated logic for matching. | ||
* It is expected to have a 'combinationOperators' property that houses the templates. | ||
* @param {*} meta An object where any errors or metadata during the processing are stored. It's modified by reference. | ||
* @param {*} operatorsToCheck An optional array of operator keys that limits which operators in 'conv' are checked. | ||
* If null, all operators in 'conv' are considered. | ||
* @returns {Object|null} The response object containing the match result, and any relevant matched fields and | ||
* arguments if a match is found. Returns null if no match is found. | ||
*/ | ||
const matchAgainstTemplates = (jsonlogic, conv, meta, operatorsToCheck = null) => { | ||
let response; | ||
if (conv?.combinationOperators) { | ||
for (const [key, value] of Object.entries(conv.combinationOperators)) { | ||
if ((operatorsToCheck == null || operatorsToCheck.includes(key))) { | ||
const tempResponse = isTemplateMatch(value.template, jsonlogic); | ||
// Found a match | ||
if (tempResponse.match) { | ||
if (!response) response = tempResponse; | ||
// Templates should be spesific enough that only one match can be found. This should not happen | ||
else meta.errors.push(`Operator matched against 2 templates: ${response.newOp} and ${key}`); | ||
// New op that is used to represent operator that is combosed of multiple operators | ||
response["newOp"] = value.jsonLogic2; | ||
} | ||
} | ||
} | ||
} | ||
// Returns undefined if no matches found | ||
return response; | ||
}; | ||
/** | ||
* This function recursively compares a jsonlogic object against a template to determine if they match structurally and content-wise. | ||
* It is used to support complex template matching where the template can include special markers indicating variable fields and arguments. | ||
* | ||
* @param {*} template The template object to match against, which can include special markers to denote fields and arguments. | ||
* @param {*} jsonlogic The jsonlogic object to test against the template. | ||
* @param {*} response An object to accumulate results such as whether a match is found, and to collect any fields or arguments identified | ||
* by the template markers. Default is initialized to a match state with empty fields and arguments. | ||
* @returns {Object} The updated response object after checking the current template level. It includes whether the current level | ||
* matches (match: true/false), any identified fields (jlField), and any arguments (jlArgs). | ||
*/ | ||
const isTemplateMatch = (template, jsonlogic, response = {"match": true, "jlField": null, "jlArgs": []}) => { | ||
if (template == undefined || jsonlogic == undefined) { | ||
response.match = false; | ||
return response; | ||
} | ||
// This lets us compare order easily | ||
const tKeys = Object.keys(template); | ||
const jKeys = Object.keys(jsonlogic); | ||
if (tKeys.length !== jKeys.length) { | ||
// Both have same length | ||
response.match = false; | ||
return response; | ||
} | ||
for (let index = 0; index < tKeys.length; index++) { | ||
const key = tKeys[index]; | ||
const value = template[key]; | ||
if (key !== jKeys[index]) { | ||
// Checks that both have exact same key at exact same place. Kind of pointless for arrays but whatever | ||
response.match = false; | ||
return response; | ||
} else if (value === jlFieldMarker && isJsonLogic(jsonlogic[key])) { | ||
// If jlFieldMarker is found in template AND it's field or func we take the value from corresponding place in jsonlogic | ||
response.jlField = jsonlogic[key]; | ||
} else if (value === jlArgsMarker) { | ||
// If jlArgsMarker is found in template we take the value from corresponding place in jsonlogic | ||
response.jlArgs.push(jsonlogic[key]); | ||
} else if (typeof value === "object" && value !== null || Array.isArray(value)) { | ||
// Here we recurse thru objects and arrays of template until we have gone thru it completely | ||
response = isTemplateMatch(value, jsonlogic[key], response); | ||
} else if (value !== jsonlogic[key]) { | ||
// This is for cases of {var: ""}, which should be only case in default config that leads here | ||
response.match = false; | ||
return response; | ||
} | ||
} | ||
return response; | ||
}; | ||
// expectedTypes - "val", "rule", "group", "switch", "case_val" | ||
@@ -120,2 +222,12 @@ const convertFromLogic = (logic, conv, config, expectedTypes, meta, not = false, fieldConfig, widget, parentField = null, _isLockedLogic = false) => { | ||
const isEmptyOp = op == "!" && (vals.length == 1 && vals[0] && isJsonLogic(vals[0]) && conv.varKeys.includes(Object.keys(vals[0])[0])); | ||
// If matchAgainstTemplates returns match then op is replaced with special jsonlogic2 value | ||
const match = matchAgainstTemplates(logic, conv, meta); | ||
if (match) { | ||
// We reset vals if match found | ||
vals = []; | ||
vals[0] = match.jlField; | ||
match.jlArgs.forEach(arg => vals.push(arg)); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
op = match.newOp; | ||
} | ||
const isNot = op == "!" && !isEmptyOp; | ||
@@ -594,8 +706,4 @@ const isLocked = lockedOp && op == lockedOp; | ||
const submeta = createMeta(meta); | ||
let res = _parseRule(op, arity, vals, parentField, conv, config, false, submeta); | ||
let res = _parseRule(op, arity, vals, parentField, conv, config, submeta); | ||
if (!res) { | ||
// try reverse | ||
res = _parseRule(op, arity, vals, parentField, conv, config, true, createMeta(meta)); | ||
} | ||
if (!res) { | ||
meta.errors.push(submeta.errors.join("; ") || `Unknown op ${op}/${arity}`); | ||
@@ -608,16 +716,13 @@ return undefined; | ||
const _parseRule = (op, arity, vals, parentField, conv, config, isRevArgs, meta) => { | ||
const _parseRule = (op, arity, vals, parentField, conv, config, meta) => { | ||
// config.settings.groupOperators are used for group count (cardinality = 0 is exception) | ||
// but don't confuse with "all-in" or "some-in" for multiselect | ||
const isAllOrSomeInForMultiselect | ||
= (op === "all" || op === "some") | ||
&& isJsonLogic(vals[1]) | ||
&& Object.keys(vals[1])[0] == "in" | ||
&& vals[1]["in"][0]?.["var"] === ""; | ||
const isGroup0 = !isAllOrSomeInForMultiselect && config.settings.groupOperators.includes(op); | ||
const eqOps = ["==", "!="]; | ||
const isAllOrSomeInForMultiselect = multiselectOps | ||
.map((opName) => config.operators[opName]?.jsonLogic2) | ||
.includes(op); | ||
const isGroup0 = config.settings.groupOperators.includes(op) && !isAllOrSomeInForMultiselect; | ||
let cardinality = isGroup0 ? 0 : arity - 1; | ||
if (isGroup0) | ||
cardinality = 0; | ||
else if (eqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
else if (jlEqOps.includes(op) && cardinality == 1 && vals[1] === null) { | ||
arity = 1; | ||
@@ -629,3 +734,3 @@ cardinality = 0; | ||
const opk = op + "/" + cardinality; | ||
let opKeys = conv.operators[(isRevArgs ? "#" : "") + opk]; | ||
let opKeys = conv.operators[opk]; | ||
if (!opKeys) | ||
@@ -635,9 +740,5 @@ return; | ||
let jlField, jlArgs = []; | ||
const rangeOps = ["<", "<=", ">", ">="]; | ||
if (rangeOps.includes(op) && arity == 3) { | ||
if (jlRangeOps.includes(op) && arity == 3) { | ||
jlField = vals[1]; | ||
jlArgs = [ vals[0], vals[2] ]; | ||
} else if (isRevArgs) { | ||
jlField = vals[1]; | ||
jlArgs = [ vals[0] ]; | ||
} else { | ||
@@ -682,16 +783,5 @@ [jlField, ...jlArgs] = vals; | ||
if (!op) return undefined; | ||
const jlConjs = Object.values(config.conjunctions).map(({jsonLogicConj}) => jsonLogicConj); | ||
const arity = vals.length; | ||
if ((op === "all" || op === "some") && isJsonLogic(vals[1])) { | ||
// special case for "all-in" and "some-in" | ||
const op2 = Object.keys(vals[1])[0]; | ||
const isEmptyVar = vals[1][op2][0]?.["var"] === ""; | ||
if (op2 === "in" && isEmptyVar) { | ||
vals = [ | ||
vals[0], | ||
vals[1][op2][1] | ||
]; | ||
op = op + "-" + op2; // "all-in" and "some-in" | ||
} | ||
} | ||
@@ -723,6 +813,7 @@ const parseRes = parseRule(op, arity, vals, parentField, conv, config, meta); | ||
const needRev = not && canRev || opNeedsReverse; | ||
let conj; | ||
let havingVals; | ||
let havingNot = false; | ||
const canRevHaving = !!config.settings.reverseOperatorsForNot; | ||
if (fieldConfig?.type == "!group" && having) { | ||
@@ -736,3 +827,6 @@ conj = Object.keys(having)[0]; | ||
// Eg. use `not_equal` instead of `not` `equal` | ||
while (conj == "!") { | ||
// We look for template matches here to make sure we dont reverse when "!" is | ||
// part of operator | ||
let match = matchAgainstTemplates(having, conv, meta); | ||
while (conj == "!" && !match) { | ||
const isEmptyOp = conj == "!" && ( | ||
@@ -749,2 +843,11 @@ havingVals.length == 1 && havingVals[0] && isJsonLogic(havingVals[0]) | ||
havingVals = having[conj]; | ||
// Negation group with single rule is to be treated the same as ! | ||
if (canRevHaving && jlConjs.includes(conj) && havingVals.length == 1) { | ||
having = having[conj][0]; | ||
conj = Object.keys(having)[0]; | ||
havingVals = having[conj]; | ||
} | ||
// Another template matching | ||
const matchTemp = matchAgainstTemplates(having, conv, meta); | ||
match = matchTemp ? matchTemp : match; | ||
} | ||
@@ -754,2 +857,11 @@ if (!Array.isArray(havingVals)) { | ||
} | ||
// If template match found we act accordingly | ||
if (match) { | ||
// We reset vals if match found | ||
havingVals = []; | ||
havingVals[0] = match.jlField; | ||
match.jlArgs.forEach(arg => havingVals.push(arg)); | ||
// We reset op to new op that represents multiple jsonlogic operators | ||
conj = match.newOp; | ||
} | ||
} | ||
@@ -756,0 +868,0 @@ |
import Immutable, { fromJS, Map } from "immutable"; | ||
import {checkTree, isValidTree} from "../utils/validation"; | ||
import {getLightTree, _fixImmutableValue, fixPathsInTree} from "../utils/treeUtils"; | ||
@@ -9,4 +8,2 @@ import {isJsonLogic} from "../utils/stuff"; | ||
isJsonLogic, | ||
// for backward compatibility: | ||
checkTree, isValidTree | ||
}; | ||
@@ -13,0 +10,0 @@ |
@@ -488,2 +488,7 @@ /* eslint-disable no-extra-semi */ | ||
translateValidation(key: Translatable["key"], args?: Translatable["args"]): string; | ||
/** | ||
* @deprecated Use Utils.Validation.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
} | ||
@@ -497,10 +502,2 @@ | ||
loadTree(jsonTree: OldJsonTree): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.sanitizeTree() instead | ||
*/ | ||
checkTree(tree: ImmutableTree, config: Config): ImmutableTree; | ||
/** | ||
* @deprecated Use Utils.Validation.isValidTree() | ||
*/ | ||
isValidTree(tree: ImmutableTree, config: Config): boolean; | ||
isImmutableTree(tree: any): boolean; | ||
@@ -603,6 +600,2 @@ isTree(tree: any): boolean; // is JsonTree ? | ||
getTotalRulesCountInTree(tree: ImmutableTree): number; | ||
/** | ||
* @deprecated | ||
*/ | ||
getTreeBadFields(tree: ImmutableTree, config: Config): Array<FieldPath>; | ||
isEmptyTree(tree: ImmutableTree): boolean; | ||
@@ -629,4 +622,4 @@ // case mode | ||
export interface Utils extends Omit<Import, "isValidTree">, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree">, | ||
export interface Utils extends Import, Export, | ||
Pick<Validation, "sanitizeTree" | "validateTree" | "isValidTree" | "checkTree">, | ||
Pick<ConfigUtils, "compressConfig" | "decompressConfig">, | ||
@@ -1075,3 +1068,4 @@ Pick<OtherUtils, "uuid">, | ||
jsonLogic?: string | JsonLogicFormatOperator | JsonLogicFunction; | ||
_jsonLogicIsRevArgs?: boolean; | ||
jsonLogic2?: string; | ||
_jsonLogicIsExclamationOp?: boolean; | ||
elasticSearchQueryType?: ElasticSearchQueryType | ElasticSearchFormatQueryType | JsonLogicFunction; | ||
@@ -1166,2 +1160,3 @@ valueSources?: Array<ValueSource>; | ||
validateValue?: ValidateValue<V> | SerializedFunction; | ||
valuePlaceholder?: string; | ||
} | ||
@@ -1189,2 +1184,3 @@ export interface TextFieldSettings<V = string> extends BasicFieldSettings<V> { | ||
showSearch?: boolean; | ||
searchPlaceholder?: string; | ||
showCheckboxes?: boolean; | ||
@@ -1191,0 +1187,0 @@ asyncFetch?: AsyncFetchListValuesFn | SerializedFunction; |
import Immutable from "immutable"; | ||
import {toImmutableList, isImmutable, applyToJS as immutableToJs} from "./stuff"; | ||
import {getTreeBadFields} from "./validation"; | ||
import {jsToImmutable} from "../import/tree"; | ||
@@ -9,4 +8,2 @@ import uuid from "./uuid"; | ||
toImmutableList, jsToImmutable, immutableToJs, isImmutable, | ||
// for backward compatibility | ||
getTreeBadFields | ||
}; | ||
@@ -13,0 +10,0 @@ |
{ | ||
"name": "@react-awesome-query-builder/core", | ||
"version": "6.6.2", | ||
"version": "6.6.3", | ||
"description": "User-friendly query builder for React. Core", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1928174
46857