APIs

Show:
/**
  @module ember-flexberry
*/

import { set } from '@ember/object';
import { getOwner } from '@ember/application';
import { isNone } from '@ember/utils';
import moment from 'moment';

import {
  SimplePredicate,
  StringPredicate,
  DatePredicate,
  NotPredicate
} from 'ember-flexberry-data/query/predicate';

/**
  Builds predicate for filter

  @example
    ```javascript
    import { predicateForFilter } from 'ember-flexberry/utils/filter'
    predicateForFilter(filter)
    ```

  @method predicateForFilter
  @param {Object} filter Object (`{ name, condition, pattern }`) with parameters for filter.
  @return {BasePredicate|null} Predicate to filter through.
*/
let predicateForFilter = function (filter) {
  let owner = getOwner(this);

  if (filter.condition) {
    switch (filter.type) {
      case 'string':
        switch (filter.condition) {
          case 'like':
            return new StringPredicate(filter.name).contains(filter.pattern || '');
          case 'nlike':
            return new NotPredicate(new StringPredicate(filter.name).contains(filter.pattern || ''));
          default:
            return new SimplePredicate(filter.name, filter.condition, filter.pattern || null);
        }

      case 'boolean':
        switch (filter.condition) {
          case 'empty':
            return new SimplePredicate(filter.name, 'eq', null);
          case 'nempty':
            return new SimplePredicate(filter.name, 'neq', null);
          default:
            return new SimplePredicate(filter.name, filter.condition, filter.pattern);
        }

      case 'number':
        if (filter.condition === 'between') {
          if (!filter.pattern) {
            return new SimplePredicate(filter.name, filter.condition, null);
          } else {
            let [from, to] = filter.pattern.split('|');
            let isNumber = (s) => Number(s) === Number(s) && s;
            if (isNumber(from) && isNumber(to)) {
              return new SimplePredicate(filter.name, 'geq', Number(from)).and(
                new SimplePredicate(filter.name, 'leq', Number(to))
              );
            } else if (isNumber(from)) {
              return new SimplePredicate(filter.name, 'leq', Number(to));
            } else if (isNumber(to)) {
              return new SimplePredicate(filter.name, 'geq', Number(from));
            } else {
              return null;
            }
          }
        } else {
          return new SimplePredicate(filter.name, filter.condition, filter.pattern ? Number(filter.pattern) : null);
        }

      case 'decimal':
        if (filter.condition === 'between') {
          if (!filter.pattern) {
            return new SimplePredicate(filter.name, filter.condition, null);
          } else {
            let [from, to] = filter.pattern.split('|');
            let isNumber = (s) => Number(s) === Number(s) && s;
            if (isNumber(from) && isNumber(to)) {
              return new SimplePredicate(filter.name, 'geq', Number(from)).and(
                new SimplePredicate(filter.name, 'leq', Number(to))
              );
            } else if (isNumber(from)) {
              return new SimplePredicate(filter.name, 'leq', Number(to));
            } else if (isNumber(to)) {
              return new SimplePredicate(filter.name, 'geq', Number(from));
            } else {
              return null;
            }
          }
        } else {
          return new SimplePredicate(filter.name, filter.condition, filter.pattern ? Number(filter.pattern) : null);
        }

      case 'date':
        if (filter.condition === 'between' && filter.pattern) {
          const [from, to] = filter.pattern.split('|');
          const fromIsValid = moment(from).isValid();
          const toIsValid = moment(to).isValid();
          if (fromIsValid && toIsValid) {
            return new DatePredicate(filter.name, 'geq', from).and(
              new DatePredicate(filter.name, 'leq', to)
            );
          } else if (fromIsValid) {
            return new DatePredicate(filter.name, 'leq', to);
          } else if (toIsValid) {
            return new DatePredicate(filter.name, 'geq', from);
          } else {
            return null;
          }
        }
  
        return filter.pattern ?
          new DatePredicate(filter.name, filter.condition, filter.pattern, true) :
          new SimplePredicate(filter.name, filter.condition, null);
      default: {
        let transformInstance = owner.lookup('transform:' + filter.type);
        let transformClass = !isNone(transformInstance) ? transformInstance.constructor : null;

        if (transformClass && transformClass.predicateForFilter) {
          return transformClass.predicateForFilter(filter);
        }

        return null;
      }
    }
  } else if (filter.pattern) {
    switch (filter.type) {
      case 'string':
        set(filter, 'condition', 'like');
        return new StringPredicate(filter.name).contains(filter.pattern);
      case 'date':
        set(filter, 'condition', 'eq');
        return new DatePredicate(filter.name, filter.condition, filter.pattern, true);
      default:
        return null;
    }
  }

  return null;
};

export {
  predicateForFilter
};