APIs

Show:
/**
 @module ember-flexberry
 */
import $ from 'jquery';
import { isNone } from '@ember/utils';
import { A } from '@ember/array';
import { assert } from '@ember/debug';
import { computed } from '@ember/object';
import { sort } from '@ember/object/computed';
import FlexberryBaseComponent from 'ember-flexberry/components/flexberry-base-component';
import { set } from '@ember/object';

export default FlexberryBaseComponent.extend({

  classNames: ['flexberry-edit-panel'],

  /**
    Edit panel current width.

    @property _editPanelWidth
    @type Number
    @private
  */
  _editPanelWidth: undefined,

  /**
    Buttons width.

    @property _buttonsWidth
    @type Number
    @private
  */
  _buttonsWidth: computed('buttons.@each.width', function() {
    return this.get('buttons').map(btn => btn.width).reduce((prev, curr) => prev + curr);
  }),

  /**
    Close button width.

    @property _closeButtonWidth
    @type Number
    @private
  */
  _closeButtonWidth: undefined,

  /**
    Margin button width.

    @property _closeButtonWidth
    @type Number
    @private
  */
  _marginWidth: 20,

  /**
    Menu dropdown width.

    @property _buttonDropdownWidth
    @type Number
    @private
  */
  _buttonDropdownWidth: computed('_menuButtons.length', 'element', function() {
    const menuButtonsLength = this.get('_menuButtons.length');
    const menuButtonsElement = $(this.element).find('.menu-buttons.group-toolbar');

    return ( menuButtonsLength > 0 && menuButtonsElement.length > 0) ? menuButtonsElement.outerWidth(true) : 60;
  }),

  /**
    Menu buttons.

    @property _menuButtons
    @type Array
    @private
  */
  _menuButtons: undefined,

  /**
    Panel buttons.

    @property _panelButtons
    @type Array
    @private
  */
  _panelButtons: undefined,

  /**
    Buttons.

    @property _panelButtons
    @type Array
  */
  buttons: undefined,

  /**
    Sorting buttons type.

    @property _buttonsSorting
    @type Object
    @private
  */
  _buttonsSorting: undefined,

  /**
    Sorting panel buttons type.

    @property panelButtonsSorted
    @type Object
  */
  panelButtonsSorted: sort('_panelButtons', '_buttonsSorting'),

  /**
    Sorting menu buttons type.

    @property menuButtonsSorted
    @type Object
  */
  menuButtonsSorted: sort('_menuButtons', '_buttonsSorting'),

  /**
    Show close button in panel.

    @property showCloseButton
    @type boolean
  */
  showCloseButton: false,

  /**
    Close button action name.

    @property closeAction
    @type string
  */
  closeAction: 'close',

  /**
    Flag, the component is embedded in another component, for example, in the flexberry-olv toolbar.
    Set to send action in the controller.

    @type {Boolean}
  */
  deepMount: false,

  /**
    Update display buttons.

    @method _updateDisplayButtons
    @private
  */
  _updateDisplayButtons() {
    let btnInPanel = A();
    let btnInMenu = A();

    if (this.get('_buttonsWidth') + this.get('_closeButtonWidth') + this.get('_marginWidth') <= this.get('_editPanelWidth')) {
      btnInPanel = this.get('buttons');
    } else {
      let maxWidthForButtonsPanel = this.get('_editPanelWidth') - (this.get('_buttonDropdownWidth') + this.get('_closeButtonWidth') + this.get('_marginWidth'));
      let currentButtonsWidth = 0;
      let isButtonsPanelFull = false;

      this.get('buttons').forEach(btn => {
        if (!btn.disabled) {
          if (currentButtonsWidth + btn.width <= maxWidthForButtonsPanel && !isButtonsPanelFull) {
            btnInPanel.pushObject(btn);
            currentButtonsWidth += btn.width;
          } else {
            isButtonsPanelFull = true;
            btnInMenu.pushObject(btn);
          }
        }
      });
    }

    this.set('_panelButtons', btnInPanel);
    this.set('_menuButtons', btnInMenu);
  },

  /**
    Initializes component.
  */
  init() {
    this._super(...arguments);

    this.set('_buttonsSorting', ['id:asc']);
    this.get('buttons').forEach((btn, i) => set(btn, 'id', `edit_btn${i}`));
    this.set('_panelButtons', this.get('buttons'));
    this.set('_menuButtons', A());

  },

  /**
    Initializes DOM-related component's logic.
  */
  didInsertElement() {
    this._super(...arguments);

    const $editPanel = $(this.element);
    this.set('_editPanelWidth', $editPanel.outerWidth());

    let closeButtonWidth = this.get('showCloseButton') ? $editPanel.find('.ui.button.close-button').outerWidth() : 0;
    this.set('_closeButtonWidth', closeButtonWidth);

    // get and save button width
    this.get('_panelButtons').forEach(btn => {
      let button = $editPanel.find(`#${btn.id}`);
      btn.width = button.outerWidth(true);
    });

    this._updateDisplayButtons();

    $(window).bind('resize', $.proxy(function() {
      const elementWidth = $(this.element).outerWidth();
      if (this.get('_editPanelWidth') !== elementWidth) {
        this.set('_editPanelWidth', elementWidth);
        this._updateDisplayButtons();
      }
    }, this));
  },

  /**
    Handles DOM-related component's properties after each render.
  */
  didRender() {
    this.$('.ui.dropdown.group-toolbar').dropdown();
  },

  /**
    Cleans up DOM-related component's logic.
  */
  willDestroyElement() {
    this._super(...arguments);

    $(window).unbind('resize');
  },

  actions: {
    /**
     * Call action of a clicked button.
     *
     * @method actions.sendButtonAction
     * @public
     * @param {String|Object} action action.
     */
    sendButtonAction(action) {
      assert('{{edit-panel}}: button.action parameter missing', !isNone(action));

      let actionName = '';
      let actionParams = [];

      if (typeof action === 'string') {
        actionName = action;
      } else if (!isNone(action.params)) {
        actionName = action.name;
        actionParams = action.params;
      }

      if (this.get('deepMount')) {
        this.currentController.send(actionName, ...actionParams);
      } else {
        this.get(actionName)(...actionParams);
      }
    }
  }
});