@joyfill/conditional-logic
Version:
Conditional logic for forms
146 lines (133 loc) • 6.57 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.applyLogic = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _Logic = _interopRequireDefault(require("./constants/Logic"));
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; }
/**
* Apply visibility logic to items
*
* What does visibility logic mean? This means that
* items are either hidden or shown based on their
* default visibility status "hidden: true|false" or
* the resolved logic conditions that will change
* their visibility status to true or false.
*
* @param {Object_Array} items
* @param {Object_Array} fields
* @param {String} fieldLookupKey
*
* @returns {Object_Array} items
*/
var applyLogic = exports.applyLogic = function applyLogic(items, fields, fieldLookupKey) {
/**
* Create field value lookup for logic
*/
var fieldLookup = {};
fields.forEach(function (field) {
fieldLookup[field[fieldLookupKey]] = field;
});
var evaluatedItems = items.map(function (item) {
var nextItem = _objectSpread({}, item);
var hasLogic = item.logic && item.logic.action && item.logic.eval && item.logic.conditions && item.logic.conditions.length > 0;
/**
* Step 1: Show item (prevent hidden) if only one item exists
* - If only one item exists then we do not want to hide the item so we need to ensure hidden is false.
*/
if (items.length < 2) {
nextItem.hidden = false;
return nextItem;
}
/**
* Step 2: No logic exists
* - If no logic exists for the item then we should simply leave it as is
*/else if (!hasLogic) {
return nextItem;
}
/**
* Step 3: Has logic and has proper logic action paired with hidden status
* - If item is hidden and the logic that exists does not have a "show" action then we simply leave the item hidden.
* - If item is shown and the logic that exists does not have a "hide" action then we simply leave the item shown.
*/else if (hasLogic && (item.hidden && item.logic.action !== _Logic["default"].actions.show || !item.hidden && item.logic.action !== _Logic["default"].actions.hide)) {
return nextItem;
}
/**
* Step 4: Evaluate logic condition
*/
var matchingConditions = [];
var validConditions = item.logic.conditions.filter(function (condition) {
/**
* A condition is only valid if it has a undeleted page, undeleted field and condition.
* We do not check the value because that could be anything depending on what they're
* trying to match against.
*/
return fieldLookup[condition.field] && condition.condition;
});
validConditions.forEach(function (condition) {
var targetField = fieldLookup[condition.field];
/**
* Filled
* - Matches against any entered value and non-empty arrays.
*/
if (condition.condition === _Logic["default"].conditions.filled && (targetField.value && !Array.isArray(targetField.value) || targetField.value && Array.isArray(targetField.value) && targetField.value.length > 0)) {
return matchingConditions.push(condition);
}
/**
* Empty
* - Matches against empty string, undefined, null, or empty array.
*/
if (condition.condition === _Logic["default"].conditions.empty && (targetField.value === '' || targetField.value === undefined || Array.isArray(targetField.value) && targetField.value.length < 1)) {
return matchingConditions.push(condition);
}
/**
* Equals
* - Case-insenstive exact match
*/
if (condition.condition === _Logic["default"].conditions.equal && (!Array.isArray(targetField.value) && new RegExp("^".concat(condition.value, "$"), 'i').test(targetField.value) || Array.isArray(targetField.value) && targetField.value.indexOf(condition.value) !== -1)) {
return matchingConditions.push(condition);
}
/**
* Not Equals
* - Case-insenstive exact match
*/
if (condition.condition === _Logic["default"].conditions.notEqual && (!Array.isArray(targetField.value) && !new RegExp("^".concat(condition.value, "$"), 'i').test(targetField.value) || Array.isArray(targetField.value) && targetField.value.indexOf(condition.value) === -1)) {
return matchingConditions.push(condition);
}
/**
* Contains
* - Case-insenstive match anywhere in value
*/
if (condition.condition === _Logic["default"].conditions.contain && new RegExp(condition.value, 'gi').test(targetField.value)) {
return matchingConditions.push(condition);
}
/**
* Greater Than
*/
if (condition.condition === _Logic["default"].conditions.greaterThan && targetField.value > condition.value) {
return matchingConditions.push(condition);
}
/**
* Less Than
*/
if (condition.condition === _Logic["default"].conditions.lessThan && targetField.value < condition.value) {
return matchingConditions.push(condition);
}
});
/**
* Step 6: Match conditions against eval criteria
*/
var evalSuccess = false;
if (item.logic.eval === _Logic["default"].evals.or && matchingConditions.length > 0) evalSuccess = true;
if (item.logic.eval === _Logic["default"].evals.and && matchingConditions.length === validConditions.length) evalSuccess = true;
if (evalSuccess && item.logic.action === _Logic["default"].actions.show) nextItem.hidden = false;else if (evalSuccess && item.logic.action === _Logic["default"].actions.hide) nextItem.hidden = true;
return nextItem;
});
return evaluatedItems;
};
var _default = exports["default"] = {
applyLogic: applyLogic
};