OctoberCMS. Массовые действия в List Controller

Кусочек кода из плагина Rainlab.User. Если предполагается набор действий для массового изменения состояния, то в интерфейсе их логично объединить в один пункт.

bulk-actions-octobercms.png

В контроллер необходимо добавить 2 метода. В index просто добавляем js код плагин, а в onBulkActions логика массовых изменений. Допускается только однозначные действия т.е. нет воможности показать модальное окно и уточнить действие у пользователя.

    public function index()
    {
        $this->addJs('/plugins/[vendorname]/[pluginname]/assets/js/bulk-actions.js');
        $this->asExtension('ListController')->index();
    }

    public function index_onBulkAction()
    {
        if (
            ($bulkAction = post('action')) &&
            ($checkedIds = post('checked')) &&
            is_array($checkedIds) &&
            count($checkedIds)
        ) {

            foreach ($checkedIds as $userId) {
                if (!$user = User::withTrashed()->find($userId)) {
                    continue;
                }

                switch ($bulkAction) {
                    case 'delete':
                        $user->forceDelete();
                        break;

                    case 'activate':
                        $user->attemptActivation($user->activation_code);
                        break;

                    case 'deactivate':
                        $user->delete();
                        break;

                    case 'restore':
                        $user->restore();
                        break;

                    case 'ban':
                        $user->ban();
                        break;

                    case 'unban':
                        $user->unban();
                        break;
                }
            }

            Flash::success(Lang::get('rainlab.user::lang.users.'.$bulkAction.'_selected_success'));
        }
        else {
            Flash::error(Lang::get('rainlab.user::lang.users.'.$bulkAction.'_selected_empty'));
        }

        return $this->listRefresh();
    }    

И в htm файл (стандартно это _list_toolbar.htm) панели инструментов:

    <div class="btn-group dropdown dropdown-fixed" data-control="bulk-actions">
        <button
            data-primary-button
            type="button"
            class="btn btn-default"
            data-request="onBulkAction"
            data-trigger-action="enable"
            data-trigger=".control-list input[type=checkbox]"
            data-trigger-condition="checked"
            data-request-success="$(this).prop('disabled', true).next().prop('disabled', true)"
            data-stripe-load-indicator>
            Массовые действия
        </button>
        <button
            type="button"
            class="btn btn-default dropdown-toggle"
            data-trigger-action="enable"
            data-trigger=".control-list input[type=checkbox]"
            data-trigger-condition="checked"
            data-toggle="dropdown">
            <span class="caret"></span>
        </button>
        <ul class="dropdown-menu" data-dropdown-title="Массовые действия">
            <li>
                <a href="javascript:;" class="oc-icon-trash-o" data-action="delete" data-confirm="<?= e(trans('rainlab.user::lang.users.delete_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.delete_selected')) ?>
                </a>
            </li>
            <li role="separator" class="divider"></li>
            <li>
                <a href="javascript:;" class="oc-icon-user-plus" data-action="activate" data-confirm="<?= e(trans('rainlab.user::lang.users.activate_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.activate_selected')) ?>
                </a>
            </li>
            <li role="separator" class="divider"></li>
            <li>
                <a href="javascript:;" class="oc-icon-user-times" data-action="deactivate" data-confirm="<?= e(trans('rainlab.user::lang.users.deactivate_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.deactivate_selected')) ?>
                </a>
            </li>
            <li>
                <a href="javascript:;" class="oc-icon-user-plus" data-action="restore" data-confirm="<?= e(trans('rainlab.user::lang.users.restore_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.restore_selected')) ?>
                </a>
            </li>
            <li role="separator" class="divider"></li>
            <li>
                <a href="javascript:;" class="oc-icon-ban" data-action="ban" data-confirm="<?= e(trans('rainlab.user::lang.users.ban_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.ban_selected')) ?>
                </a>
            </li>
            <li>
                <a href="javascript:;" class="oc-icon-circle-o-notch" data-action="unban" data-confirm="<?= e(trans('rainlab.user::lang.users.unban_selected_confirm')) ?>">
                    <?= e(trans('rainlab.user::lang.users.unban_selected')) ?>
                </a>
            </li>
        </ul>
    </div>

В разрабатываемый плагин October CMS соответственно сам js плагин assets/js/bulk-actions.js

/*
 * Bulk actions plugin
 * 
 * Data attributes:
 * - data-control="bulk-actions" - enables the plugin on an element
 *
 * JavaScript API:
 * $('div').bulkActions()
 */

+function ($) { "use strict";

    // BULK ACTIONS CLASS DEFINITION
    // ============================

    var BulkActions = function(element, options) {
        this.options   = options
        this.$el       = $(element)

        // Init
        this.init()
    }

    BulkActions.DEFAULTS = {}

    BulkActions.prototype.init = function() {
        this.activeAction = null
        this.$primaryBtn = $('[data-primary-button]', this.$el)
        this.$toggleBtn = $('.dropdown-toggle', this.$el)
        this.$dropdownMenu = $('.dropdown-menu', this.$el)
        this.baseCss = this.$primaryBtn.attr('class')

        this.$primaryBtn.on('click', $.proxy(this.onClickPrimaryButton, this))
        this.$dropdownMenu.on('click', 'li > a', $.proxy(this.onClickMenuItem, this))

        this.setActiveItem($('li > a:first', this.$dropdownMenu))
    }

    BulkActions.prototype.onClickPrimaryButton = function() {
        if (!this.activeAction) {
            throw new Error('Bulk action not found')
        }

        this.$primaryBtn.data('request-data', {
            checked: $('.control-list').listWidget('getChecked'),
            action: this.activeAction
        })
    }

    BulkActions.prototype.onClickMenuItem = function(ev) {
        this.setActiveItem($(ev.target))
        this.$primaryBtn.click()
    }

    BulkActions.prototype.setActiveItem = function($el) {
        this.$toggleBtn.blur()
        this.activeAction = $el.data('action')
        this.$primaryBtn.text($el.text())
        this.$primaryBtn.attr('class', this.baseCss)
        this.$primaryBtn.addClass($el.attr('class'))
        this.$primaryBtn.data('request-confirm', $el.data('confirm'))
    }

    // BULK ACTIONS PLUGIN DEFINITION
    // ============================

    var old = $.fn.bulkActions

    $.fn.bulkActions = function (option) {
        var args = Array.prototype.slice.call(arguments, 1), result
        this.each(function () {
            var $this   = $(this)
            var data    = $this.data('oc.bulkactions')
            var options = $.extend({}, BulkActions.DEFAULTS, $this.data(), typeof option == 'object' && option)
            if (!data) $this.data('oc.bulkactions', (data = new BulkActions(this, options)))
            if (typeof option == 'string') result = data[option].apply(data, args)
            if (typeof result != 'undefined') return false
        })

        return result ? result : this
    }

    $.fn.bulkActions.Constructor = BulkActions

    // BULK ACTIONS NO CONFLICT
    // =================

    $.fn.bulkActions.noConflict = function () {
        $.fn.bulkActions = old
        return this
    }

    // BULK ACTIONS DATA-API
    // ===============

    $(document).render(function() {
        $('[data-control="bulk-actions"]').bulkActions()
    });

}(window.jQuery);

Другие записи из подборки «OctoberCMS. Backend.»

Похожие записи

Собственные сообщения об ошибках валидации форм OctoberCMS

Во время разработки модели данных OctoberCMS при необходимости, можно использовать собственные сообщения об ошибках валидации полей формы вместо сообщения The :attribute field is required. по-умолчанию. В статье показывается как, достаточно просто, это делается.