UNPKG

@react-awesome-query-builder/core

Version:
362 lines (353 loc) 19.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getNewValueForFieldOp = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _immutable = _interopRequireDefault(require("immutable")); var _configUtils = require("./configUtils"); var _stuff = require("./stuff"); var _i18n = require("../i18n"); var _treeUtils = require("./treeUtils"); 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; } /** * @param {Immutable.Map} current * @param {string} changedProp * @param {boolean} canFix (default: false) true - eg. set value to max if it > max or revert or drop * @param {boolean} isEndValue (default: false) true - if value is in process of editing by user * @param {boolean} canDropArgs (default: false) * @return {{canReuseValue, newValue, newValueSrc, newValueType, fixedField, operatorCardinality, newValueError, newFieldError, validationErrors}} */ var getNewValueForFieldOp = exports.getNewValueForFieldOp = function getNewValueForFieldOp(_ref, config) { var _currentField, _currentField$get, _newField, _newField$get; var validateValue = _ref.validateValue, validateRange = _ref.validateRange; var oldConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var current = arguments.length > 3 ? arguments[3] : undefined; var newField = arguments.length > 4 ? arguments[4] : undefined; var newOperator = arguments.length > 5 ? arguments[5] : undefined; var changedProp = 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 canDropArgs = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false; //const isValidatingTree = (changedProp === null); if (!oldConfig) oldConfig = config; var _config$settings = config.settings, keepInputOnChangeFieldSrc = _config$settings.keepInputOnChangeFieldSrc, convertableWidgets = _config$settings.convertableWidgets, clearValueOnChangeField = _config$settings.clearValueOnChangeField, clearValueOnChangeOp = _config$settings.clearValueOnChangeOp; var isCase = newField == "!case_value"; var currentField = current.get("field"); if (!currentField && isCase) { currentField = newField; } var currentFieldType = current.get("fieldType"); var currentFieldSrc = current.get("fieldSrc"); var currentOperator = current.get("operator"); var currentValue = current.get("value"); var currentValueSrc = current.get("valueSrc", new _immutable["default"].List()); var currentValueType = current.get("valueType", new _immutable["default"].List()); var currentValueError = current.get("valueError", new _immutable["default"].List()); var asyncListValues = current.get("asyncListValues"); var isOkWithoutOperator = isCase; var currentOperatorConfig = (0, _configUtils.getOperatorConfig)(oldConfig, currentOperator); var newOperatorConfig = (0, _configUtils.getOperatorConfig)(config, newOperator, newField); var currentOperatorCardinality = isCase ? 1 : currentOperator ? (0, _stuff.getOpCardinality)(currentOperatorConfig) : null; var operatorCardinality = isCase ? 1 : newOperator ? (0, _stuff.getOpCardinality)(newOperatorConfig) : null; var currentFieldConfig = (0, _configUtils.getFieldConfig)(oldConfig, currentField); var newFieldConfig = (0, _configUtils.getFieldConfig)(config, newField); var isOkWithoutField = !currentField && currentFieldType && keepInputOnChangeFieldSrc; var currentType = (currentFieldConfig === null || currentFieldConfig === void 0 ? void 0 : currentFieldConfig.type) || currentFieldType; var newType = (newFieldConfig === null || newFieldConfig === void 0 ? void 0 : newFieldConfig.type) || !newField && isOkWithoutField && currentType; var currentListValuesType = currentFieldConfig === null || currentFieldConfig === void 0 ? void 0 : currentFieldConfig.listValuesType; var newListValuesType = newFieldConfig === null || newFieldConfig === void 0 ? void 0 : newFieldConfig.listValuesType; var currentFieldSimpleValue = ((_currentField = currentField) === null || _currentField === void 0 || (_currentField$get = _currentField.get) === null || _currentField$get === void 0 ? void 0 : _currentField$get.call(_currentField, "func")) || currentField; var newFieldSimpleValue = ((_newField = newField) === null || _newField === void 0 || (_newField$get = _newField.get) === null || _newField$get === void 0 ? void 0 : _newField$get.call(_newField, "func")) || newField; var hasFieldChanged = newFieldSimpleValue != currentFieldSimpleValue; var validationErrors = []; var canReuseValue = (currentField || isOkWithoutField) && (currentOperator && newOperator || isOkWithoutOperator) && currentValue != undefined; if (!(currentType && newType && currentType == newType) || changedProp === "field" && hasFieldChanged && clearValueOnChangeField || changedProp === "operator" && clearValueOnChangeOp) { canReuseValue = false; } if (hasFieldChanged && _configUtils.selectTypes.includes(newType)) { if (newListValuesType && newListValuesType === currentListValuesType) { // ok } else { // different fields of select types has different listValues canReuseValue = false; } } if (!isOkWithoutOperator && (!(currentValue !== null && currentValue !== void 0 && currentValue.size) && operatorCardinality || currentValue !== null && currentValue !== void 0 && currentValue.size && !operatorCardinality)) { canReuseValue = false; } // validate func LHS var newFieldError; if (currentFieldSrc === "func" && newField) { var _validateValue = validateValue(config, null, null, newOperator, newField, newType, currentFieldSrc, asyncListValues, canFix, isEndValue, canDropArgs), _validateValue2 = (0, _slicedToArray2["default"])(_validateValue, 2), fixedField = _validateValue2[0], fieldErrors = _validateValue2[1]; var isValid = !(fieldErrors !== null && fieldErrors !== void 0 && fieldErrors.length); var willFix = fixedField !== newField; var willFixAllErrors = !isValid && willFix && !fieldErrors.find(function (e) { return !e.fixed; }); var willRevert = canFix && !isValid && !willFixAllErrors && !!changedProp && newField !== currentField; var willDrop = false; //canFix && !isValid && !willFixAllErrors && !willRevert && !changedProp; if (willDrop) { newField = null; } else if (willRevert) { newField = currentField; } else if (willFix) { newField = fixedField; } if (!isValid) { var showError = !isValid && !willFixAllErrors && !willDrop && !willRevert; var firstError = fieldErrors.find(function (e) { return !e.fixed && !e.ignore; }); if (showError && firstError) { newFieldError = (0, _i18n.translateValidation)(firstError); } // tip: even if we don't show errors, but revert LHS, put the reason of revert fieldErrors.map(function (e) { return validationErrors.push(_objectSpread(_objectSpread({ side: "lhs" }, e), {}, { fixed: e.fixed || willRevert || willDrop })); }); } } // compare old & new widgets for (var i = 0; i < operatorCardinality; i++) { var vs = currentValueSrc.get(i) || null; var currentWidget = (0, _configUtils.getWidgetForFieldOp)(oldConfig, currentField, currentOperator, vs); var newWidget = (0, _configUtils.getWidgetForFieldOp)(config, newField, newOperator, vs); // need to also check value widgets if we changed operator and current value source was 'field' // cause for select type op '=' requires single value and op 'in' requires array value var currentValueWidget = vs === "value" ? currentWidget : (0, _configUtils.getWidgetForFieldOp)(oldConfig, currentField, currentOperator, "value"); var newValueWidget = vs === "value" ? newWidget : (0, _configUtils.getWidgetForFieldOp)(config, newField, newOperator, "value"); var canReuseWidget = newValueWidget == currentValueWidget || (convertableWidgets[currentValueWidget] || []).includes(newValueWidget) || !currentValueWidget && isOkWithoutField; if (!canReuseWidget) { canReuseValue = false; } } if (currentOperator != newOperator && [currentOperator, newOperator].includes("proximity")) { canReuseValue = false; } var firstValueSrc = currentValueSrc.first(); var firstWidgetConfig = (0, _configUtils.getFieldWidgetConfig)(config, newField, newOperator, null, firstValueSrc); var valueSources = (0, _configUtils.getValueSourcesForFieldOp)(config, newField, newOperator, null); if (!newField && isOkWithoutField) { valueSources = Object.keys(config.settings.valueSourcesInfo); } var defaultValueSrc = valueSources[0]; var defaultValueType; if (operatorCardinality === 1 && firstWidgetConfig && firstWidgetConfig.type !== undefined) { defaultValueType = firstWidgetConfig.type; } else if (operatorCardinality === 1 && newFieldConfig && newFieldConfig.type !== undefined) { defaultValueType = newFieldConfig.type === "!group" ? "number" : newFieldConfig.type; } // changed operator from '==' to 'between' var canExtendValueToRange = canReuseValue && changedProp === "operator" && currentOperatorCardinality === 1 && operatorCardinality === 2; var valueFixes = []; var valueSrcFixes = []; var valueTypeFixes = []; var valueErrors = Array.from({ length: operatorCardinality }, function () { return null; }); if (canReuseValue) { var _loop = function _loop(_i) { var v = currentValue.get(_i); var vType = currentValueType.get(_i) || null; var vSrc = currentValueSrc.get(_i) || null; if (canExtendValueToRange && _i === 1) { v = valueFixes[0] !== undefined ? valueFixes[0] : currentValue.get(0); valueFixes[_i] = v; vType = currentValueType.get(0) || null; vSrc = currentValueSrc.get(0) || null; } var isValidSrc = vSrc ? valueSources.find(function (v) { return v == vSrc; }) !== undefined : true; var _validateValue3 = validateValue(config, newField, newField, newOperator, v, vType, vSrc, asyncListValues, canFix, isEndValue, canDropArgs), _validateValue4 = (0, _slicedToArray2["default"])(_validateValue3, 2), fixedValue = _validateValue4[0], allErrors = _validateValue4[1]; var isValid = !(allErrors !== null && allErrors !== void 0 && allErrors.length); // Allow bad value with error message // But not on field change - in that case just drop bad value that can't be reused // ? Maybe we should also drop bad value on op change? // For bad multiselect value we have both error message + fixed value. // If we show error message, it will gone on next tree validation var willFix = fixedValue !== v; var willFixAllErrors = !isValid && willFix && !(allErrors !== null && allErrors !== void 0 && allErrors.find(function (e) { return !e.fixed; })); var allErrorsHandled = !(allErrors !== null && allErrors !== void 0 && allErrors.find(function (e) { return !e.fixed && !e.ignore; })); // tip: is value src is invalid, drop ANYWAY // tip: Edge case in demo: // Given "login = LOWER(?)", change config to not show errors -> "LOWER(?)" will be dropped // We don't want to drop func completely, so need to add `allErrorsAheHandled` or `vSrc !== "func"` // todo: `hasFieldChanged` is not needed ? var willDrop = !isValidSrc || canFix && !isValid && !willFixAllErrors && (!allErrorsHandled || hasFieldChanged); if (!isValid) { // tip: even if we don't show errors, but drop bad values, put the reason of removal allErrors === null || allErrors === void 0 || allErrors.map(function (e) { return validationErrors.push(_objectSpread(_objectSpread({ side: "rhs", delta: _i }, e), {}, { fixed: e.fixed || willDrop })); }); } if (willDrop) { valueFixes[_i] = null; if (_i === 0) { delete valueFixes[1]; } } var showError = !isValid && !willFix; var firstError = allErrors === null || allErrors === void 0 ? void 0 : allErrors.find(function (e) { return !e.fixed && !e.ignore; }); if (showError && firstError) { valueErrors[_i] = (0, _i18n.translateValidation)(firstError); } if (willFix) { valueFixes[_i] = fixedValue; } if (canExtendValueToRange && _i === 0 && !isValid && !willFix) { // don't extend bad value to range canExtendValueToRange = false; } if (canExtendValueToRange && _i === 0 && ["func", "field"].includes(vSrc)) { // don't extend func/field value, only primitive value canExtendValueToRange = false; } }; for (var _i = 0; _i < operatorCardinality; _i++) { _loop(_i); } } // if can't reuse, get defaultValue if (!canReuseValue) { for (var _i2 = 0; _i2 < operatorCardinality; _i2++) { if (operatorCardinality === 1) { var _newFieldConfig$field, _dv$get; // tip: default range values (for cardinality > 1) are not supported yet, todo var dv = (0, _stuff.getFirstDefined)([newFieldConfig === null || newFieldConfig === void 0 ? void 0 : newFieldConfig.defaultValue, newFieldConfig === null || newFieldConfig === void 0 || (_newFieldConfig$field = newFieldConfig.fieldSettings) === null || _newFieldConfig$field === void 0 ? void 0 : _newFieldConfig$field.defaultValue, firstWidgetConfig === null || firstWidgetConfig === void 0 ? void 0 : firstWidgetConfig.defaultValue]); valueFixes[_i2] = dv; if (dv !== null && dv !== void 0 && dv.func || dv !== null && dv !== void 0 && (_dv$get = dv.get) !== null && _dv$get !== void 0 && _dv$get.call(dv, "func")) { valueSrcFixes[_i2] = "func"; //tip: defaultValue of src "field" is not supported, todo } } } } // set default valueSrc and valueType for (var _i3 = 0; _i3 < operatorCardinality; _i3++) { var _vs = canReuseValue && currentValueSrc.get(_i3) || null; var vt = canReuseValue && currentValueType.get(_i3) || null; var v = valueFixes[_i3] !== undefined ? valueFixes[_i3] : canReuseValue ? currentValue.get(_i3) : undefined; if (canReuseValue && canExtendValueToRange && _i3 === 1) { var _valueSrcFixes$_i, _valueTypeFixes$_i; _vs = (_valueSrcFixes$_i = valueSrcFixes[_i3]) !== null && _valueSrcFixes$_i !== void 0 ? _valueSrcFixes$_i : currentValueSrc.get(0); vt = (_valueTypeFixes$_i = valueTypeFixes[_i3]) !== null && _valueTypeFixes$_i !== void 0 ? _valueTypeFixes$_i : currentValueType.get(0); valueSrcFixes[_i3] = _vs; valueTypeFixes[_i3] = vt; } var isValidSrc = valueSources.includes(_vs); if (!isValidSrc) { valueSrcFixes[_i3] = defaultValueSrc; } if (!vt) { valueTypeFixes[_i3] = defaultValueType; } // Fix if func in LHS has `defaultValue: { func: ..., args: {...} }` if (v !== null && v !== void 0 && v.func) { valueFixes[_i3] = (0, _treeUtils.jsToImmutable)(v); valueSrcFixes[_i3] = "func"; } } // build new values var newValue = currentValue; if (valueFixes.length > 0 || !canReuseValue || operatorCardinality < currentOperatorCardinality) { newValue = new _immutable["default"].List(Array.from({ length: operatorCardinality }, function (_ignore, i) { return valueFixes[i] !== undefined ? valueFixes[i] : canReuseValue ? currentValue.get(i) : undefined; })); } var newValueSrc = currentValueSrc; if (valueSrcFixes.length > 0 || !canReuseValue || operatorCardinality < currentOperatorCardinality) { newValueSrc = new _immutable["default"].List(Array.from({ length: operatorCardinality }, function (_ignore, i) { var _valueSrcFixes$i; return (_valueSrcFixes$i = valueSrcFixes[i]) !== null && _valueSrcFixes$i !== void 0 ? _valueSrcFixes$i : canReuseValue && currentValueSrc.get(i) || null; })); } var newValueType = currentValueType; if (valueTypeFixes.length > 0 || !canReuseValue || operatorCardinality < currentOperatorCardinality) { newValueType = new _immutable["default"].List(Array.from({ length: operatorCardinality }, function (_ignore, i) { var _valueTypeFixes$i; return (_valueTypeFixes$i = valueTypeFixes[i]) !== null && _valueTypeFixes$i !== void 0 ? _valueTypeFixes$i : canReuseValue && currentValueType.get(i) || null; })); } // Validate range var rangeErrorObj = validateRange(config, newField, newOperator, newValue, newValueSrc); if (rangeErrorObj) { // last element in `valueError` list is for range validation error var rangeValidationError = (0, _i18n.translateValidation)(rangeErrorObj); var _willFix = canFix && operatorCardinality >= 2; var badValue = newValue; if (_willFix) { valueFixes[1] = newValue.get(0); newValue = newValue.set(1, valueFixes[1]); valueErrors[1] = valueErrors[0]; } var _showError = !_willFix; if (_showError) { valueErrors.push(rangeValidationError); } validationErrors.push(_objectSpread(_objectSpread({ side: "rhs", delta: -1 }, rangeErrorObj), {}, { fixed: _willFix, fixedFrom: _willFix ? [badValue.get(0), badValue.get(1)] : undefined, fixedTo: _willFix ? [newValue.get(0), newValue.get(1)] : undefined })); } var newValueError = currentValueError; var hasValueErrorChanged = (currentValueError === null || currentValueError === void 0 ? void 0 : currentValueError.size) !== valueErrors.length || valueErrors.filter(function (v, i) { return v != currentValueError.get(i); }).length > 0; if (hasValueErrorChanged) { newValueError = new _immutable["default"].List(valueErrors); } return { canReuseValue: canReuseValue, newValue: newValue, newValueSrc: newValueSrc, newValueType: newValueType, operatorCardinality: operatorCardinality, fixedField: newField, newValueError: newValueError, newFieldError: newFieldError, validationErrors: validationErrors }; };