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. Ошибка RelationController: "Не удалось найти шаблон (partial) ... traits\ViewMaker.php"

В контроллере поведения RelationController при нажатии на кнопке "Cоздание" вылетает ошибка с подобным содержаним

"Не удалось найти шаблон (partial) с именем _comments.htm." on line 91
of ...\modules\system\traits\ViewMaker.php

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

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

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

FrontEnd контроллеры в OctoberCMS

В OctoberCMS нет концепции frontEnd контроллеров. Иными словами, идеология этой CMS не подразумевает возможность просто создать некий ProductController с несколькими action для обслуживания маршрутов Route::method('product/{id}', 'ProductController@show'). Вместо этого предлагается использовать компоненты плагинов. Именно компоненты являются формой frontEnd контроллеров.