@react-awesome-query-builder/core
Version:
User-friendly query builder for React. Core
1,171 lines (1,147 loc) • 52.4 kB
JavaScript
"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