UNPKG

@react-awesome-query-builder/core

Version:
420 lines (406 loc) 18.2 kB
import _typeof from "@babel/runtime/helpers/typeof"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import Immutable from "immutable"; import { getFieldConfig, getOperatorConfig, getFieldWidgetConfig, getFieldRawConfig, getFuncConfig, getFieldParts, isFieldDescendantOfField, _getFromConfigCache, _saveToConfigCache, _getWidgetsAndSrcsForFieldOp, filterValueSourcesForField } from "./configUtils"; import { isObject } from "./stuff"; import last from "lodash/last"; export var calculateValueType = function calculateValueType(value, valueSrc, config) { var calculatedValueType = null; if (value) { if (valueSrc === "field") { var fieldConfig = getFieldConfig(config, value); if (fieldConfig) { calculatedValueType = fieldConfig.type; } } else if (valueSrc === "func") { var funcKey = value.get("func"); if (funcKey) { var funcConfig = getFuncConfig(config, funcKey); if (funcConfig) { calculatedValueType = funcConfig.returnType || funcConfig.type; } } } } return calculatedValueType; }; export var getFuncPathLabels = function getFuncPathLabels(field, config) { var parentField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; return getFieldPathLabels(field, config, parentField, "funcs", "subfields"); }; export var getFieldPathLabels = function getFieldPathLabels(field, config) { var parentField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var fieldsKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "fields"; var subfieldsKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : "subfields"; if (!field) return null; var fieldSeparator = config.settings.fieldSeparator; var parts = getFieldParts(field, config); var parentParts = getFieldParts(parentField, config); var res = parts.slice(parentParts.length).map(function (_curr, ind, arr) { return arr.slice(0, ind + 1); }).map(function (parts) { return [].concat(_toConsumableArray(parentParts), _toConsumableArray(parts)).join(fieldSeparator); }).map(function (part) { var cnf = getFieldRawConfig(config, part, fieldsKey, subfieldsKey); return cnf && cnf.label || last(part.split(fieldSeparator)); }).filter(function (label) { return label != null; }); return res; }; export var getValueLabel = function getValueLabel(config, field, operator, delta) { var valueSrc = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var isSpecialRange = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; // const isFuncArg = field && typeof field == "object" && !!field.func && !!field.arg; // const {showLabels} = config.settings; // const fieldConfig = getFieldConfig(config, field); var fieldWidgetConfig = getFieldWidgetConfig(config, field, operator, null, valueSrc) || {}; var mergedOpConfig = getOperatorConfig(config, operator, field) || {}; var cardinality = isSpecialRange ? 1 : mergedOpConfig.cardinality; var ret = null; if (cardinality > 1) { var valueLabels = fieldWidgetConfig.valueLabels || mergedOpConfig.valueLabels; if (valueLabels) ret = valueLabels[delta]; if (ret && _typeof(ret) !== "object") { ret = { label: ret, placeholder: ret }; } if (!ret) { ret = { label: config.settings.valueLabel + " " + (delta + 1), placeholder: config.settings.valuePlaceholder + " " + (delta + 1) }; } } else { var label = fieldWidgetConfig.valueLabel; var placeholder = fieldWidgetConfig.valuePlaceholder; // tip: this logic moved to extendFieldConfig(), see comment "label for func arg" // if (isFuncArg) { // if (!label) // label = fieldConfig.label || field.arg; // if (!placeholder && !showLabels) // placeholder = fieldConfig.label || field.arg; // } ret = { label: label || config.settings.valueLabel, placeholder: placeholder || config.settings.valuePlaceholder }; } return ret; }; // can use alias (fieldName) // even if `parentField` is provided, `field` is still a full path export var formatFieldName = function formatFieldName(field, config, meta) { var parentField = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; if (!field) return; var fieldDef = getFieldConfig(config, field) || {}; var fieldSeparator = config.settings.fieldSeparator; var fieldParts = getFieldParts(field, config); var fieldName = Array.isArray(field) ? field.join(fieldSeparator) : field; if (options !== null && options !== void 0 && options.useTableName && fieldDef.tableName) { // legacy var fieldPartsCopy = _toConsumableArray(fieldParts); fieldPartsCopy[0] = fieldDef.tableName; fieldName = fieldPartsCopy.join(fieldSeparator); } if (fieldDef.fieldName) { fieldName = fieldDef.fieldName; } if (parentField) { var parentFieldDef = getFieldConfig(config, parentField) || {}; var parentFieldName = parentField; if (fieldName.indexOf(parentFieldName + fieldSeparator) == 0) { fieldName = fieldName.slice((parentFieldName + fieldSeparator).length); // fieldName = "#this." + fieldName; // ? for spel } else { if (fieldDef.fieldName) { // ignore } else { meta.errors.push("Can't cut group ".concat(parentFieldName, " from field ").concat(fieldName)); } } } return fieldName; }; /** * Used together with keepInputOnChangeFieldSrc */ export var isEmptyItem = function isEmptyItem(item, config) { var type = item.get("type"); var mode = item.getIn(["properties", "mode"]); if (type == "rule_group" && mode == "array") { return isEmptyRuleGroupExt(item, config); } else if (type == "group" || type == "rule_group") { return isEmptyGroup(item, config); } else { return isEmptyRule(item, config); } }; var isEmptyRuleGroupExt = function isEmptyRuleGroupExt(item, config) { var children = item.get("children1"); var properties = item.get("properties"); return isEmptyRuleGroupExtPropertiesAndChildren(properties.toObject(), children, config); }; /** * Used to remove group ext without confirmation * * If group operator is count, children can be empty. * If group operator is some/none/all, there should be at least one non-empty (even incomplete) child. */ export var isEmptyRuleGroupExtPropertiesAndChildren = function isEmptyRuleGroupExtPropertiesAndChildren(properties, children, config) { var _config$operators$ope, _config$operators$ope2; var operator = properties.operator; var cardinality = (_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; var childrenAreRequired = cardinality == 0; // tip: for group operators some/none/all var filledParts = { group: !isEmptyRuleProperties(properties, config), children: !isEmptyGroupChildren(children, config) }; var hasEnough = filledParts.group && (childrenAreRequired ? filledParts.children : true); return !hasEnough; }; var isEmptyGroup = function isEmptyGroup(group, config) { var children = group.get("children1"); return isEmptyGroupChildren(children, config); }; /** * Used to remove group without confirmation * @returns {boolean} false if there is at least one (even incomplete) child */ export var isEmptyGroupChildren = function isEmptyGroupChildren(children, config) { var hasEnough = (children === null || children === void 0 ? void 0 : children.size) > 0 && children.filter(function (ch) { return !isEmptyItem(ch, config); }).size > 0; return !hasEnough; }; var isEmptyRule = function isEmptyRule(rule, config) { var properties = rule.get("properties"); return isEmptyRuleProperties((properties === null || properties === void 0 ? void 0 : properties.toObject()) || {}, config); }; /** * Used to remove rule without confirmation * @param properties is an Object, but properties (like value) are Immutable * @returns {boolean} true if there is no enough data in rule */ export var isEmptyRuleProperties = function isEmptyRuleProperties(properties, config) { var liteCheck = true; var scoreThreshold = 3; var compl = whatRulePropertiesAreCompleted(properties, config, liteCheck); var hasEnough = compl.score >= scoreThreshold; return !hasEnough; }; /** * Used to validate rule * @param properties is an Object, but its properties (like `value`) are Immutable * @param liteCheck true can be used to check that rule has enough data to ask confirmation before delete * @return {{parts: {field: boolean, operator: boolean, value: boolean}, score: number}} */ export var whatRulePropertiesAreCompleted = function whatRulePropertiesAreCompleted(_ref, config) { var _config$operators$ope3, _config$operators$ope4, _value$filter; var field = _ref.field, fieldSrc = _ref.fieldSrc, fieldType = _ref.fieldType, operator = _ref.operator, value = _ref.value, valueSrc = _ref.valueSrc, valueType = _ref.valueType; var liteCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var cardinality = (_config$operators$ope3 = (_config$operators$ope4 = config.operators[operator]) === null || _config$operators$ope4 === void 0 ? void 0 : _config$operators$ope4.cardinality) !== null && _config$operators$ope3 !== void 0 ? _config$operators$ope3 : 1; var valueSrcs = valueSrc !== null && valueSrc !== void 0 && valueSrc.get ? valueSrc.toJS() : valueSrc; // tip: for liteCheck==true `score` should equal 3 if both LHS and RHS are at least partially filled var res = { parts: {}, score: 0 }; res.parts.field = liteCheck ? field != null : _isCompletedValue(field, fieldSrc, config); res.parts.operator = !!operator; res.parts.value = (value === null || value === void 0 || (_value$filter = value.filter(function (val, delta) { return _isCompletedValue(val, valueSrcs === null || valueSrcs === void 0 ? void 0 : valueSrcs[delta], config, liteCheck); })) === null || _value$filter === void 0 ? void 0 : _value$filter.size) >= (liteCheck ? Math.min(cardinality, 1) : cardinality); res.score = Object.keys(res.parts).filter(function (k) { return !!res.parts[k]; }).length; if (liteCheck && res.score < 3) { // Boost score to confirm deletion: // - if RHS is empty, but LHS is a completed function // - if LHS is empty (only fieldType is set), but there is a completed function in RHS var deepCheck = true; if (!res.parts.value && fieldSrc === "func" && _isCompletedValue(field, fieldSrc, config, false, deepCheck)) { res.score++; } if (!res.parts.field) { value === null || value === void 0 || value.map(function (val, delta) { if ((valueSrcs === null || valueSrcs === void 0 ? void 0 : valueSrcs[delta]) === "func" && _isCompletedValue(val, valueSrcs === null || valueSrcs === void 0 ? void 0 : valueSrcs[delta], config, false, deepCheck)) { res.score++; } }); } } return res; }; var _isCompletedValue = function isCompletedValue(value, valueSrc, config) { var liteCheck = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; var deepCheck = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; if (!liteCheck && valueSrc == "func" && value) { var _value$get; var funcKey = (_value$get = value.get) === null || _value$get === void 0 ? void 0 : _value$get.call(value, "func"); var funcConfig = getFuncConfig(config, funcKey); if (funcConfig) { var args = value.get("args"); for (var argKey in funcConfig.args) { var argConfig = funcConfig.args[argKey]; var argVal = args ? args.get(argKey) : undefined; // const argDef = getFieldConfig(config, argConfig); var argValue = argVal ? argVal.get("value") : undefined; var argValueSrc = argVal ? argVal.get("valueSrc") : undefined; if (argValue == undefined && (argConfig === null || argConfig === void 0 ? void 0 : argConfig.defaultValue) === undefined && !(argConfig !== null && argConfig !== void 0 && argConfig.isOptional)) { // arg is not completed return false; } if (argValue != undefined) { if (!_isCompletedValue(argValue, argValueSrc, config, deepCheck ? liteCheck : true)) { // arg is complex and is not completed return false; } } } // all args are completed return true; } } return value != undefined; }; /** * @param {*} value * @param {'value'|'field'|'func'} valueSrc * @param {object} config * @return {* | undefined} undefined if func value is not complete (missing required arg vals); can return completed value != value */ export var completeValue = function completeValue(value, valueSrc, config) { if (valueSrc == "func") return completeFuncValue(value, config);else return value; }; /** * @param {Immutable.Map} value * @param {object} config * @return {Immutable.Map | undefined} - undefined if func value is not complete (missing required arg vals); can return completed value != value */ export var completeFuncValue = function completeFuncValue(value, config) { if (!value) return undefined; var funcKey = value.get("func"); var funcConfig = funcKey && getFuncConfig(config, funcKey); if (!funcConfig) return undefined; var complValue = value; var tmpHasOptional = false; for (var argKey in funcConfig.args) { var argConfig = funcConfig.args[argKey]; var valueSources = argConfig.valueSources, isOptional = argConfig.isOptional, defaultValue = argConfig.defaultValue; var filteredValueSources = filterValueSourcesForField(config, valueSources, argConfig); var args = complValue.get("args"); var argDefaultValueSrc = filteredValueSources.length == 1 ? filteredValueSources[0] : undefined; var argVal = args ? args.get(argKey) : undefined; var argValue = argVal ? argVal.get("value") : undefined; var argValueSrc = (argVal ? argVal.get("valueSrc") : undefined) || argDefaultValueSrc; if (argValue !== undefined) { var completeArgValue = completeValue(argValue, argValueSrc, config); if (completeArgValue === undefined) { return undefined; } else if (completeArgValue !== argValue) { complValue = complValue.setIn(["args", argKey, "value"], completeArgValue); } if (tmpHasOptional) { // has gap return undefined; } } else if (defaultValue !== undefined && !isObject(defaultValue)) { complValue = complValue.setIn(["args", argKey, "value"], getDefaultArgValue(argConfig)); complValue = complValue.setIn(["args", argKey, "valueSrc"], "value"); } else if (isOptional) { // optional tmpHasOptional = true; } else { // missing value return undefined; } } return complValue; }; // item - Immutable var _getOneChildOrDescendant = function getOneChildOrDescendant(item) { var children = item.get("children1"); if ((children === null || children === void 0 ? void 0 : children.size) == 1) { var child = children.first(); var childType = child.get("type"); if (childType === "group") { return _getOneChildOrDescendant(child); } return child; } return null; }; ///// Func utils export { _getOneChildOrDescendant as getOneChildOrDescendant }; export var getDefaultArgValue = function getDefaultArgValue(_ref2) { var value = _ref2.defaultValue; if (isObject(value) && !Immutable.Map.isMap(value) && value.func) { return Immutable.fromJS(value, function (k, v) { return Immutable.Iterable.isIndexed(v) ? v.toList() : v.toOrderedMap(); }); } return value; }; /** * Used @ FuncWidget * @param {Immutable.Map} value * @param {string} argKey * @param {*} argVal * @param {object} argConfig */ export var setArgValue = function setArgValue(value, argKey, argVal, argConfig, config) { if (value && value.get("func")) { value = value.setIn(["args", argKey, "value"], argVal); // set default arg value source var valueSrc = value.getIn(["args", argKey, "valueSrc"]); var valueSources = argConfig.valueSources; var filteredValueSources = filterValueSourcesForField(config, valueSources, argConfig); var argDefaultValueSrc = filteredValueSources.length == 1 ? filteredValueSources[0] : undefined; if (!argDefaultValueSrc && filteredValueSources.includes("value")) { argDefaultValueSrc = "value"; } if (!valueSrc && argDefaultValueSrc) { value = value.setIn(["args", argKey, "valueSrc"], argDefaultValueSrc); } } return value; }; export var setFuncDefaultArgs = function setFuncDefaultArgs(config, funcValue, funcConfig) { if (funcConfig) { for (var argKey in funcConfig.args) { funcValue = setFuncDefaultArg(config, funcValue, funcConfig, argKey); } } return funcValue; }; export var setFuncDefaultArg = function setFuncDefaultArg(config, funcValue, funcConfig, argKey) { var argConfig = funcConfig.args[argKey]; var valueSources = argConfig.valueSources, defaultValue = argConfig.defaultValue; var filteredValueSources = filterValueSourcesForField(config, valueSources, argConfig); var firstValueSrc = filteredValueSources.length ? filteredValueSources[0] : undefined; var defaultValueSrc = defaultValue ? isObject(defaultValue) && !!defaultValue.func ? "func" : "value" : undefined; var argDefaultValueSrc = defaultValueSrc || firstValueSrc; var hasValue = funcValue.getIn(["args", argKey]); if (!hasValue) { if (defaultValue !== undefined) { funcValue = funcValue.setIn(["args", argKey, "value"], getDefaultArgValue(argConfig)); } if (argDefaultValueSrc) { funcValue = funcValue.setIn(["args", argKey, "valueSrc"], argDefaultValueSrc); } } return funcValue; };