UNPKG

dtable-utils

Version:

dtable common utils

472 lines (460 loc) 16.8 kB
import _typeof from '@babel/runtime/helpers/typeof'; import _classCallCheck from '@babel/runtime/helpers/classCallCheck'; import _createClass from '@babel/runtime/helpers/createClass'; import { CellType } from '../constants/cell-type.js'; import { COLLABORATOR_COLUMN_TYPES, DEPARTMENT_SELECT_RANGE_MAP } from '../constants/column.js'; import { FORMULA_COLUMN_TYPES_MAP, FORMULA_RESULT_TYPE } from '../constants/formula.js'; import { FILTER_ERR_MSG } from '../constants/filter/index.js'; import { getColumnOptions } from '../column/option.js'; import { isDateColumn } from '../column/date.js'; import { FILTER_PREDICATE_TYPE } from '../constants/filter/filter-predicate.js'; import { FILTER_TERM_MODIFIER_TYPE } from '../constants/filter/filter-modifier.js'; import { FILTER_COLUMN_OPTIONS } from '../constants/filter/filter-column-options.js'; import { filterTermModifierIsWithin, filterTermModifierNotWithin } from '../constants/filter/filter-is-within.js'; var TERM_TYPE_MAP = { NUMBER: 'number', STRING: 'string', BOOLEAN: 'boolean', ARRAY: 'array' }; var TEXT_COLUMN_TYPES = [CellType.TEXT, CellType.STRING]; var CHECK_EMPTY_PREDICATES = [FILTER_PREDICATE_TYPE.EMPTY, FILTER_PREDICATE_TYPE.NOT_EMPTY]; var PREDICATES_REQUIRE_ARRAY_TERM = [FILTER_PREDICATE_TYPE.IS_ANY_OF, FILTER_PREDICATE_TYPE.IS_NONE_OF]; var DATE_MODIFIERS_REQUIRE_TERM = [FILTER_TERM_MODIFIER_TYPE.NUMBER_OF_DAYS_AGO, FILTER_TERM_MODIFIER_TYPE.NUMBER_OF_DAYS_FROM_NOW, FILTER_TERM_MODIFIER_TYPE.THE_NEXT_NUMBERS_OF_DAYS, FILTER_TERM_MODIFIER_TYPE.THE_PAST_NUMBERS_OF_DAYS, FILTER_TERM_MODIFIER_TYPE.EXACT_DATE]; var MODIFIERS_REQUIRE_NUMERIC_TERM = [FILTER_TERM_MODIFIER_TYPE.NUMBER_OF_DAYS_AGO, FILTER_TERM_MODIFIER_TYPE.NUMBER_OF_DAYS_FROM_NOW, FILTER_TERM_MODIFIER_TYPE.THE_NEXT_NUMBERS_OF_DAYS, FILTER_TERM_MODIFIER_TYPE.THE_PAST_NUMBERS_OF_DAYS]; var ValidateFilter = /*#__PURE__*/function () { function ValidateFilter() { _classCallCheck(this, ValidateFilter); } return _createClass(ValidateFilter, null, [{ key: "validate", value: /** * Check filter is valid. The error_message from returns will be null if the filter is valid. * 1.incomplete filter which should be ignored * - column_key: required * - filter_predicate: required * - filter_term_modifier: determined by the column to filter with * - filter_term: determined by filter_predicate / the column to filter with * 2.illegal filter * - column missing: cannot find the column to filter * - column not support: the column to filter is not support * - mismatch: filter_predicate, filter_term_modifier mismatch * - wrong data type: filter_term with wrong data type * @param {object} filter e.g. { column_key, filter_term, ... } * @param {array} columns e.g. [{ key, name, ... }, ...] * @param {bool} isValidTerm No longer to validate filter term if false. default as false * @returns { error_message }, object */ function validate(filter, columns) { var isValidTerm = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var column_key = filter.column_key, filter_predicate = filter.filter_predicate, filter_term_modifier = filter.filter_term_modifier, filter_term = filter.filter_term; var _this$validateColumn = this.validateColumn(column_key, columns), column_error_message = _this$validateColumn.error_message; if (column_error_message) { return { error_message: column_error_message }; } var filterColumn = columns.find(function (column) { return column.key === column_key; }); var _this$validatePredica = this.validatePredicate(filter_predicate, filterColumn), predicate_error_message = _this$validatePredica.error_message; if (predicate_error_message) { return { error_message: predicate_error_message }; } if (this.isFilterOnlyWithPredicate(filter_predicate, filterColumn)) { return { error_message: null }; } var _this$validateModifie = this.validateModifier(filter_term_modifier, filter_predicate, filterColumn), modifier_error_message = _this$validateModifie.error_message; if (modifier_error_message) { return { error_message: modifier_error_message }; } if (this.isFilterOnlyWithModifier(filter_term_modifier, filterColumn)) { return { error_message: null }; } if (isValidTerm) { var _this$validateTerm = this.validateTerm(filter_term, filter_predicate, filter_term_modifier, filterColumn), term_error_message = _this$validateTerm.error_message; if (term_error_message) { return { error_message: term_error_message }; } } return { error_message: null }; } }, { key: "validateColumn", value: function validateColumn(column_key, columns) { if (!column_key) { return { error_message: FILTER_ERR_MSG.INCOMPLETE_FILTER }; } var filterColumn = columns.find(function (column) { return column.key === column_key; }); if (!filterColumn) { return { error_message: FILTER_ERR_MSG.COLUMN_MISSING }; } if (!this.isValidColumnType(filterColumn)) { return { error_message: FILTER_ERR_MSG.COLUMN_NOT_SUPPORTED }; } return { error_message: null }; } /** * the column to filter must be available */ }, { key: "validatePredicate", value: function validatePredicate(predicate, filterColumn) { if (!predicate) { return { error_message: FILTER_ERR_MSG.INCOMPLETE_FILTER }; } var columnType = filterColumn.type, data = filterColumn.data; var filterConfigs = FILTER_COLUMN_OPTIONS[columnType]; var predicateList = filterConfigs.filterPredicateList; if (FORMULA_COLUMN_TYPES_MAP[columnType] || columnType === CellType.LINK) { var result_type = data.result_type; if (result_type === FORMULA_RESULT_TYPE.ARRAY) { return this.validatePredicateWithArrayType(predicate, filterColumn); } return this.validatePredicate(predicate, { type: result_type }); } if (!predicateList.includes(predicate)) { return { error_message: FILTER_ERR_MSG.UNMATCHED_PREDICATE }; } return { error_message: null }; } }, { key: "validatePredicateWithArrayType", value: function validatePredicateWithArrayType(predicate, filterColumn) { var data = filterColumn.data; var array_type = data.array_type; // Only support: is if (array_type === CellType.CHECKBOX || array_type === CellType.BOOL) { return this.validatePredicate(predicate, { type: CellType.CHECKBOX }); } // Filter predicate should support: is_empty/is_not_empty(excludes checkbox and bool) if (CHECK_EMPTY_PREDICATES.includes(predicate)) { return true; } if (array_type === CellType.SINGLE_SELECT || array_type === CellType.DEPARTMENT_SINGLE_SELECT) { return this.validatePredicate(predicate, { type: CellType.MULTIPLE_SELECT }); } if (COLLABORATOR_COLUMN_TYPES.includes(array_type)) { return this.validatePredicate(predicate, { type: CellType.COLLABORATOR }); } return this.validatePredicate(predicate, { type: array_type }); } /** * filter predicate must be available. * filterColumn the column to filter must be available */ }, { key: "isFilterOnlyWithPredicate", value: function isFilterOnlyWithPredicate(predicate, filterColumn) { if (CHECK_EMPTY_PREDICATES.includes(predicate)) { return true; } var columnType = filterColumn.type, data = filterColumn.data; if (FORMULA_COLUMN_TYPES_MAP[columnType] || columnType === CellType.LINK) { var result_type = data.result_type, array_type = data.array_type; if (result_type === FORMULA_RESULT_TYPE.ARRAY) { return this.isFilterOnlyWithPredicate(predicate, { type: array_type }); } return this.isFilterOnlyWithPredicate(predicate, { type: result_type }); } var IS_CURRENT_USER_ID = FILTER_PREDICATE_TYPE.IS_CURRENT_USER_ID, INCLUDE_ME = FILTER_PREDICATE_TYPE.INCLUDE_ME; if (predicate === IS_CURRENT_USER_ID && TEXT_COLUMN_TYPES.includes(columnType)) { return true; } if (predicate === INCLUDE_ME && COLLABORATOR_COLUMN_TYPES.includes(columnType)) { return true; } return false; } /** * filter predicate must be available. * the column to filter must be available */ }, { key: "validateModifier", value: function validateModifier(modifier, predicate, filterColumn) { if (!isDateColumn(filterColumn)) { return { error_message: null }; } if (!modifier) { return { error_message: FILTER_ERR_MSG.INCOMPLETE_FILTER }; } if (predicate === FILTER_PREDICATE_TYPE.IS_WITHIN) { if (filterTermModifierIsWithin.includes(modifier)) { return { error_message: null }; } } else if (filterTermModifierNotWithin.includes(modifier)) { return { error_message: null }; } return { error_message: FILTER_ERR_MSG.UNMATCHED_MODIFIER }; } /** * filter predicate must be available. * filter modifier must be available. * the column to filter must be available */ }, { key: "isFilterOnlyWithModifier", value: function isFilterOnlyWithModifier(modifier, filterColumn) { if (isDateColumn(filterColumn)) { return !DATE_MODIFIERS_REQUIRE_TERM.includes(modifier); } return false; } }, { key: "validateTerm", value: function validateTerm(term, predicate, modifier, filterColumn) { if (this.isTermMissing(term)) { return { error_message: FILTER_ERR_MSG.INCOMPLETE_FILTER }; } if (!this.isValidTerm(term, predicate, modifier, filterColumn)) { return { error_message: FILTER_ERR_MSG.INVALID_TERM }; } return { error_message: null }; } }, { key: "isTermMissing", value: function isTermMissing(term) { return !term && term !== 0 && term !== false || Array.isArray(term) && term.length === 0; } }, { key: "isValidTerm", value: function isValidTerm(term, predicate, modifier, filterColumn) { switch (filterColumn.type) { case CellType.TEXT: case CellType.GEOLOCATION: case CellType.AUTO_NUMBER: case CellType.EMAIL: case CellType.URL: case CellType.STRING: { return this.isValidTermType(term, TERM_TYPE_MAP.STRING); } case CellType.SINGLE_SELECT: { var options = getColumnOptions(filterColumn); if (PREDICATES_REQUIRE_ARRAY_TERM.includes(predicate)) { if (!this.isValidTermType(term, TERM_TYPE_MAP.ARRAY)) { return false; } // contains deleted option(s) return this.isValidSelectedOptions(term, options); } if (!this.isValidTermType(term, TERM_TYPE_MAP.STRING)) { return false; } // invalid filter_term if selected option is deleted return !!options.find(function (option) { return term === option.id; }); } case CellType.NUMBER: case CellType.DURATION: case CellType.RATE: { return this.isValidTermType(term, TERM_TYPE_MAP.NUMBER); } case CellType.CHECKBOX: case CellType.BOOL: { return this.isValidTermType(term, TERM_TYPE_MAP.BOOLEAN); } case CellType.COLLABORATOR: case CellType.CREATOR: case CellType.LAST_MODIFIER: { return this.isValidTermType(term, TERM_TYPE_MAP.ARRAY); } case CellType.DEPARTMENT_SINGLE_SELECT: { if (PREDICATES_REQUIRE_ARRAY_TERM.includes(predicate)) { return this.isValidTermType(term, TERM_TYPE_MAP.ARRAY); } if ([DEPARTMENT_SELECT_RANGE_MAP.CURRENT_USER_DEPARTMENT, DEPARTMENT_SELECT_RANGE_MAP.CURRENT_USER_DEPARTMENT_AND_SUB].includes(term)) { return true; } return this.isValidTermType(term, TERM_TYPE_MAP.NUMBER); } case CellType.MULTIPLE_SELECT: { if (!this.isValidTermType(term, TERM_TYPE_MAP.ARRAY)) { return false; } // contains deleted option(s) var _options = getColumnOptions(filterColumn); return this.isValidSelectedOptions(term, _options); } case CellType.DATE: case CellType.CTIME: case CellType.MTIME: { if (MODIFIERS_REQUIRE_NUMERIC_TERM.includes(modifier)) { return this.isValidTermType(term, TERM_TYPE_MAP.NUMBER); } return this.isValidTermType(term, TERM_TYPE_MAP.STRING); } case CellType.FORMULA: case CellType.LINK_FORMULA: { var data = filterColumn.data; var result_type = data.result_type; if (result_type === FORMULA_RESULT_TYPE.ARRAY) { return this.isValidTermWithArrayType(term, predicate, modifier, filterColumn); } return this.isValidTerm(term, predicate, modifier, { type: result_type }); } case CellType.LINK: { return this.isValidTermWithArrayType(term, predicate, modifier, filterColumn); } default: { return false; } } } }, { key: "isValidTermType", value: function isValidTermType(term, type) { if (type === TERM_TYPE_MAP.ARRAY) { return Array.isArray(term) && term.length > 0; } if (type === CellType.NUMBER) { // is a number or a number string // eslint-disable-next-line return _typeof(term) === type || !isNaN(Number(term)); } // eslint-disable-next-line return _typeof(term) === type; } }, { key: "isValidTermWithArrayType", value: function isValidTermWithArrayType(term, predicate, modifier, filterColumn) { var data = filterColumn.data; var array_type = data.array_type, array_data = data.array_data; if (array_type === CellType.SINGLE_SELECT) { return this.isValidTerm(term, predicate, modifier, { type: CellType.MULTIPLE_SELECT, data: array_data }); } if (array_type === CellType.DEPARTMENT_SINGLE_SELECT) { return this.isValidTermType(term, TERM_TYPE_MAP.ARRAY); } if (COLLABORATOR_COLUMN_TYPES.includes(array_type)) { return this.isValidTerm(term, predicate, modifier, { type: CellType.COLLABORATOR }); } return this.isValidTerm(term, predicate, modifier, { type: array_type, data: array_data }); } }, { key: "isValidColumnType", value: function isValidColumnType(filterColumn) { var columnType = filterColumn.type, data = filterColumn.data; if (FORMULA_COLUMN_TYPES_MAP[columnType] || columnType === CellType.LINK) { if (!data) { return false; } var result_type = data.result_type, array_type = data.array_type; if (result_type === FORMULA_RESULT_TYPE.ARRAY) { return this.isValidColumnType({ type: array_type }); } return this.isValidColumnType({ type: result_type }); } // eslint-disable-next-line return FILTER_COLUMN_OPTIONS.hasOwnProperty(columnType); } }, { key: "isValidSelectedOptions", value: function isValidSelectedOptions(selectedOptionIds, options) { var validSelectedOptions = options.filter(function (option) { return selectedOptionIds.includes(option.id); }); return selectedOptionIds.length === validSelectedOptions.length; } }]); }(); export { DATE_MODIFIERS_REQUIRE_TERM, ValidateFilter };