APIs

Show:
import Mixin from '@ember/object/mixin';
import $ from 'jquery';
import { inject as service } from '@ember/service';
import { merge } from '@ember/polyfills';
import { later } from '@ember/runloop';

import needSaveCurrentAgregator from '../utils/need-save-current-agregator';

/**
  Mixin for {{#crossLink "DS.Route"}}Route{{/crossLink}}
  to support work with {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.

  @class FlexberryGroupeditRouteMixin
  @extends Mixin
  @public
*/
export default Mixin.create({
  /**
    Service that triggers {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}} events.

    @private
    @property _groupEditEventsService
    @readOnly
    @type Service
    @default ObjectlistviewEventsService
  */
  _groupEditEventsService: service('objectlistview-events'),

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

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

  /**
    Service that lets interact between agregator's and detail's form.

    @property flexberryDetailInteractionService
    @readOnly
    @type Service
    @default DetailInteractionService
  */
  flexberryDetailInteractionService: service('detail-interaction'),

  actions: {
    /**
      {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}} row click handler.
      It sets `modelNoRollBack` to `true` at current controller, redirects to detail's route, save necessary data to service.

      @method actions.groupEditRowClick
      @param {EmberObject} record Record related to clicked table row.
      @param {Object} [options] Record related to clicked table row.
      @param {Boolean} options.saveBeforeRouteLeave Flag: indicates whether to save current model before going to the detail's route.
      @param {Boolean} options.editOnSeparateRoute Flag: indicates whether to edit detail on separate route.
      @param {String} options.modelName Clicked detail model name (used to create record if record is undefined).
      @param {Array} options.detailArray Current detail array (used to add record to if record is undefined).
      @param {Boolean} options.editFormRoute Path to detail's form.
    */
    groupEditRowClick(record, options) {
      let methodOptions = {
        saveBeforeRouteLeave: false,
        editOnSeparateRoute: false,
        modelName: undefined,
        detailArray: undefined,
        editFormRoute: undefined,
        readonly: false
      };
      methodOptions = merge(methodOptions, options);
      let editOnSeparateRoute = methodOptions.editOnSeparateRoute;
      let saveBeforeRouteLeave = methodOptions.saveBeforeRouteLeave;

      if (!editOnSeparateRoute) {
        return;
      }

      let _this = this;
      let editFormRoute = methodOptions.editFormRoute;
      if (!editFormRoute) {
        throw new Error('Detail\'s edit form route is undefined.');
      }

      this.get('appState').loading();

      let goToOtherRouteFunction = function() {
        if (!record)
        {
          let modelName = methodOptions.modelName;
          if (!modelName) {
            throw new Error('Detail\'s model name is undefined.');
          }

          let detailArray = methodOptions.detailArray;
          var modelToAdd = _this.store.createRecord(modelName, {});
          detailArray.addObject(modelToAdd);
          record = modelToAdd;
        }

        _this.controller.set('modelNoRollBack', true);

        let flexberryDetailInteractionService = _this.get('flexberryDetailInteractionService');
        flexberryDetailInteractionService.pushValue(
          'modelCurrentAgregatorPathes', _this.controller.get('modelCurrentAgregatorPathes'), _this.get('router.url'));
        flexberryDetailInteractionService.set('modelSelectedDetail', record);
        flexberryDetailInteractionService.set('saveBeforeRouteLeave', saveBeforeRouteLeave);
        flexberryDetailInteractionService.pushValue(
          'modelCurrentAgregators', _this.controller.get('modelCurrentAgregators'), _this.controller.get('model'));

        if (record.get('isNew')) {
          let newModelPath = _this.newRoutePath(editFormRoute);
          later((function() {
            _this.transitionTo(newModelPath).then((newRoute) => {
              newRoute.controller.set('readonly', methodOptions.readonly);
            });
          }), 50);
        } else {
          _this.transitionTo(editFormRoute, record.get('id')).then((newRoute) => {
            newRoute.controller.set('readonly', methodOptions.readonly);
          });
        }
      };

      if (saveBeforeRouteLeave) {
        let model = this.controller.get('model');
        let isModelChanged = !$.isEmptyObject(model.changedAttributes()) ||
         !$.isEmptyObject(model.changedBelongsTo()) || !$.isEmptyObject(model.changedHasMany());
        let isModelNew = model.get('isNew');
        if (isModelNew || isModelChanged) {
          this.controller.save(false, true).then(() => {
            goToOtherRouteFunction();
          });
        } else {
          goToOtherRouteFunction();
        }
      } else {
        goToOtherRouteFunction();
      }
    },

    saveAgregator(agregatorModel) {
      let agregator = agregatorModel ? agregatorModel : this.get('controller.model');
      if (needSaveCurrentAgregator.call(this, agregator)) {
        agregator.save();
      }
    }
  },

  /**
    This hook is executed when the router enters the route. It is not executed when the model for the route changes.

    It is used to subscribe on {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}} events.

    @method activate
  */
  activate() {
    this._super(...arguments);

    this.get('_groupEditEventsService').on('olvRowAdded', this, this._rowAdded);
    this.get('_groupEditEventsService').on('olvRowDeleted', this, this._rowDeleted);
    this.get('_groupEditEventsService').on('olvRowsChanged', this, this._rowChanged);
  },

  /**
    This hook is executed when the router completely exits this route. It is not executed when the model for the route changes.

    It is used to unsubscribe from {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}} events.

    @method deactivate
  */
  deactivate() {
    this._super(...arguments);

    this.get('_groupEditEventsService').off('olvRowAdded', this, this._rowAdded);
    this.get('_groupEditEventsService').off('olvRowDeleted', this, this._rowDeleted);
    this.get('_groupEditEventsService').off('olvRowsChanged', this, this._rowChanged);
  },

  /**
    It forms path for new model's route.

    @method newRoutePath
    @param {String} ordinalPath The path to model's route.
    @return {String} The path to new model's route.
  */
  newRoutePath(ordinalPath) {
    return ordinalPath + '.new';
  },

  /**
    Event handler for "row has been selected" event in {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.

    @method _rowAdded
    @private

    @param {String} componentName The name of {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.
    @param {DS.Model} record The model corresponding to added row in {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.
  */
  /* eslint-disable no-unused-vars */
  _rowAdded(componentName, record) {
    // Manually make record dirty, because ember-data does not do it when relationship changes.
    this.controller.get('model').makeDirty();
  },
  /* eslint-enable no-unused-vars */

  /**
    Event handler for "row has been deleted" event in {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.

    @method _rowDeleted
    @private

    @param {String} componentName The name of {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.
    @param {DS.Model} record The model corresponding to deleted row in {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.
  */
  /* eslint-disable no-unused-vars */
  _rowDeleted(componentName, record) {
    // Manually make record dirty, because ember-data does not do it when relationship changes.
    this.controller.get('model').makeDirty();
  },
  /* eslint-enable no-unused-vars */

  /**
    Event handler for "model(s) corresponding to some row(s) was changed" event in {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.

    @method _rowChanged
    @private

    @param {String} componentName The name of {{#crossLink "FlexberryGroupeditComponent"}}{{/crossLink}}.
  */
  /* eslint-disable no-unused-vars */
  _rowChanged(componentName) {
    // Manually make record dirty, because ember-data does not do it when relationship changes.
    this.controller.get('model').makeDirty();
  }
  /* eslint-enable no-unused-vars */
});