APIs

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

import Mixin from '@ember/object/mixin';
import { assert } from '@ember/debug';
import { on } from '@ember/object/evented';
import { set, computed, observer } from '@ember/object';
import { once } from '@ember/runloop';
import { inject as service } from '@ember/service';
import Builder from 'ember-flexberry-data/query/builder';
import PredicateFromFiltersMixin from '../mixins/predicate-from-filters';
import deserializeSortingParam from '../utils/deserialize-sorting-param';

/**
  Mixin for edit-form-controller for ObjectListView support.

  @class FlexberryObjectlistviewOnEditFormControllerMixin
  @extends Mixin
  @uses PredicateFromFiltersMixin
  @public
*/
export default Mixin.create(PredicateFromFiltersMixin, {
  /**
    Name of related to FOLV edit form route.

    @property folvEditFormRoute
    @type String
    @default undefined
   */
  folvEditFormRoute: undefined,

  /**
    Name of FOLV model.

    @property folvModelName
    @type String
    @default undefined
   */
  folvModelName: undefined,

  /**
    Name of FOLV projection.

    @property folvProjection
    @type String
    @default undefined
   */
  folvProjection: undefined,

  /**
    Result predicate with all restrictions for olv.

    @property resultPredicate
    @type BasePredicate
    @default null
   */
  resultPredicate: null,

  /**
    Service for managing the state of the application.

    @property appState
    @type AppStateService
  */
  appState: service(),

  /**
    Total count of FOLV records.

    @property recordsTotalCount
    @type Number
    @readOnly
  */
  recordsTotalCount: computed('customFolvContent', function() {
    return this.get('customFolvContent.meta.count');
  }),

  /**
    Content of FOLV on this edit form.

    @property customFolvContent
    @type Promise
    @readOnly
  */
  customFolvContentObserver: observer('model', 'perPage', 'page', 'sorting', 'filter', 'filters', function() {
    if (this.get('folvModelName') && this.get('folvProjection')) {
      // https://github.com/emberjs/ember.js/issues/15479
      once(this, 'getCustomContent');
    }
  }),

  getCustomContent() {
    let _this = this;
    let folvModelName = this.get('folvModelName');
    let folvProjection = this.get('folvProjection');
    let filtersPredicate = this._filtersPredicate();
    let perPage = this.get('perPage');
    let page = this.get('page');
    let sorting = this.get('sorting');
    let filter = this.get('filter');
    let filterCondition = this.get('filterCondition');
    let filterProjectionName = this.get('filterProjectionName');
    let hierarchicalAttribute;
    if (this.get('inHierarchicalMode')) {
      hierarchicalAttribute = this.get('hierarchicalAttribute');
    }

    let params = {};
    params.perPage = perPage;
    params.page = page;
    params.sorting = sorting;
    params.filter = filter;
    params.filterCondition = filterCondition;
    let limitPredicate =
      this.objectListViewLimitPredicate({ modelName: folvModelName, projectionName: folvProjection, params: params });
    if (folvModelName && folvProjection) {
      let queryParameters = {
        modelName: folvModelName,
        projectionName: folvProjection,
        perPage: perPage,
        page: page,
        sorting: sorting,
        filter: filter,
        filterCondition: filterCondition,
        filters: filtersPredicate,
        filterProjectionName: filterProjectionName,
        predicate: limitPredicate,
        hierarchicalAttribute: hierarchicalAttribute,
      };
      return this.reloadList(queryParameters)
      .then(records => {
        _this.set('customFolvContent', records);
      })
      .catch(reason => {
        _this.send('handleError', reason);
      })
      .finally(() => {
        this.get('appState').reset();
      });
    }

    _this.set('customFolvContent', undefined);
  },

  customFolvContent: undefined,

  sort: undefined,

  sorting: [],

  sortObserver: on('init', observer('sort', function() {
    let sorting = this.get('sort');

    if (sorting) {
      sorting = deserializeSortingParam(sorting);
    }

    this.set('sorting', sorting || []);
  })),

  /**
    Dictionary with sorting data related to properties.

    @property computedSorting
    @type Object
    @readOnly
  */
  computedSorting: computed('sorting', function() {
    let sorting = this.get('sorting');
    let result = {};

    if (sorting) {
      for (let i = 0; i < sorting.length; i++) {
        let propName = sorting[i].propName;
        let sortDef = {
          sortAscending: sorting[i].direction === 'asc' ? true : false,
          sortNumber: i + 1
        };
        result[propName] = sortDef;
      }
    }

    return result;
  }),

  /**
    It forms the limit predicate for FOLV loaded data on edit form.

    By default it returns `undefined`.
    In order to set specific limit predicate, this method have to be overriden on applied-specific controller.

  @method objectListViewLimitPredicate
  @public

  @param {Object} options Method options
  @param {String} [options.modelName] Type of records to load
  @param {String} [options.projectionName] Projection name to load data by
  @param {String} [options.params] Current route query parameters
  @return {BasePredicate} The predicate to limit loaded data
  */
  /* eslint-disable no-unused-vars */
  objectListViewLimitPredicate(options) {
    return undefined;
  },
  /* eslint-enable no-unused-vars */

  actions: {
    /**
      Set in `property` for `target` promise that load nested records.

      @method actions.loadRecordsById
      @param {String} id Record ID.
      @param {ObjectListViewRowComponent} Instance of {{#crossLink "ObjectListViewRowComponent"}}{{/crossLink}}.
      @param {String} property Property name into {{#crossLink "ObjectListViewRowComponent"}}{{/crossLink}}.
    */
    loadRecordsById(id, target, property) {
      let hierarchicalAttribute = this.get('hierarchicalAttribute');
      let modelName = this.get('folvModelName');
      let projectionName = this.get('folvProjection');
      let builder = new Builder(this.store)
        .from(modelName)
        .selectByProjection(projectionName)
        .where(hierarchicalAttribute, 'eq', id);

      set(target, property, this.store.query(modelName, builder.build()));
    },

    /**
      Switch hierarchical mode.

      @method actions.switchHierarchicalMode
    */
    switchHierarchicalMode() {
      this.toggleProperty('inHierarchicalMode');
      this.getCustomContent();
    },

    /**
      Hook that executes before deleting all records on all pages.
      Need to be overriden in corresponding application controller.

      @method actions.beforeDeleteAllRecords
    */
    beforeDeleteAllRecords(modelName, data) {
      data.cancel = true;
      assert(`Please specify 'beforeDeleteAllRecords' action for '${this.componentName}' list compoenent in corresponding controller`);
    }
  },
});