UNPKG

@react-awesome-query-builder/core

Version:
1,171 lines (1,147 loc) 52.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof3 = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.sanitizeTree = exports.isValidTree = exports.getTreeBadFields = exports.checkTree = exports._validateTree = void 0; Object.defineProperty(exports, "translateValidation", { enumerable: true, get: function get() { return _i18n.translateValidation; } }); exports.validateValue = exports.validateTree = exports.validateRange = exports.validateAndFixTree = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _omit = _interopRequireDefault(require("lodash/omit")); var _immutable = _interopRequireDefault(require("immutable")); var _configUtils = require("./configUtils"); var _configExtend = require("./configExtend"); var _ruleUtils = require("./ruleUtils"); var _getNewValueForFieldOp = require("./getNewValueForFieldOp"); var _stuff = require("./stuff"); var _listValues = require("./listValues"); var _defaultUtils = require("./defaultUtils"); var _treeUtils = require("./treeUtils"); var _queryString = require("../export/queryString"); var constants = _interopRequireWildcard(require("../i18n/validation/constains")); var _i18n = require("../i18n"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } 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; } // tip: If showErrorMessage is false, this function will always return true var isValidTree = exports.isValidTree = function isValidTree(tree, config) { return getTreeBadFields(tree, config).length === 0; }; // tip: If showErrorMessage is false, this function will always return [] // tip: If LHS is func, func key will be used to put in array of bad fields (naive) var getTreeBadFields = exports.getTreeBadFields = function getTreeBadFields(tree, config) { var showErrorMessage = config.settings.showErrorMessage; var badFields = []; function _processNode(item, path, lev) { var _field$get, _field$get2; var id = item.get("id"); var children = item.get("children1"); var valueError = item.getIn(["properties", "valueError"]); var fieldError = item.getIn(["properties", "fieldError"]); var field = item.getIn(["properties", "field"]); var fieldStr = (_field$get = field === null || field === void 0 || (_field$get2 = field.get) === null || _field$get2 === void 0 ? void 0 : _field$get2.call(field, "func")) !== null && _field$get !== void 0 ? _field$get : field; var hasValueError = (valueError === null || valueError === void 0 ? void 0 : valueError.size) > 0 && valueError.filter(function (v) { return v != null; }).size > 0; var isBad = hasValueError || !!fieldError; if (isBad && showErrorMessage) { // for showErrorMessage=false valueError/fieldError is used to hold last error, but actual value is always valid badFields.push(fieldStr); } if (children) { children.map(function (child, _childId) { if (child) { _processNode(child, path.concat(id), lev + 1); } }); } } if (tree) _processNode(tree, [], 0); return Array.from(new Set(badFields)); }; // @deprecated var checkTree = exports.checkTree = function checkTree(tree, config) { var extendedConfig = (0, _configExtend.extendConfig)(config, undefined, true); var options = { removeEmptyGroups: config.settings.removeEmptyGroupsOnLoad, removeIncompleteRules: config.settings.removeIncompleteRulesOnLoad, removeEmptyRules: config.settings.removeEmptyRulesOnLoad, forceFix: false }; var _validateTree2 = _validateTree(tree, null, extendedConfig, extendedConfig, options), fixedTree = _validateTree2.fixedTree, allErrors = _validateTree2.allErrors, isSanitized = _validateTree2.isSanitized; if (isSanitized && allErrors.length) { console.warn("Tree check errors: ", allErrors); } return fixedTree; }; /** * @param {Immutable.Map} tree * @param {SanitizeOptions} options * @returns {ValidationItemErrors[]} */ var validateTree = exports.validateTree = function validateTree(tree, config) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var extendedConfig = (0, _configExtend.extendConfig)(config, undefined, true); var finalOptions = _objectSpread(_objectSpread({}, options), {}, { // disbale sanitize options, just validate removeEmptyGroups: false, removeEmptyRules: false, removeIncompleteRules: false, forceFix: false }); var _validateTree3 = _validateTree(tree, null, extendedConfig, extendedConfig, finalOptions), allErrors = _validateTree3.allErrors; return allErrors; }; /** * @param {Immutable.Map} tree * @param {SanitizeOptions} options * @returns {{ * fixedTree: Immutable.Map, * fixedErrors: ValidationItemErrors[], * nonFixedErrors: ValidationItemErrors[], * allErrors: ValidationItemErrors[], * }} */ var sanitizeTree = exports.sanitizeTree = function sanitizeTree(tree, config) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var extendedConfig = (0, _configExtend.extendConfig)(config, undefined, true); var finalOptions = _objectSpread({ // defaults removeEmptyGroups: true, removeEmptyRules: true, removeIncompleteRules: true, forceFix: false }, options); var _validateTree4 = _validateTree(tree, null, extendedConfig, extendedConfig, finalOptions), fixedTree = _validateTree4.fixedTree, fixedErrors = _validateTree4.fixedErrors, nonFixedErrors = _validateTree4.nonFixedErrors, allErrors = _validateTree4.allErrors; return { fixedTree: fixedTree, fixedErrors: fixedErrors, nonFixedErrors: nonFixedErrors, allErrors: allErrors }; }; // tip: Should be used only internally in createValidationMemo() var validateAndFixTree = exports.validateAndFixTree = function validateAndFixTree(newTree, _oldTree, newConfig, oldConfig, removeEmptyGroups, removeEmptyRules, removeIncompleteRules) { if (removeEmptyGroups === undefined) { removeEmptyGroups = newConfig.settings.removeEmptyGroupsOnLoad; } if (removeEmptyRules === undefined) { removeEmptyRules = newConfig.settings.removeEmptyRulesOnLoad; } if (removeIncompleteRules === undefined) { removeIncompleteRules = newConfig.settings.removeIncompleteRulesOnLoad; } var options = { // sanitize options removeEmptyGroups: removeEmptyGroups, removeEmptyRules: removeEmptyRules, removeIncompleteRules: removeIncompleteRules, forceFix: false }; var _validateTree5 = _validateTree(newTree, _oldTree, newConfig, oldConfig, options), fixedTree = _validateTree5.fixedTree, allErrors = _validateTree5.allErrors, fixedErrors = _validateTree5.fixedErrors, nonFixedErrors = _validateTree5.nonFixedErrors, isSanitized = _validateTree5.isSanitized; if (isSanitized && fixedErrors.length) { console.warn("Fixed tree errors: ", fixedErrors); } // if (nonFixedErrors.length) { // console.info("Tree validation errors: ", nonFixedErrors); // } fixedTree = (0, _treeUtils.fixPathsInTree)(fixedTree); return fixedTree; }; /** * @param {Immutable.Map} tree * @param {SanitizeOptions} options * @typedef {{ * removeEmptyGroups?: boolean, * removeEmptyRules?: boolean, * removeIncompleteRules?: boolean, * forceFix?: boolean, * translateErrors?: boolean, * includeStringifiedItems?: boolean, * stringifyFixedItems?: boolean, * stringifyItemsUserFriendly?: boolean, * includeItemsPositions?: boolean, * }} SanitizeOptions * @typedef {{ * path: string[], * errors: { * key: string, args?: object | null, str?: string, * side?: "lhs"|"rhs"|"op", delta?: number, fixed?: boolean, fixedTo?: any, fixedFrom?: any, * }[], * itemStr?: string, * itemPosition?: { * caseNo: number | null, globalNoByType: number, indexPath: number[], globalLeafNo?: number, globalGroupNo?: number, * isDeleted: boolean, index: number, type: "rule"|"group"|"rule_group" * }, * itemPositionStr?: string, * }} ValidationItemErrors * @returns {{ * fixedTree: Immutable.Map, * allErrors: ValidationItemErrors[], * fixedErrors: ValidationItemErrors[], * nonFixedErrors: ValidationItemErrors[], * isSanitized: boolean * }} */ var _validateTree = exports._validateTree = function _validateTree(tree, _oldTree, config, oldConfig, options) { if (!tree) { return { fixedTree: tree, allErrors: [], fixedErrors: [], nonFixedErrors: [], isSanitized: false }; } var _ref = options || {}, removeEmptyGroups = _ref.removeEmptyGroups, removeEmptyRules = _ref.removeEmptyRules, removeIncompleteRules = _ref.removeIncompleteRules, forceFix = _ref.forceFix, _ref$translateErrors = _ref.translateErrors, translateErrors = _ref$translateErrors === void 0 ? true : _ref$translateErrors, _ref$includeStringifi = _ref.includeStringifiedItems, includeStringifiedItems = _ref$includeStringifi === void 0 ? true : _ref$includeStringifi, _ref$stringifyFixedIt = _ref.stringifyFixedItems, stringifyFixedItems = _ref$stringifyFixedIt === void 0 ? false : _ref$stringifyFixedIt, _ref$stringifyItemsUs = _ref.stringifyItemsUserFriendly, stringifyItemsUserFriendly = _ref$stringifyItemsUs === void 0 ? true : _ref$stringifyItemsUs, _ref$includeItemsPosi = _ref.includeItemsPositions, includeItemsPositions = _ref$includeItemsPosi === void 0 ? true : _ref$includeItemsPosi; var c = { config: config, oldConfig: oldConfig, removeEmptyGroups: removeEmptyGroups, removeEmptyRules: removeEmptyRules, removeIncompleteRules: removeIncompleteRules, forceFix: forceFix }; var meta = { errors: {} }; var fixedTree = validateItem(tree, [], null, meta, c); var isSanitized = meta.sanitized; // build allErrors var allErrors = []; var flatItems, oldFlatItems; if (includeItemsPositions) { flatItems = (0, _treeUtils.getFlatTree)(fixedTree, config).items; } for (var id in meta.errors) { var _meta$errors$id = meta.errors[id], path = _meta$errors$id.path, errors = _meta$errors$id.errors; if (translateErrors) { errors = errors.map(function (e) { return _objectSpread(_objectSpread({}, e), {}, { str: (0, _i18n.translateValidation)(e) }); }); } var errorItem = { path: path, errors: errors }; if (includeStringifiedItems) { var item = (0, _treeUtils.getItemByPath)(stringifyFixedItems ? fixedTree : tree, path); var isRoot = path.length === 1; if (!isRoot && item.get("type") !== "group") { var isDebugMode = true; var isForDisplay = stringifyItemsUserFriendly; var itemStr = (0, _queryString.queryString)(item, config, isForDisplay, isDebugMode); errorItem.itemStr = itemStr; } } if (includeItemsPositions) { var flatItem = flatItems[id]; var isDeleted = !flatItem; if (isDeleted) { // get positions from old tree if (!oldFlatItems) { oldFlatItems = (0, _treeUtils.getFlatTree)(tree, config).items; } flatItem = oldFlatItems[id]; } if (flatItem) { // build position object var itemPosition = _objectSpread(_objectSpread({}, flatItem.position), {}, { index: flatItem.index, type: flatItem.type, isDeleted: isDeleted }); errorItem.itemPosition = itemPosition; // build position string var trKey = !flatItem.index ? constants.ITEM_POSITION_ROOT : constants.ITEM_POSITION + "__" + flatItem.type + (isDeleted ? "__deleted" : ""); var trArgs = _objectSpread({}, itemPosition); if (stringifyItemsUserFriendly) { var _itemPosition$indexPa; // convert indexes from 0-based to 1-based (user friendly) for (var _i = 0, _arr = ["caseNo", "globalLeafNo", "globalGroupNo", "globalNoByType"]; _i < _arr.length; _i++) { var k = _arr[_i]; if (trArgs[k] != undefined) { trArgs[k] = trArgs[k] + 1; } } trArgs.indexPath = (_itemPosition$indexPa = itemPosition.indexPath) === null || _itemPosition$indexPa === void 0 ? void 0 : _itemPosition$indexPa.map(function (ind) { return ind + 1; }); } errorItem.itemPositionStr = (0, _i18n.translateValidation)(trKey, trArgs); if (flatItem.index) { // don't extend for root if (flatItem.caseId && flatItem.type !== "case_group") { errorItem.itemPositionStr = (0, _i18n.translateValidation)(constants.ITEM_POSITION_IN_CASE, _objectSpread(_objectSpread({}, trArgs), {}, { str: errorItem.itemPositionStr })); } if (flatItem.type !== "case_group") { errorItem.itemPositionStr = (0, _i18n.translateValidation)(constants.ITEM_POSITION_WITH_INDEX_PATH, _objectSpread(_objectSpread({}, trArgs), {}, { str: errorItem.itemPositionStr })); } } } } allErrors.push(errorItem); } // split allErrors to fixedErrors and nonFixedErrors var fixedErrors = []; var nonFixedErrors = []; for (var _i2 = 0, _allErrors = allErrors; _i2 < _allErrors.length; _i2++) { var itemErrors = _allErrors[_i2]; var fixedItemErrors = itemErrors.errors.filter(function (e) { return !!e.fixed; }); var nonFixedItemErrors = itemErrors.errors.filter(function (e) { return !e.fixed && e.key !== "EMPTY_QUERY"; }); if (fixedItemErrors.length) { fixedErrors.push(_objectSpread(_objectSpread({}, itemErrors), {}, { errors: fixedItemErrors })); } if (nonFixedItemErrors.length) { nonFixedErrors.push(_objectSpread(_objectSpread({}, itemErrors), {}, { errors: nonFixedItemErrors })); } } return { fixedTree: fixedTree, allErrors: allErrors, fixedErrors: fixedErrors, nonFixedErrors: nonFixedErrors, isSanitized: isSanitized }; }; function _addError(meta, item, path, err) { var id = item.get("id"); if (!meta.errors[id]) { meta.errors[id] = { path: [].concat((0, _toConsumableArray2["default"])(path), [id]), errors: [] }; } meta.errors[id].errors.push(err); } function _setErrorsAsFixed(meta, item) { var id = item.get("id"); if (meta.errors[id]) { meta.errors[id].errors.map(function (e) { e.fixed = true; }); } } function validateItem(item, path, itemId, meta, c) { var type = item === null || item === void 0 ? void 0 : item.get("type"); if (type === "group" || type === "rule_group" || type == "case_group" || type == "switch_group") { return validateGroup(item, path, itemId, meta, c); } else if (type === "rule") { return validateRule(item, path, itemId, meta, c); } else { return item; } } function validateGroup(item, path, itemId, meta, c) { var _properties$get, _config$operators$ope, _config$operators$ope2, _children, _children2, _children3; var removeEmptyGroups = c.removeEmptyGroups, removeIncompleteRules = c.removeIncompleteRules, forceFix = c.forceFix, config = c.config; var showErrorMessage = config.settings.showErrorMessage; var canFix = !showErrorMessage || forceFix; var id = item.get("id"); var children = item.get("children1"); var isRoot = !path.length; var oldChildren = children; var type = item.get("type"); var properties = item.get("properties"); var field = properties === null || properties === void 0 ? void 0 : properties.get("field"); var mode = properties === null || properties === void 0 ? void 0 : properties.get("mode"); var operator = properties === null || properties === void 0 || (_properties$get = properties.get) === null || _properties$get === void 0 ? void 0 : _properties$get.call(properties, "operator"); var isGroupExt = type === "rule_group" && mode === "array"; var isCase = type === "case_group"; var isDefaultCase = isCase && children == undefined; var cardinality = operator ? (_config$operators$ope = (_config$operators$ope2 = config.operators[operator]) === null || _config$operators$ope2 === void 0 ? void 0 : _config$operators$ope2.cardinality) !== null && _config$operators$ope !== void 0 ? _config$operators$ope : 1 : undefined; // tip: for group operators some/none/all children ARE required, for group operator count children are NOT required // tip: default case should contain only value var childrenAreRequired = isCase ? !isDefaultCase : isGroupExt ? cardinality == 0 : removeEmptyGroups; var canHaveValue = isGroupExt || isCase; if (!id && itemId) { id = itemId; item = item.set("id", id); meta.sanitized = true; } if (canHaveValue) { item = validateRule(item, path, itemId, meta, c); } //validate children var submeta = { errors: {} }; children = (_children = children) === null || _children === void 0 ? void 0 : _children.map(function (currentChild, childId) { return validateItem(currentChild, path.concat(id), childId, submeta, c); }); var nonEmptyChildren = (_children2 = children) === null || _children2 === void 0 ? void 0 : _children2.filter(function (currentChild) { return currentChild != undefined; }); if (removeEmptyGroups) { children = nonEmptyChildren; } var sanitized = submeta.sanitized || (oldChildren === null || oldChildren === void 0 ? void 0 : oldChildren.size) != ((_children3 = children) === null || _children3 === void 0 ? void 0 : _children3.size); var isEmptyChildren = !(nonEmptyChildren !== null && nonEmptyChildren !== void 0 && nonEmptyChildren.size); var canDrop = removeEmptyGroups && !isRoot; if (isGroupExt && field) { // to remove rule-group like "SOME cars" (with SOME/ALL/NONE, but without filters), we need to rely on removeIncompleteRules canDrop = removeIncompleteRules; } if (isEmptyChildren && childrenAreRequired) { _addError(meta, item, path, { key: isRoot ? constants.EMPTY_QUERY : isCase ? constants.EMPTY_CASE : isGroupExt ? constants.EMPTY_RULE_GROUP : constants.EMPTY_GROUP, args: { field: field }, fixed: canDrop }); if (canDrop) { _setErrorsAsFixed(meta, item); item = undefined; } } if (sanitized) meta.sanitized = true; if (sanitized && item) item = item.set("children1", children); meta.errors = _objectSpread(_objectSpread({}, meta.errors), (submeta === null || submeta === void 0 ? void 0 : submeta.errors) || {}); return item; } /** * @param {Immutable.Map} item * @returns {Immutable.Map} */ function validateRule(item, path, itemId, meta, c) { var removeIncompleteRules = c.removeIncompleteRules, removeEmptyRules = c.removeEmptyRules, forceFix = c.forceFix, config = c.config, oldConfig = c.oldConfig; var showErrorMessage = config.settings.showErrorMessage; var canFix = !showErrorMessage || forceFix; var origItem = item; var id = item.get("id"); var type = item.get("type"); var isCase = type === "case_group"; var properties = item.get("properties"); if (!properties) { if (isCase) { properties = new _immutable["default"].Map(); } else { var err = { key: constants.INCOMPLETE_RULE, args: {}, fixed: removeIncompleteRules || removeEmptyRules }; _addError(meta, item, path, err); return undefined; } } var field = properties.get("field") || null; if (isCase) { field = "!case_value"; } var fieldSrc = properties.get("fieldSrc") || null; var operator = properties.get("operator") || null; var operatorOptions = properties.get("operatorOptions"); var valueSrc = properties.get("valueSrc"); var value = properties.get("value"); var valueError = properties.get("valueError"); var fieldError = properties.get("fieldError"); var serializeRule = function serializeRule() { var _field, _field$toJS; return { field: ((_field = field) === null || _field === void 0 || (_field$toJS = _field.toJS) === null || _field$toJS === void 0 ? void 0 : _field$toJS.call(_field)) || field, fieldSrc: fieldSrc, operator: operator, operatorOptions: operatorOptions ? operatorOptions.toJS() : {}, valueSrc: valueSrc ? valueSrc.toJS() : null, value: value ? value.toJS() : null, valueError: valueError ? valueError.toJS() : null, fieldError: fieldError ? fieldError : null }; }; var oldSerialized = serializeRule(); //const _wasValid = field && operator && value && !value.includes(undefined); if (!id && itemId) { id = itemId; item = item.set("id", id); meta.sanitized = true; } //validate field var fieldDefinition = field ? (0, _configUtils.getFieldConfig)(config, field) : null; if (field && !fieldDefinition) { _addError(meta, item, path, { key: constants.NO_CONFIG_FOR_FIELD, args: { field: field }, side: "lhs", fixed: removeIncompleteRules || removeEmptyRules }); field = null; } if (field == null && !isCase) { properties = ["operator", "operatorOptions", "valueSrc", "value", "valueError", "fieldError", "field"].reduce(function (map, key) { return map["delete"](key); }, properties); operator = null; } if (!fieldSrc && field && !isCase) { fieldSrc = (0, _configUtils.getFieldSrc)(field); properties = properties.set("fieldSrc", fieldSrc); } //validate operator // Backward compatibility: obsolete operator range_between if (operator === "range_between" || operator === "range_not_between") { operator = operator === "range_between" ? "between" : "not_between"; // _addError(meta, item, path, { // type: "fix", // key: constants.FIXED_OPERATOR, // args: { from: properties.get("operator"), to: operator, field } // }); properties = properties.set("operator", operator); } var operatorDefinition = operator ? (0, _configUtils.getOperatorConfig)(config, operator, field) : null; if (operator && !operatorDefinition) { _addError(meta, item, path, { key: constants.NO_CONFIG_FOR_OPERATOR, args: { operator: operator }, side: "op", fixed: removeIncompleteRules || removeEmptyRules }); operator = null; } var availOps = field ? (0, _configUtils.getOperatorsForField)(config, field) : []; if (field && !isCase) { if (!(availOps !== null && availOps !== void 0 && availOps.length)) { _addError(meta, item, path, { key: constants.UNSUPPORTED_FIELD_TYPE, args: { field: field }, side: "lhs", fixed: removeIncompleteRules || removeEmptyRules }); operator = null; } else if (operator && availOps.indexOf(operator) == -1) { if (operator === "is_empty" || operator === "is_not_empty") { // Backward compatibility: is_empty #494 operator = operator === "is_empty" ? "is_null" : "is_not_null"; // _addError(meta, item, path, { // type: "fix", // key: constants.FIXED_OPERATOR, // args: { from: properties.get("operator"), to: operator, field } // }); properties = properties.set("operator", operator); } else { _addError(meta, item, path, { key: constants.UNSUPPORTED_OPERATOR_FOR_FIELD, args: { operator: operator, field: field }, side: "lhs", fixed: removeIncompleteRules || removeEmptyRules }); operator = null; } } } if (operator == null && !isCase) { // do not unset operator ? properties = ["operatorOptions", "valueSrc", "value", "valueError"].reduce(function (map, key) { return map["delete"](key); }, properties); } //validate operator options operatorOptions = properties.get("operatorOptions"); //const _operatorCardinality = operator ? getOpCardinality(operatorDefinition) : null; if (!operator || operatorOptions && !operatorDefinition.options) { operatorOptions = null; properties = properties["delete"]("operatorOptions"); } else if (operator && !operatorOptions && operatorDefinition.options) { operatorOptions = (0, _defaultUtils.defaultOperatorOptions)(config, operator, field); properties = properties.set("operatorOptions", operatorOptions); } //validate values valueSrc = properties.get("valueSrc"); value = properties.get("value"); var isEndValue = true; var _getNewValueForFieldO = (0, _getNewValueForFieldOp.getNewValueForFieldOp)({ validateValue: validateValue, validateRange: validateRange }, config, oldConfig, properties, field, operator, null, canFix, isEndValue), newValue = _getNewValueForFieldO.newValue, newValueSrc = _getNewValueForFieldO.newValueSrc, newValueError = _getNewValueForFieldO.newValueError, validationErrors = _getNewValueForFieldO.validationErrors, newFieldError = _getNewValueForFieldO.newFieldError, fixedField = _getNewValueForFieldO.fixedField; value = newValue; valueSrc = newValueSrc; valueError = newValueError; fieldError = newFieldError; field = fixedField; properties = properties.set("field", field); properties = properties.set("value", value); properties = properties.set("valueSrc", valueSrc); if (showErrorMessage) { properties = properties.set("valueError", valueError).set("fieldError", fieldError); } else { properties = properties["delete"]("valueError")["delete"]("fieldError"); } var newSerialized = serializeRule(); var hasBeenSanitized = !(0, _stuff.deepEqual)(oldSerialized, newSerialized); var compl = (0, _ruleUtils.whatRulePropertiesAreCompleted)(properties.toObject(), config); var isCompleted = isCase ? compl.parts.value : compl.score >= 3; if (hasBeenSanitized) { meta.sanitized = true; item = item.set("properties", properties); } validationErrors === null || validationErrors === void 0 || validationErrors.map(function (e) { return _addError(meta, item, path, e); }); if (!isCompleted) { if (isCase) { // todo } else { var shoudlRemoveRule = !compl.score ? removeEmptyRules : removeIncompleteRules; // if (shoudlRemoveRule && showErrorMessage) { // // try to be not so rude about removing incomplete rule with functions // const complLite = whatRulePropertiesAreCompleted(properties.toObject(), config, true); // const isCompletedLite = complLite.score >= 3; // if (isCompletedLite) { // shoudlRemoveRule = false; // } // } var incError = { key: constants.INCOMPLETE_RULE, args: {} }; if (!compl.parts.field) { incError.key = constants.INCOMPLETE_LHS; incError.side = "lhs"; } else if (!compl.parts.value) { var _newSerialized$valueS, _newSerialized$valueS2, _oldSerialized$valueS, _newSerialized$value; incError.key = constants.INCOMPLETE_RHS; incError.side = "rhs"; if ((_newSerialized$valueS = newSerialized.valueSrc) !== null && _newSerialized$valueS !== void 0 && _newSerialized$valueS[0] && ((_newSerialized$valueS2 = newSerialized.valueSrc) === null || _newSerialized$valueS2 === void 0 ? void 0 : _newSerialized$valueS2[0]) != ((_oldSerialized$valueS = oldSerialized.valueSrc) === null || _oldSerialized$valueS === void 0 ? void 0 : _oldSerialized$valueS[0]) && ((_newSerialized$value = newSerialized.value) === null || _newSerialized$value === void 0 ? void 0 : _newSerialized$value[0]) != undefined) { // eg. operator `starts_with` supports only valueSrc "value" incError.key = constants.INVALID_VALUE_SRC; incError.args = { valueSrcs: newSerialized.valueSrc }; } } incError.fixed = shoudlRemoveRule; _addError(meta, item, path, incError); if (shoudlRemoveRule) { _setErrorsAsFixed(meta, item); item = undefined; } } } return item; } /** * * @param {bool} canFix true is useful for func values to remove bad args * @param {bool} isEndValue false if value is in process of editing by user * @return {array} [fixedValue, allErrors] - if `allErrors` is empty and `canFix` == true, `fixedValue` can differ from value if was fixed. * `allErrors` is an array of {key, args, fixed, fixedFrom, fixedTo} * If `args` === null, `key` should not be translated */ var validateValue = exports.validateValue = function validateValue(config, leftField, field, operator, value, valueType, valueSrc, asyncListValues) { var canFix = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false; var isEndValue = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false; var canDropArgs = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false; var allErrors = []; var fixedValue = value; if (value != null) { var _allErrors2, _allErrors3, _allErrors4, _allErrors5; if (valueSrc === "field") { var _validateFieldValue = validateFieldValue(leftField, field, value, valueSrc, valueType, asyncListValues, config, operator, canFix, isEndValue); var _validateFieldValue2 = (0, _slicedToArray2["default"])(_validateFieldValue, 2); fixedValue = _validateFieldValue2[0]; allErrors = _validateFieldValue2[1]; } else if (valueSrc === "func") { var _validateFuncValue = validateFuncValue(leftField, field, value, valueSrc, valueType, asyncListValues, config, operator, canFix, isEndValue, canDropArgs); var _validateFuncValue2 = (0, _slicedToArray2["default"])(_validateFuncValue, 2); fixedValue = _validateFuncValue2[0]; allErrors = _validateFuncValue2[1]; } else if (valueSrc === "value" || !valueSrc) { var _validateNormalValue = validateNormalValue(field, value, valueSrc, valueType, asyncListValues, config, operator, canFix, isEndValue); var _validateNormalValue2 = (0, _slicedToArray2["default"])(_validateNormalValue, 2); fixedValue = _validateNormalValue2[0]; allErrors = _validateNormalValue2[1]; } var fixedAllErrors = !((_allErrors2 = allErrors) !== null && _allErrors2 !== void 0 && _allErrors2.find(function (e) { return !e.fixed; })); var shouldCallValidateFn = !!field // `validateValue` should not be available for valueSrc === "func" or "field" && !["field", "func"].includes(valueSrc) // eg. if value was > max, and fixed to max, but max value can not satisfy validateValue() in config && (!((_allErrors3 = allErrors) !== null && _allErrors3 !== void 0 && _allErrors3.length) || fixedAllErrors); if (shouldCallValidateFn) { //todo: why not just take fieldSettings from fieldConfig, why need to use getFieldWidgetConfig() ?? // const fieldConfig = getFieldConfig(config, field); // const fieldSettings = fieldConfig?.fieldSettings; var w = (0, _configUtils.getWidgetForFieldOp)(config, field, operator, valueSrc); var operatorDefinition = operator ? (0, _configUtils.getOperatorConfig)(config, operator, field) : null; var fieldWidgetDefinition = (0, _configUtils.getFieldWidgetConfig)(config, field, operator, w, valueSrc, { forExport: true }); var rightFieldDefinition = valueSrc === "field" ? (0, _configUtils.getFieldConfig)(config, value) : null; var fieldSettings = fieldWidgetDefinition; // widget definition merged with fieldSettings var fn = fieldWidgetDefinition.validateValue; if (typeof fn === "function") { var args = [fixedValue, fieldSettings, operator, operatorDefinition]; if (valueSrc === "field") args.push(rightFieldDefinition); var validResult = fn.call.apply(fn, [config.ctx].concat(args)); if ((0, _typeof2["default"])(validResult) === "object" && validResult !== null && !Array.isArray(validResult)) { var _validResult$error; var newError; if ((_validResult$error = validResult.error) !== null && _validResult$error !== void 0 && _validResult$error.key) { newError = _objectSpread({}, validResult.error); } else { // Note: `null` means it's not translated string! newError = { key: validResult.error, args: null }; } if (validResult.fixedValue !== undefined && canFix) { newError.fixed = true; newError.fixedFrom = fixedValue; newError.fixedTo = validResult.fixedValue; fixedValue = validResult.fixedValue; } allErrors.push(newError); } else if (typeof validResult === "boolean") { if (validResult == false) { allErrors.push({ key: constants.INVALID_VALUE, args: {} }); } } else if (typeof validResult === "string") { allErrors.push({ key: validResult, args: null }); } } } // if can't fix value, use defaultValue fixedAllErrors = !((_allErrors4 = allErrors) !== null && _allErrors4 !== void 0 && _allErrors4.find(function (e) { return !e.fixed; })); if ((_allErrors5 = allErrors) !== null && _allErrors5 !== void 0 && _allErrors5.length && !fixedAllErrors && canFix) { var fieldConfig = (0, _configUtils.getFieldConfig)(config, field); var _fieldSettings = fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.fieldSettings; var defaultValue = _fieldSettings === null || _fieldSettings === void 0 ? void 0 : _fieldSettings.defaultValue; if (defaultValue !== undefined) { var lastError = allErrors[allErrors.length - 1]; lastError.fixed = true; lastError.fixedFrom = fixedValue; lastError.fixedTo = defaultValue; fixedValue = defaultValue; // mark all errors as fixed allErrors.map(function (e) { e.fixed = true; }); } } } return [fixedValue, allErrors]; }; /** * */ var validateValueInList = function validateValueInList(value, listValues, canFix, isEndValue, removeInvalidMultiSelectValuesOnLoad) { var values = _immutable["default"].List.isList(value) ? value.toJS() : value instanceof Array ? (0, _toConsumableArray2["default"])(value) : undefined; var fixedValue = value; var allErrors = []; if (values) { var _values$reduce = values.reduce(function (_ref2, val) { var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2), goodVals = _ref3[0], badVals = _ref3[1]; var vv = (0, _listValues.getItemInListValues)(listValues, val); if (vv == undefined) { return [goodVals, [].concat((0, _toConsumableArray2["default"])(badVals), [val])]; } else { return [[].concat((0, _toConsumableArray2["default"])(goodVals), [vv.value]), badVals]; } }, [[], []]), _values$reduce2 = (0, _slicedToArray2["default"])(_values$reduce, 2), goodValues = _values$reduce2[0], badValues = _values$reduce2[1]; var needFix = badValues.length > 0; // always remove bad values at tree validation as user can't unselect them (except AntDesign widget) canFix = canFix || removeInvalidMultiSelectValuesOnLoad === true; fixedValue = canFix && needFix ? goodValues : value; if (badValues.length) { var fixed = canFix && needFix; allErrors.push({ key: constants.BAD_MULTISELECT_VALUES, args: { badValues: badValues, count: badValues.length }, fixed: fixed, fixedFrom: fixed ? values : undefined, fixedTo: fixed ? fixedValue : undefined }); } return [fixedValue, allErrors]; } else { var vv = (0, _listValues.getItemInListValues)(listValues, value); if (vv == undefined) { fixedValue = canFix ? null : value; allErrors.push({ key: constants.BAD_SELECT_VALUE, args: { value: value }, fixed: canFix, fixedFrom: canFix ? value : undefined, fixedTo: canFix ? fixedValue : undefined }); } else { fixedValue = vv.value; } return [fixedValue, allErrors]; } }; /** * */ var validateNormalValue = function validateNormalValue(field, value, valueSrc, valueType, asyncListValues, config) { var operator = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; var canFix = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false; var isEndValue = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false; var allErrors = []; var fixedValue = value; if (field) { var fieldConfig = (0, _configUtils.getFieldConfig)(config, field); var w = (0, _configUtils.getWidgetForFieldOp)(config, field, operator, valueSrc); var wConfig = config.widgets[w]; var wType = wConfig === null || wConfig === void 0 ? void 0 : wConfig.type; var jsType = wConfig === null || wConfig === void 0 ? void 0 : wConfig.jsType; var fieldSettings = fieldConfig === null || fieldConfig === void 0 ? void 0 : fieldConfig.fieldSettings; var listValues = (fieldSettings === null || fieldSettings === void 0 ? void 0 : fieldSettings.treeValues) || (fieldSettings === null || fieldSettings === void 0 ? void 0 : fieldSettings.listValues); var isAsyncListValues = !!(fieldSettings !== null && fieldSettings !== void 0 && fieldSettings.asyncFetch); // todo: for select/multiselect value can be string or number var canSkipTypeCheck = listValues || isAsyncListValues; // validate type if (valueType && wType && valueType != wType) { allErrors.push({ key: constants.INCORRECT_VALUE_TYPE, args: { wType: wType, valueType: valueType } }); return [value, allErrors]; } if (jsType && !(0, _stuff.isTypeOf)(value, jsType) && !canSkipTypeCheck) { allErrors.push({ key: constants.INCORRECT_VALUE_JS_TYPE, args: { jsType: jsType, valueTypeof: (0, _stuff.typeOf)(value) } }); return [value, allErrors]; } if (fieldSettings) { // validate against list of values var realListValues = asyncListValues || listValues; // tip: "case_value" is deprecated, don't apply validation based on listValues if (realListValues && !fieldSettings.allowCustomValues && w !== "case_value") { var _validateValueInList = validateValueInList(value, realListValues, canFix, isEndValue, config.settings.removeInvalidMultiSelectValuesOnLoad); var _validateValueInList2 = (0, _slicedToArray2["default"])(_validateValueInList, 2); fixedValue = _validateValueInList2[0]; allErrors = _validateValueInList2[1]; } // validate length if (fieldSettings.maxLength > 0 && value != null && String(value).length > fieldSettings.maxLength) { fixedValue = canFix ? String(value).substring(0, fieldSettings.maxLength) : value; allErrors.push({ key: constants.VALUE_LENGTH_CONSTRAINT_FAIL, args: { value: value, length: String(value).length, fieldSettings: fieldSettings }, fixed: canFix, fixedFrom: canFix ? value : undefined, fixedTo: canFix ? fixedValue : undefined }); } // validate min/max var minMaxContext = fieldSettings.min != undefined && fieldSettings.max != undefined ? constants._CONTEXT_MIN_MAX : undefined; if (fieldSettings.min != null && value < fieldSettings.min) { fixedValue = canFix ? fieldSettings.min : value; allErrors.push({ key: constants.VALUE_MIN_CONSTRAINT_FAIL, args: { value: value, fieldSettings: fieldSettings, context: minMaxContext }, fixed: canFix, fixedFrom: canFix ? value : undefined, fixedTo: canFix ? fixedValue : undefined }); } if (fieldSettings.max != null && value > fieldSettings.max) { fixedValue = canFix ? fieldSettings.max : value; allErrors.push({ key: constants.VALUE_MAX_CONSTRAINT_FAIL, args: { value: value, fieldSettings: fieldSettings, context: minMaxContext }, fixed: canFix, fixedFrom: canFix ? value : undefined, fixedTo: canFix ? fixedValue : undefined }); } } } return [fixedValue, allErrors]; }; /** * */ var validateFieldValue = function validateFieldValue(leftField, field, value, _valueSrc, valueType, asyncListValues, config) { var operator = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var canFix = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false; var isEndValue = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false; var allErrors = []; var _config$settings = config.settings, fieldSeparator = _config$settings.fieldSeparator, canCompareFieldWithField = _config$settings.canCompareFieldWithField; var isFuncArg = (0, _typeof2["default"])(field) == "object" && (field === null || field === void 0 ? void 0 : field._isFuncArg); var leftFieldStr = Array.isArray(leftField) ? leftField.join(fieldSeparator) : leftField; var leftFieldConfig = (0, _configUtils.getFieldConfig)(config, leftField); var rightFieldStr = Array.isArray(value) ? value.join(fieldSeparator) : value; var rightFieldConfig = (0, _configUtils.getFieldConfig)(config, value); if (!rightFieldConfig) { allErrors.push({ key: constants.NO_CONFIG_FOR_FIELD_VALUE, args: { field: rightFieldStr } }); return [value, allErrors]; } if (leftField && rightFieldStr === leftFieldStr && !isFuncArg) { allErrors.push({ key: constants.CANT_COMPARE_FIELD_WITH_ITSELF, args: { field: leftFieldStr } }); return [value, allErrors]; } if (valueType && valueType != rightFieldConfig.type) { allErrors.push({ key: constants.INCORRECT_FIELD_TYPE, args: { field: rightFieldStr, type: rightFieldConfig.type, expected: valueType } }); return [value, allErrors]; } if (leftField && !isFuncArg && canCompareFieldWithField) { var canUse = canCompareFieldWithField(leftFieldStr, leftFieldConfig, rightFieldStr, rightFieldConfig, operator); if (!canUse) { allErrors.push({ key: constants.CANT_COMPARE_FIELD_WITH_FIELD, args: { leftField: leftFieldStr, rightField: rightFieldStr } }); return [value, allErrors]; } } return [value]; }; /** * @param {bool} canDropArgs true only if user sets new func key */ var validateFuncValue = function validateFuncValue(leftField, field, value, _valueSrc, valueType, asyncListValues, config) { var _value$get, _funcConfig$label; var operator = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var canFix = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false; var isEndValue = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false; var canDropArgs = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false; var fixedValue = value; var allErrors = []; if (!value) { // empty value return [value]; } var funcKey = (_value$get = value.get) === null || _value$get === void 0 ? void 0 : _value$get.call(value, "func"); if (!funcKey) { // it's not a function value return [value]; } var fieldDef = (0, _configUtils.getFieldConfig)(config, field); if (fieldDef !== null && fieldDef !== void 0 && fieldDef.funcs && !fieldDef.funcs.includes(funcKey)) { allErrors.push({ key: constants.UNSUPPORTED_FUNCTION_FOR_FIELD, args: { funcKey: funcKey, field: field } }); return [value, allErrors]; } var funcConfig = (0, _configUtils.getFuncConfig)(config, funcKey); if (!funcConfig) { allErrors.push({ key: constants.NO_CONFIG_FOR_FUNCTION, args: { funcKey: funcKey } }); return [value, allErrors]; } var funcName = (_funcConfig$label = funcConfig.label) !== null && _funcConfig$label !== void 0 ? _funcConfig$label : funcKey; if (valueType && funcConfig.returnType != valueType) { allErrors.push({ key: constants.INCORRECT_FUNCTION_RETURN_TYPE, args: { funcKey: funcKey, funcName: funcName, returnType: funcConfig.returnType, valueType: valueType } }); return [value, allErrors]; } //tip: Exception for canDropArgs (true only if changing func) - can fix/drop args to fit new func validations canFix = canFix || canDropArgs; for (var argKey in funcConfig.args) { var _argDef$label; var argConfig = funcConfig.args[argKey]; var args = fixedValue.get("args"); var argVal = args ? args.get(argKey) : undefined; var argDef = (0, _configUtils.getFieldConfig)(config, argConfig); var argName = (_argDef$label = argDef === null || argDef === void 0 ? void 0 : argDef.label) !== null && _argDef$label !== void 0 ? _argDef$label : argKey; var argValue = argVal ? argVal.get("value") : undefined; var argValueSrc = argVal ? argVal.get("valueSrc") : undefined; if (argValue !== undefined) { var _validateValue = validateValue(config, leftField, argDef, operator, argValue, argConfig.type, argValueSrc, asyncListValues, canFix, isEndValue, canDropArgs), _validateValue2 = (0, _slicedToArray2["default"])(_validateValue, 2), fixedArgVal = _validateValue2[0], argErrors = _validateValue2[1]; var isValid = !(argErrors !== null && argErrors !== void 0 && argErrors.length); var willFix = canFix && fixedArgVal !== argValue; //const willFixAllErrors = !isValid && willFix && !allErrors?.find(e => !e.fixed); //tip: reset to default ONLY if isEndValue==true var canDropOrReset = canFix && !isValid && !willFix && (isEndValue || canDropArgs); if (willFix) { fixedValue = fixedValue.setIn(["args", argKey, "value"], fixedArgVal); } if (canDropOrReset) { // reset to default fixedValue = fixedValue.deleteIn(["args", argKey]); fixedValue = (0, _ruleUtils.setFuncDefaultArg)(config, fixedValue, funcConfig, argKey); } if (!isValid) { var _ref4, _argErrors$find; var firstError = (_ref4 = (_argErrors$find = argErrors.find(function (e) { return !e.fixed && !e.ignore; })) !== null && _argErrors$find !== void 0 ? _argErrors$find : argErrors.find(function (e) { return !e.fixed; })) !== null && _ref4 !== void 0 ? _ref4 : argErrors[0]; var fixed = willFix || canDropOrReset; var ignore = argErrors.filter(function (e) { return !e.ignore; }).length === 0; if (firstError) { var argValidationError = (0, _i18n.translateValidation)(firstError); allErrors.push({ key: constants.INVALID_FUNC_ARG_VALUE, args: { funcKey: funcKey, funcName: funcName, argKey: argKey, argName: argName, argValidationError: argValidationError, // more meta argErrors: argErrors }, ignore: ignore, fixed: fixed, fixedFrom: fixed ? argValue : undefined, fixedTo: fixed ? willFix ? fixedArgVal : argConfig.defaultValue : undefined }); } } } else if (!argConfig.isOptional && (isEndValue || canDropArgs)) { var canReset = canFix && argConfig.defaultValue !== undefined && (isEndValue || canDropArgs); var canAddError = isEndValue; //tip: Exception for canDropArgs (true only if changing func) - don't show error about requi