UNPKG

@react-awesome-query-builder/core

Version:
1,105 lines (1,067 loc) 51.5 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; 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(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } import Immutable, { fromJS } from "immutable"; import { expandTreePath, expandTreeSubpath, getItemByPath, getAncestorRuleGroups, fixPathsInTree, getTotalRulesCountInTree, fixEmptyGroupsInTree, isEmptyTree, hasChildren, removeIsLockedInTree } from "../utils/treeUtils"; import { defaultRuleProperties, defaultGroupProperties, getDefaultOperator, defaultOperatorOptions, defaultItemProperties } from "../utils/defaultRuleUtils"; import * as constants from "./constants"; import uuid from "../utils/uuid"; import { getFuncConfig, getFieldConfig, getOperatorConfig, selectTypes, getOperatorsForType, getOperatorsForField, getFirstOperator } from "../utils/configUtils"; import { isEmptyItem, calculateValueType } from "../utils/ruleUtils"; import { deepEqual, getOpCardinality, applyToJS } from "../utils/stuff"; import { validateValue, validateRange } from "../utils/validation"; import { getNewValueForFieldOp } from "../utils/getNewValueForFieldOp"; import { translateValidation } from "../i18n"; import omit from "lodash/omit"; import mapValues from "lodash/mapValues"; import { setFunc, setArgValue, setArgValueSrc, setArgValueAsyncListValues } from "../utils/funcUtils"; /** * @param {object} config * @param {Immutable.List} path * @param {Immutable.Map} properties */ var addNewGroup = function addNewGroup(state, path, type, generatedId, properties, config) { var _properties$get; var children = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; var meta = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : {}; var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } var groupUuid = (properties === null || properties === void 0 || (_properties$get = properties.get) === null || _properties$get === void 0 ? void 0 : _properties$get.call(properties, "id")) || generatedId; var shouldCreateEmptyGroup = config.settings.shouldCreateEmptyGroup; var groupPath = path.push(groupUuid); var canAddNewRule = !shouldCreateEmptyGroup; var isDefaultCase = !!(meta !== null && meta !== void 0 && meta.isDefaultCase); var origState = state; state = addItem(state, path, type, groupUuid, defaultGroupProperties(config).merge(fromJS(properties) || {}), config, children); if (state !== origState) { if (!children && !isDefaultCase) { state = state.setIn(expandTreePath(groupPath, "children1"), new Immutable.OrderedMap()); // Add one empty rule into new group if (canAddNewRule) { state = addItem(state, groupPath, "rule", uuid(), defaultRuleProperties(config, meta === null || meta === void 0 ? void 0 : meta.parentRuleGroupField), config); } } state = fixPathsInTree(state); } return state; }; /** * @param {object} config * @param {Immutable.List} path * @param {Immutable.Map} properties */ var removeGroup = function removeGroup(state, path, config) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = removeItem(state, path); var canLeaveEmptyGroup = config.settings.canLeaveEmptyGroup; var parentPath = path.slice(0, -1); var isEmptyParentGroup = !hasChildren(state, parentPath); if (isEmptyParentGroup && !canLeaveEmptyGroup) { // check ancestors for emptiness (and delete 'em if empty) state = fixEmptyGroupsInTree(state); if (isEmptyTree(state) && !canLeaveEmptyGroup) { // if whole query is empty, add one empty(!) rule to root var canUseDefaultFieldAndOp = false; var canGetFirst = false; state = addItem(state, new Immutable.List(), "rule", uuid(), defaultRuleProperties(config, undefined, undefined, canUseDefaultFieldAndOp, canGetFirst), config); } } state = fixPathsInTree(state); return state; }; /** * @param {object} config * @param {Immutable.List} path * @param {Immutable.Map} properties */ var removeGroupChildren = function removeGroupChildren(state, path, config) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = removeChildren(state, path); state = fixPathsInTree(state); return state; }; /** * @param {object} config * @param {Immutable.List} path */ var removeRule = function removeRule(state, path, config) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = removeItem(state, path); var canLeaveEmptyGroup = config.settings.canLeaveEmptyGroup; var parentPath = path.pop(); var parent = state.getIn(expandTreePath(parentPath)); var parentField = parent.getIn(["properties", "field"]); var parentOperator = parent.getIn(["properties", "operator"]); // const parentValue = parent.getIn(["properties", "value", 0]); var parentFieldConfig = parentField ? getFieldConfig(config, parentField) : null; var parentOperatorConfig = parentOperator ? getOperatorConfig(config, parentOperator, parentField) : null; var hasGroupCountRule = parentField && parentOperator && parentOperatorConfig.cardinality != 0; // && parentValue != undefined; var isParentRuleGroup = parent.get("type") == "rule_group"; var isEmptyParentGroup = !hasChildren(state, parentPath); var canLeaveEmpty = isParentRuleGroup ? hasGroupCountRule && parentFieldConfig.initialEmptyWhere : canLeaveEmptyGroup; if (isEmptyParentGroup && !canLeaveEmpty) { if (isParentRuleGroup) { // deleted last rule from rule_group, so delete whole rule_group state = state.deleteIn(expandTreePath(parentPath)); } // check ancestors for emptiness (and delete 'em if empty) state = fixEmptyGroupsInTree(state); if (isEmptyTree(state) && !canLeaveEmptyGroup) { // if whole query is empty, add one empty(!) rule to root var canUseDefaultFieldAndOp = false; var canGetFirst = false; state = addItem(state, new Immutable.List(), "rule", uuid(), defaultRuleProperties(config, undefined, undefined, canUseDefaultFieldAndOp, canGetFirst), config); } } state = fixPathsInTree(state); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {bool} not */ var setNot = function setNot(state, path, not) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = state.setIn(expandTreePath(path, "properties", "not"), not); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {bool} lock */ var setLock = function setLock(state, path, lock) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = removeIsLockedInTree(state.setIn(expandTreePath(path, "properties", "isLocked"), lock)); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {string} conjunction */ var setConjunction = function setConjunction(state, path, conjunction) { var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } state = state.setIn(expandTreePath(path, "properties", "conjunction"), conjunction); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {string} type * @param {string} id * @param {Immutable.OrderedMap} properties * @param {object} config */ var addItem = function addItem(state, path, type, generatedId, properties, config) { var _properties$get2; var children = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; if (type === "switch_group") throw new Error("Can't add switch_group programmatically"); var targetItem = state.getIn(expandTreePath(path)); if (!targetItem) { // incorrect path return state; } var id = (properties === null || properties === void 0 || (_properties$get2 = properties.get) === null || _properties$get2 === void 0 ? void 0 : _properties$get2.call(properties, "id")) || generatedId; var _config$settings = config.settings, maxNumberOfCases = _config$settings.maxNumberOfCases, maxNumberOfRules = _config$settings.maxNumberOfRules, maxNesting = _config$settings.maxNesting; var rootType = state.get("type"); var isTernary = rootType === "switch_group"; var caseGroup = isTernary ? state.getIn(expandTreePath(path.take(2))) : null; var childrenPath = expandTreePath(path, "children1"); var targetChildren = state.getIn(childrenPath); var hasChildren = !!targetChildren && targetChildren.size; var targetChildrenSize = hasChildren ? targetChildren.size : null; var currentNumber, maxNumber; if (type === "case_group") { currentNumber = targetChildrenSize; maxNumber = maxNumberOfCases; } else if (type === "group") { var ruleGroups = getAncestorRuleGroups(state, path); if (ruleGroups.length) { // closest rule-group var _ruleGroups$ = ruleGroups[0], ruleGroupPath = _ruleGroups$.path, ruleGroupField = _ruleGroups$.field; var ruleGroupFieldConfig = getFieldConfig(config, ruleGroupField); currentNumber = path.size - ruleGroupPath.length; maxNumber = ruleGroupFieldConfig === null || ruleGroupFieldConfig === void 0 ? void 0 : ruleGroupFieldConfig.maxNesting; } else { currentNumber = path.size; maxNumber = maxNesting; } } else { // rule or rule_group var _ruleGroups = getAncestorRuleGroups(state, path); if (_ruleGroups.length) { // closest rule-group var _ruleGroups$2 = _ruleGroups[0], _ruleGroupPath = _ruleGroups$2.path, _ruleGroupField = _ruleGroups$2.field; var _ruleGroupFieldConfig = getFieldConfig(config, _ruleGroupField); var ruleGroupItem = getItemByPath(state, _ruleGroupPath); maxNumber = _ruleGroupFieldConfig === null || _ruleGroupFieldConfig === void 0 ? void 0 : _ruleGroupFieldConfig.maxNumberOfRules; currentNumber = getTotalRulesCountInTree(ruleGroupItem); } else { currentNumber = isTernary ? getTotalRulesCountInTree(caseGroup) : getTotalRulesCountInTree(state); maxNumber = maxNumberOfRules; } } var canAdd = maxNumber && currentNumber ? currentNumber < maxNumber : true; var item = { type: type, id: id, properties: properties }; _addChildren(config, item, children); var isLastDefaultCase = type === "case_group" && hasChildren && targetChildren.last().get("children1") == null; if (canAdd) { var newChildren = new Immutable.OrderedMap(_defineProperty({}, id, new Immutable.Map(item))); if (!hasChildren) { state = state.setIn(childrenPath, newChildren); } else if (isLastDefaultCase) { var last = targetChildren.last(); var newChildrenWithLast = new Immutable.OrderedMap(_defineProperty(_defineProperty({}, id, new Immutable.Map(item)), last.get("id"), last)); state = state.deleteIn(expandTreePath(childrenPath, "children1", last.get("id"))); state = state.mergeIn(childrenPath, newChildrenWithLast); } else { state = state.mergeIn(childrenPath, newChildren); } state = fixPathsInTree(state); } return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path */ var removeItem = function removeItem(state, path) { state = state.deleteIn(expandTreePath(path)); state = fixPathsInTree(state); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path */ var removeChildren = function removeChildren(state, path) { state = state.deleteIn(expandTreePath(path, "children1")); state = fixPathsInTree(state); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} fromPath * @param {Immutable.List} toPath * @param {string} placement, see constants PLACEMENT_*: PLACEMENT_AFTER, PLACEMENT_BEFORE, PLACEMENT_APPEND, PLACEMENT_PREPEND * @param {object} config */ var moveItem = function moveItem(state, fromPath, toPath, placement, config) { var from = getItemByPath(state, fromPath); var sourcePath = fromPath.pop(); var source = fromPath.size > 1 ? getItemByPath(state, sourcePath) : null; var sourceChildren = source ? source.get("children1") : null; var to = getItemByPath(state, toPath); var targetPath = placement == constants.PLACEMENT_APPEND || placement == constants.PLACEMENT_PREPEND ? toPath : toPath.pop(); var target = placement == constants.PLACEMENT_APPEND || placement == constants.PLACEMENT_PREPEND ? to : toPath.size > 1 ? getItemByPath(state, targetPath) : null; var targetChildren = target ? target.get("children1") : null; if (!source || !target || !from) { // incorrect path return state; } var isSameParent = source.get("id") == target.get("id"); var isSourceInsideTarget = targetPath.size < sourcePath.size && deepEqual(targetPath.toArray(), sourcePath.toArray().slice(0, targetPath.size)); var isTargetInsideSource = targetPath.size > sourcePath.size && deepEqual(sourcePath.toArray(), targetPath.toArray().slice(0, sourcePath.size)); var sourceSubpathFromTarget = null; var targetSubpathFromSource = null; if (isSourceInsideTarget) { sourceSubpathFromTarget = Immutable.List(sourcePath.toArray().slice(targetPath.size)); } else if (isTargetInsideSource) { targetSubpathFromSource = Immutable.List(targetPath.toArray().slice(sourcePath.size)); } var newTargetChildren = targetChildren, newSourceChildren = sourceChildren; if (!isTargetInsideSource) newSourceChildren = newSourceChildren["delete"](from.get("id")); if (isSameParent) { newTargetChildren = newSourceChildren; } else if (isSourceInsideTarget) { newTargetChildren = newTargetChildren.updateIn(expandTreeSubpath(sourceSubpathFromTarget, "children1"), function (_oldChildren) { return newSourceChildren; }); } if (placement == constants.PLACEMENT_BEFORE || placement == constants.PLACEMENT_AFTER) { newTargetChildren = Immutable.OrderedMap().withMutations(function (r) { var _iterator = _createForOfIteratorHelper(newTargetChildren.entries()), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var _step$value = _slicedToArray(_step.value, 2), itemId = _step$value[0], item = _step$value[1]; if (itemId == (to === null || to === void 0 ? void 0 : to.get("id")) && placement == constants.PLACEMENT_BEFORE) { r.set(from.get("id"), from); } r.set(itemId, item); if (itemId == (to === null || to === void 0 ? void 0 : to.get("id")) && placement == constants.PLACEMENT_AFTER) { r.set(from.get("id"), from); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } }); } else if (placement == constants.PLACEMENT_APPEND) { newTargetChildren = newTargetChildren.merge(Immutable.OrderedMap(_defineProperty({}, from.get("id"), from))); } else if (placement == constants.PLACEMENT_PREPEND) { newTargetChildren = Immutable.OrderedMap(_defineProperty({}, from.get("id"), from)).merge(newTargetChildren); } if (isTargetInsideSource) { newSourceChildren = newSourceChildren.updateIn(expandTreeSubpath(targetSubpathFromSource, "children1"), function (_oldChildren) { return newTargetChildren; }); newSourceChildren = newSourceChildren["delete"](from.get("id")); } if (!isSameParent && !isSourceInsideTarget) state = state.updateIn(expandTreePath(sourcePath, "children1"), function (_oldChildren) { return newSourceChildren; }); if (!isTargetInsideSource) state = state.updateIn(expandTreePath(targetPath, "children1"), function (_oldChildren) { return newTargetChildren; }); state = fixPathsInTree(state); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {integer} delta * @param {string} srcKey */ var setFieldSrc = function setFieldSrc(state, path, srcKey, config) { var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return state; } var keepInputOnChangeFieldSrc = config.settings.keepInputOnChangeFieldSrc; var currentProperties = currentRule.get("properties"); var currentField = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("field"); var currentFielType = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("fieldType"); var currentFieldConfig = getFieldConfig(config, currentField); // const currentType = currentRule.get("type"); // const currentFieldSrc = currentProperties?.get("fieldSrc"); // get fieldType for "memory effect" var fieldType = (currentFieldConfig === null || currentFieldConfig === void 0 ? void 0 : currentFieldConfig.type) || currentFielType; if (!fieldType || fieldType === "!group" || fieldType === "!struct") { fieldType = null; } var canReuseValue = !selectTypes.includes(fieldType); var keepInput = keepInputOnChangeFieldSrc && !isEmptyItem(currentRule, config) && canReuseValue; if (!keepInput) { // clear ALL properties state = state.setIn(expandTreePath(path, "properties"), defaultRuleProperties(config, null, null, false)); } else { // clear non-relevant properties state = state.setIn(expandTreePath(path, "properties", "field"), null); state = state.deleteIn(expandTreePath(path, "properties", "fieldError")); // set fieldType for "memory effect" state = state.setIn(expandTreePath(path, "properties", "fieldType"), fieldType); } // set fieldSrc state = state.setIn(expandTreePath(path, "properties", "fieldSrc"), srcKey); return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {integer} delta * @param {Array} parentFuncs * @param {string | null} argKey * @param {*} argValue if argKey is null, it's new func key * @param {string | "!valueSrc"} valueType * @param {*} asyncListValues */ var setFuncValue = function setFuncValue(config, state, path, delta, parentFuncs, argKey, argValue, valueType, asyncListValues) { var _meta = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : {}; var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return state; } var isLHS = delta === -1; var currentProperties = currentRule.get("properties"); var currentField = currentProperties.get("field"); var currentValue = currentProperties.get("value"); var currentV = isLHS ? currentField : currentValue.getIn([delta]); // go inwards var funcsPath = []; var targetFV = currentV; var _iterator2 = _createForOfIteratorHelper(parentFuncs || []), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _step2$value = _slicedToArray(_step2.value, 2), _funcK = _step2$value[0], _argK = _step2$value[1]; funcsPath.push([_funcK, _argK, targetFV]); if (_funcK !== targetFV.get("func")) { var funcPath = funcsPath.map(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), f = _ref2[0], a = _ref2[1]; return "".concat(f, "(").concat(a, ")"); }).join("/") || "root"; throw new Error("In ".concat(isLHS ? "LHS" : "RHS", " for path ").concat(funcPath, " expected func key ").concat(_funcK, " but got ").concat(targetFV.get("func"))); } targetFV = targetFV.getIn(["args", _argK, "value"]); } // modify } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } if (!argKey) { var newFuncKey = argValue; var canFixArgs = true; // try to fix args to fit new func validations, otherwise - drop invalid args targetFV = setFunc(targetFV, newFuncKey, config, canFixArgs); // allow drop invalid args / reset to default, but don't trigger error if some arg is required // (not same as setting isEndValue = true) _meta.canDropArgs = true; } else { var funcKey = targetFV.get("func"); var funcDefinition = getFuncConfig(config, funcKey); var args = funcDefinition.args; var argDefinition = args[argKey]; if (valueType === "!valueSrc") { targetFV = setArgValueSrc(targetFV, argKey, argValue, argDefinition, config); } else { targetFV = setArgValue(targetFV, argKey, argValue, argDefinition, config); if (asyncListValues) { targetFV = setArgValueAsyncListValues(targetFV, argKey, asyncListValues, argDefinition, config); } } } // go outwards var newV = targetFV; while (funcsPath.length) { var _funcsPath$pop = funcsPath.pop(), _funcsPath$pop2 = _slicedToArray(_funcsPath$pop, 3), funcK = _funcsPath$pop2[0], argK = _funcsPath$pop2[1], parentFV = _funcsPath$pop2[2]; var _funcDefinition = getFuncConfig(config, funcK); var _args = _funcDefinition.args; var _argDefinition = _args[argK]; newV = setArgValue(parentFV, argK, newV, _argDefinition, config); } if (isLHS) { return setField(state, path, newV, config, undefined, _meta); } else { return setValue(state, path, delta, newV, undefined, config, undefined, _meta); } }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {string | Immutable.OrderedMap} newField */ var setField = function setField(state, path, newField, config, asyncListValues) { var _newFieldConfig$opera, _currentField$get, _newField, _newField$get; var _meta = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return { state: state }; } var isEndValue = _meta.isEndValue, canDropArgs = _meta.canDropArgs; if (!newField) { state = removeItem(state, path); return { state: state }; } var _config$settings2 = config.settings, fieldSeparator = _config$settings2.fieldSeparator, setOpOnChangeField = _config$settings2.setOpOnChangeField, showErrorMessage = _config$settings2.showErrorMessage; if (Array.isArray(newField)) newField = newField.join(fieldSeparator); var currentType = currentRule.get("type"); var currentProperties = currentRule.get("properties"); var wasRuleGroup = currentType == "rule_group"; var currentFieldSrc = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("fieldSrc"); // const currentFieldError = currentProperties?.get("fieldError"); var newFieldConfig = getFieldConfig(config, newField); if (!newFieldConfig) { console.warn("No config for LHS ".concat(newField)); return { state: state }; } var fieldType = newFieldConfig.type; if (fieldType === "!group" || fieldType === "!struct") { fieldType = null; } var currentOperator = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("operator"); var currentOperatorOptions = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("operatorOptions"); var currentField = currentProperties === null || currentProperties === void 0 ? void 0 : currentProperties.get("field"); // const currentValue = currentProperties?.get("value"); // const currentValueErrorStr = currentProperties?.get("valueError")?.join?.("|"); // const _currentValueSrc = currentProperties?.get("valueSrc", new Immutable.List()); // const _currentValueType = currentProperties?.get("valueType", new Immutable.List()); var isRuleGroup = newFieldConfig.type == "!group"; var isRuleGroupExt = isRuleGroup && newFieldConfig.mode == "array"; var isChangeToAnotherType = wasRuleGroup != isRuleGroup; // const wasOkWithoutField = !currentField && currentFieldSrc && currentOperator; // If the newly selected field supports the same operator the rule currently // uses, keep it selected. var lastOp = newFieldConfig && ((_newFieldConfig$opera = newFieldConfig.operators) === null || _newFieldConfig$opera === void 0 ? void 0 : _newFieldConfig$opera.indexOf(currentOperator)) !== -1 ? currentOperator : null; var isSameFunc = currentFieldSrc === "func" && (currentField === null || currentField === void 0 || (_currentField$get = currentField.get) === null || _currentField$get === void 0 ? void 0 : _currentField$get.call(currentField, "func")) === ((_newField = newField) === null || _newField === void 0 || (_newField$get = _newField.get) === null || _newField$get === void 0 ? void 0 : _newField$get.call(_newField, "func")); var forceKeepOp = isSameFunc && !!lastOp; var newOperator = null; var availOps = currentFieldSrc === "func" ? getOperatorsForType(config, fieldType) : getOperatorsForField(config, newField); if (availOps && availOps.length == 1) newOperator = availOps[0];else if (forceKeepOp) newOperator = lastOp;else if (availOps && availOps.length > 1) { var _iterator3 = _createForOfIteratorHelper(setOpOnChangeField), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var strategy = _step3.value; if (strategy == "keep" && !isChangeToAnotherType) newOperator = lastOp;else if (strategy == "default") newOperator = getDefaultOperator(config, newField, false);else if (strategy == "first") newOperator = getFirstOperator(config, newField); if (newOperator) //found op for strategy break; } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } if (!isRuleGroup && !newFieldConfig.operators) { console.warn("Type ".concat(newFieldConfig.type, " is not supported")); return { state: state }; } if (wasRuleGroup && !isRuleGroup) { state = state.setIn(expandTreePath(path, "type"), "rule"); state = state.deleteIn(expandTreePath(path, "children1")); state = state.setIn(expandTreePath(path, "properties"), new Immutable.OrderedMap()); } if (!currentProperties) { state = state.setIn(expandTreePath(path, "properties"), new Immutable.OrderedMap()); } var canFix = !showErrorMessage; if (isRuleGroup) { state = state.setIn(expandTreePath(path, "type"), "rule_group"); var _getNewValueForFieldO = getNewValueForFieldOp({ validateValue: validateValue, validateRange: validateRange }, config, config, currentProperties, newField, newOperator, "field", canFix, isEndValue, canDropArgs), canReuseValue = _getNewValueForFieldO.canReuseValue, newValue = _getNewValueForFieldO.newValue, newValueSrc = _getNewValueForFieldO.newValueSrc, newValueType = _getNewValueForFieldO.newValueType, operatorCardinality = _getNewValueForFieldO.operatorCardinality; var groupProperties = defaultGroupProperties(config, newFieldConfig, newField).merge({ field: newField, fieldSrc: "field", mode: newFieldConfig.mode }); if (isRuleGroupExt) { groupProperties = groupProperties.merge({ operator: newOperator, value: newValue, valueSrc: newValueSrc, valueType: newValueType }); } state = state.setIn(expandTreePath(path, "children1"), new Immutable.OrderedMap()); state = state.setIn(expandTreePath(path, "properties"), groupProperties); if (newFieldConfig.initialEmptyWhere && operatorCardinality == 1) {// just `COUNT(grp) > 1` without `HAVING ..` // no children } else { state = addItem(state, path, "rule", uuid(), defaultRuleProperties(config, newField), config); } state = fixPathsInTree(state); } else { state = state.updateIn(expandTreePath(path, "properties"), function (map) { return map.withMutations(function (current) { var _getNewValueForFieldO2 = getNewValueForFieldOp({ validateValue: validateValue, validateRange: validateRange }, config, config, current, newField, newOperator, "field", canFix, isEndValue, canDropArgs), canReuseValue = _getNewValueForFieldO2.canReuseValue, newValue = _getNewValueForFieldO2.newValue, newValueSrc = _getNewValueForFieldO2.newValueSrc, newValueType = _getNewValueForFieldO2.newValueType, newValueError = _getNewValueForFieldO2.newValueError, newFieldError = _getNewValueForFieldO2.newFieldError, fixedField = _getNewValueForFieldO2.fixedField; // const newValueErrorStr = newValueError?.join?.("|"); var newCorrectField = newField; var willFixField = fixedField !== newField; if (willFixField) { newCorrectField = fixedField; } // tip: `newCorrectField` is SAFE to set: even if it can't be fixed, it is reverted to previous good field. // Unlike logic in `setValue()` action where we need to calc `canUpdValue` // const didFieldErrorChanged = showErrorMessage ? currentFieldError != newFieldError : !!currentFieldError != !!newFieldError; // const didValueErrorChanged = showErrorMessage ? currentValueErrorStr != newValueErrorStr : !!currentValueErrorStr != !!newValueErrorStr; // const didErrorChanged = didFieldErrorChanged || didValueErrorChanged; // isInternalValueChange = !didErrorChanged && !willFixField; if (showErrorMessage) { current = current.set("fieldError", newFieldError); current = current.set("valueError", newValueError); } var newOperatorOptions = canReuseValue ? currentOperatorOptions : defaultOperatorOptions(config, newOperator, newCorrectField); current = current.set("field", newCorrectField)["delete"]("fieldType") // remove "memory effect" .set("fieldSrc", currentFieldSrc).set("operator", newOperator).set("operatorOptions", newOperatorOptions).set("value", newValue).set("valueSrc", newValueSrc).set("valueType", newValueType); if (!canReuseValue) { current = current["delete"]("asyncListValues"); } return current; }); }); } return { state: state }; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {string} operator */ var setOperator = function setOperator(state, path, newOperator, config) { var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return state; } var showErrorMessage = config.settings.showErrorMessage; var properties = currentRule.get("properties"); var children = currentRule.get("children1"); var currentField = properties.get("field"); var currentFieldSrc = properties.get("fieldSrc"); var fieldConfig = getFieldConfig(config, currentField); var isRuleGroup = (fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.type) == "!group"; var operatorConfig = getOperatorConfig(config, newOperator, currentField); var operatorCardinality = operatorConfig ? getOpCardinality(operatorConfig) : null; var canFix = true; state = state.updateIn(expandTreePath(path, "properties"), function (map) { return map.withMutations(function (current) { var currentField = current.get("field"); var currentOperatorOptions = current.get("operatorOptions"); var _currentValue = current.get("value", new Immutable.List()); var _currentValueSrc = current.get("valueSrc", new Immutable.List()); var _currentOperator = current.get("operator"); var _getNewValueForFieldO3 = getNewValueForFieldOp({ validateValue: validateValue, validateRange: validateRange }, config, config, current, currentField, newOperator, "operator", canFix), canReuseValue = _getNewValueForFieldO3.canReuseValue, newValue = _getNewValueForFieldO3.newValue, newValueSrc = _getNewValueForFieldO3.newValueSrc, newValueType = _getNewValueForFieldO3.newValueType, newValueError = _getNewValueForFieldO3.newValueError; if (showErrorMessage) { current = current.set("valueError", newValueError); } var newOperatorOptions = canReuseValue ? currentOperatorOptions : defaultOperatorOptions(config, newOperator, currentField); if (!canReuseValue) { current = current["delete"]("asyncListValues"); } return current.set("operator", newOperator).set("operatorOptions", newOperatorOptions).set("value", newValue).set("valueSrc", newValueSrc).set("valueType", newValueType); }); }); if (isRuleGroup) { if (operatorCardinality == 0 && (children === null || children === void 0 ? void 0 : children.size) == 0) { state = addItem(state, path, "rule", uuid(), defaultRuleProperties(config, currentField), config); } } return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {integer} delta * @param {*} value * @param {string} valueType * @param {*} asyncListValues */ var setValue = function setValue(state, path, delta, value, valueType, config, asyncListValues) { var _meta = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : {}; var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return { state: state }; } var canDropArgs = _meta.canDropArgs, isEndValue = _meta.isEndValue; var _config$settings3 = config.settings, fieldSeparator = _config$settings3.fieldSeparator, showErrorMessage = _config$settings3.showErrorMessage; var valueSrc = state.getIn(expandTreePath(path, "properties", "valueSrc", delta + "")) || null; if (valueSrc === "field" && Array.isArray(value)) value = value.join(fieldSeparator); var field = state.getIn(expandTreePath(path, "properties", "field")) || null; //const fieldSrc = state.getIn(expandTreePath(path, "properties", "fieldSrc")) || null; var operator = state.getIn(expandTreePath(path, "properties", "operator")) || null; var operatorConfig = getOperatorConfig(config, operator, field); var operatorCardinality = operator ? getOpCardinality(operatorConfig) : null; var calculatedValueType = valueType || calculateValueType(value, valueSrc, config); var canFix = !showErrorMessage; var _validateValue = validateValue(config, field, field, operator, value, calculatedValueType, valueSrc, asyncListValues, canFix, isEndValue, canDropArgs), _validateValue2 = _slicedToArray(_validateValue, 2), fixedValue = _validateValue2[0], allErrors = _validateValue2[1]; var firstError = allErrors === null || allErrors === void 0 ? void 0 : allErrors.find(function (e) { return !e.fixed && !e.ignore; }); var validationError = firstError ? translateValidation(firstError) : null; // tip: even if canFix == false, use fixedValue, it can SAFELY fix value of select // (get exact value from listValues, not string) var willFix = fixedValue !== value; if (willFix) { value = fixedValue; } // init lists state = initEmptyValueLists(state, path, config, operatorCardinality); // Additional validation for range values var values = Array.from({ length: operatorCardinality }, function (_, i) { return i == delta ? value : state.getIn(expandTreePath(path, "properties", "value", i + "")) || null; }); var valueSrcs = Array.from({ length: operatorCardinality }, function (_, i) { return state.getIn(expandTreePath(path, "properties", "valueSrc", i + "")) || null; }); var rangeErrorObj = validateRange(config, field, operator, values, valueSrcs); var rangeValidationError = rangeErrorObj ? translateValidation(rangeErrorObj) : null; var isValid = !validationError && !rangeValidationError; var canUpdValue = showErrorMessage ? true : isValid || willFix; // set only good value // const lastValue = state.getIn(expandTreePath(path, "properties", "value", delta)); // const lastError = state.getIn(expandTreePath(path, "properties", "valueError", delta)); // const lastRangeError = state.getIn(expandTreePath(path, "properties", "valueError", operatorCardinality)); // const didDeltaErrorChanged = showErrorMessage ? lastError != validationError : !!lastError != !!validationError; // const didRangeErrorChanged = showErrorMessage ? lastRangeError != rangeValidationError : !!lastRangeError != !!rangeValidationError; // const didErrorChanged = didDeltaErrorChanged || didRangeErrorChanged; // const didEmptinessChanged = !!lastValue != !!value; // isInternalValueChange = !didEmptinessChanged && !didErrorChanged && !willFix; if (canUpdValue) { state = state.deleteIn(expandTreePath(path, "properties", "asyncListValues")); if (typeof value === "undefined") { state = state.setIn(expandTreePath(path, "properties", "value", delta), undefined); state = state.setIn(expandTreePath(path, "properties", "valueType", delta), null); } else { if (asyncListValues) { state = state.setIn(expandTreePath(path, "properties", "asyncListValues"), asyncListValues); } state = state.setIn(expandTreePath(path, "properties", "value", delta), value); state = state.setIn(expandTreePath(path, "properties", "valueType", delta), calculatedValueType); } } if (showErrorMessage) { // check list var lastValueErrorArr = state.getIn(expandTreePath(path, "properties", "valueError")); if (!lastValueErrorArr) { state = state.setIn(expandTreePath(path, "properties", "valueError"), new Immutable.List(new Array(operatorCardinality))); } // set error at delta state = state.setIn(expandTreePath(path, "properties", "valueError", delta), validationError); // set range error if (operatorCardinality >= 2) { state = state.setIn(expandTreePath(path, "properties", "valueError", operatorCardinality), rangeValidationError); } } return { state: state }; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {integer} delta * @param {*} srcKey */ var setValueSrc = function setValueSrc(state, path, delta, srcKey, config) { var _meta = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return state; } var showErrorMessage = config.settings.showErrorMessage; var field = state.getIn(expandTreePath(path, "properties", "field")) || null; //const fieldSrc = state.getIn(expandTreePath(path, "properties", "fieldSrc")) || null; var operator = state.getIn(expandTreePath(path, "properties", "operator")) || null; var operatorConfig = getOperatorConfig(config, operator, field); var operatorCardinality = operator ? getOpCardinality(operatorConfig) : null; // init lists state = initEmptyValueLists(state, path, config, operatorCardinality); state = state.setIn(expandTreePath(path, "properties", "value", delta + ""), undefined); state = state.setIn(expandTreePath(path, "properties", "valueType", delta + ""), null); state = state.deleteIn(expandTreePath(path, "properties", "asyncListValues")); if (showErrorMessage) { // clear value error state = state.setIn(expandTreePath(path, "properties", "valueError", delta), null); // if current operator is range, clear possible range error if (operatorConfig !== null && operatorConfig !== void 0 && operatorConfig.validateValues) { state = state.setIn(expandTreePath(path, "properties", "valueError", operatorCardinality), null); } } // set valueSrc if (typeof srcKey === "undefined") { state = state.setIn(expandTreePath(path, "properties", "valueSrc", delta + ""), null); } else { state = state.setIn(expandTreePath(path, "properties", "valueSrc", delta + ""), srcKey); } // maybe set default value if (srcKey) { var properties = state.getIn(expandTreePath(path, "properties")); // this call should return canReuseValue = false and provide default value var canFix = true; var _getNewValueForFieldO4 = getNewValueForFieldOp({ validateValue: validateValue, validateRange: validateRange }, config, config, properties, field, operator, "valueSrc", canFix), canReuseValue = _getNewValueForFieldO4.canReuseValue, newValue = _getNewValueForFieldO4.newValue, newValueSrc = _getNewValueForFieldO4.newValueSrc, newValueType = _getNewValueForFieldO4.newValueType, newValueError = _getNewValueForFieldO4.newValueError; if (!canReuseValue && newValueSrc.get(delta) == srcKey) { state = state.setIn(expandTreePath(path, "properties", "value", delta + ""), newValue.get(delta)); state = state.setIn(expandTreePath(path, "properties", "valueType", delta + ""), newValueType.get(delta)); } } return state; }; /** * @param {Immutable.Map} state * @param {Immutable.List} path * @param {string} name * @param {*} value */ var setOperatorOption = function setOperatorOption(state, path, name, value) { var currentRule = state.getIn(expandTreePath(path)); if (!currentRule) { // incorrect path return state; } return state.setIn(expandTreePath(path, "properties", "operatorOptions", name), value); }; /** * @param {Immutable.Map} state */ var checkEmptyGroups = function checkEmptyGroups(state, config) { var canLeaveEmptyGroup = config.settings.canLeaveEmptyGroup; if (!canLeaveEmptyGroup) { state = fixEmptyGroupsInTree(state); } return state; }; var initEmptyValueLists = function initEmptyValueLists(state, path, config, operatorCardinality) { if (!operatorCardinality) { var field = state.getIn(expandTreePath(path, "properties", "field")) || null; var operator = state.getIn(expandTreePath(path, "properties", "operator")) || null; var operatorConfig = getOperatorConfig(config, operator, field); operatorCardinality = operator ? getOpCardinality(operatorConfig) : null; } for (var _i = 0, _arr = ["value", "valueType", "valueError", "valueSrc"]; _i < _arr.length; _i++) { var k = _arr[_i]; if (!state.getIn(expandTreePath(path, "properties", k))) { state = state.setIn(expandTreePath(path, "properties", k), new Immutable.List(operatorCardinality ? Array.from({ length: operatorCardinality }) : [])); } } return state; }; // convert children deeply from JS to Immutable var _addChildren = function _addChildren1(config, item, children) { if (children && Array.isArray(children)) { item.children1 = new Immutable.OrderedMap(children.reduce(function (map, it) { var _it$id; var id1 = (_it$id = it.id) !== null && _it$id !== void 0 ? _it$id : uuid(); var it1 = _objectSpread(_objectSpread({}, it), {}, { properties: defaultItemProperties(config, it).merge(fromJS(it.properties) || {}), id: id1 }); _addChildren(config, it1, it1.children1); //todo: guarantee order return _objectSpread(_objectSpread({}, map), {}, _defineProperty({}, id1, new Immutable.Map(it1))); }, {})); } }; var getField = function getField(state, path) { var field = state.getIn(expandTreePath(path, "properties", "field")) || null; return field; }; var emptyDrag = { dragging: { id: null, x: null, y: null, w: null, h: null }, mousePos: {}, dragStart: { id: null } }; var getActionMeta = function getActionMeta(action, state) { if (!action || !action.type) return null; var actionKeysToOmit = ["config", "asyncListValues"]; var actionTypesToIgnore = [constants.SET_TREE, constants.SET_DRAG_START, constants.SET_DRAG_PROGRESS, constants.SET_DRAG_END]; var meta = mapValues(omit(action, actionKeysToOmit), applyToJS); var affectedField = action.path && getField(state.tree, action.path) || action.field; if (affectedField) { var _affectedField; if ((_affectedField = affectedField) !== null && _affectedField !== void 0 && _affectedField.toJS) affectedField = affectedField.toJS(); meta.affectedField = affectedField; } if (actionTypesToIgnore.includes(action.type) || action.type.indexOf("@@redux") == 0) meta = null; return meta; }; /** * @param {Immutable.Map} state * @param {object} action */ export default (function (initialConfig, tree, getMemoizedTree, setLastTree, getLastConfig) { var initTree = tree; var emptyState = _objectSpread({ tree: initTree }, emptyDrag); return function () { var _ref3, _getLastConfig; var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : emptyState; var action = arguments.length > 1 ? arguments[1] : undefined; var config = (_ref3 = (_getLastConfig = getLastConfig === null || getLastConfig === void 0 ? void 0 : getLastConfig()) !== null && _getLastConfig !== void 0 ? _getLastConfig : action === null || action === void 0 ? void 0 : action.config) !== null && _ref3 !== void 0 ? _ref3 : initialConfig; var unset = { __lastAction: undefined }; var set = {}; var actionMeta = getActionMeta(action, state); switch (action === null || action === void 0 ? void 0 : action.type) { case constants.SET_TREE: { var validatedTree = getMemoizedTree(config, action.tree); set.tree = validatedTree; break; } case constants.ADD_CASE_GROUP: { set.tree = addNewGroup(state.tree, action.path, "case_group", action.id, action.properties, config, action.children, action.meta); break; } case constants.ADD_GROUP: { set.tree = addNewGroup(state.tree, action.path, "group", action.id, action.properties, config, action.children, action.meta); break; } case constants.REMOVE_GROUP: { set.tree = removeGroup(state.tree, action.path, config); break; } case constants.REMOVE_GROUP_CHILDREN: { set.tree = removeGroupChildren(state.tree, action.path, config); break; } case constants.ADD_RULE: { set.tree = addItem(state.tree, action.path, action.ruleType, action.id, action.properties, config, action.children); break; } case constants.REMOVE_RULE: { set.tree = removeRule(state.tree, action.path, config); break; } case constants.SET_CONJUNCTION: { set.tree = setConjunction(state.tree, action.path, action.conjunction); break; } case constants.SET_NOT: { set.tree = setNot(state.tree, action.path, action.not); break; } case constants.SET_FIELD: { var _setField = setField(state.tree, action.path, action.field, config, action.asyncListValues, action._meta), newTree = _setField.state; set.tree = newTree; break; } case constants.SET_FIELD_SRC: { set.tree = setFieldSrc(state.tree, action.path, action.srcKey, config); break; } case constants.SET_LOCK: { set.tree = setLock(state.tree, action.path, action.lock); break; } case constants.SET_OPERATOR: { set.tree = setOperator(state.tree, action.path, action.operator, config); break; } case constants.SET_VALUE: { var _setValue = setValue(state.tree, action.path, action.delta, action.value, action.valueType, config, action.asyncListValues, action._meta), _newTree = _setValue.state; set.tree = _newTree; break; } case constants.SET_FUNC_VALUE: { var _setFuncValue = setFuncValue(config, state.tree, action.path, action.delta, action.parentFuncs, action.argKey, action.value, action.v