Обновление стандартной сетки Magento 2 с помощью компонентов пользовательского интерфейса (часть 2)
Опубликовано: 2016-10-18В предыдущей статье мы описали, как создать модуль с базовыми условиями и интерфейсом, который позволит нам работать с ними. В процессе создания мы использовали стандартные блоки Magento. Однако Magento 2 способен на гораздо большее.
Я говорю о возможности улучшить интерфейс с помощью UI-компонентов. Эти компоненты добавляются с модулем Magento/UI.
*хотя эти компоненты можно найти в версии 2.0, мы настоятельно рекомендуем вам использовать версию 2.1.
Из этой статьи вы узнаете, как переделать стандартную сетку (расположенную в макете: app/code/Vendor/Rules/view/adminhtml/layout/vendor_rules_example_rule_index.xml ) и обогатить ее компонентами пользовательского интерфейса.
Просто сравните. Это старая сетка:
с новым, сделанным с компонентами UX:
Как видите, обновленный Grid будет намного более удобным для пользователя и сэкономит время, его будет легче масштабировать, он будет иметь множество замечательных дополнительных функций (например, закладки, способные сохранять текущее состояние Grid) и устанавливать интеллектуальные фильтры.
Итак, начнем.
Во-первых, вам нужно внести некоторые изменения в модуль. Ниже показано, как это сделать:
1) Создайте новый файл для объявления необходимых компонентов:
> приложение/код/Поставщик/Правила/и т.д./di.xml
<?xml версия="1.0"?> <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="VendorRulesRuleGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider"> <аргументы> <argument name="collection" xsi:type="object" shared="false">Vendor\Rules\Model\ResourceModel\Rule\Collection</argument> <argument name="filterPool" xsi:type="object" shared="false">VendorRulesRuleGridFilterPool</argument> </аргументы> </ виртуальный тип> <virtualType name="VendorRulesRuleGridFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool"> <аргументы> <argument name="appliers" xsi:type="массив"> <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item> <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item> </аргумент> </аргументы> </ виртуальный тип> <type name="Vendor\Rules\Model\ResourceModel\Rule\Grid\Collection"> <аргументы> <argument name="mainTable" xsi:type="string">vendor_rules</argument> <argument name="eventPrefix" xsi:type="string">vendor_rules_rule_grid_collection</argument> <argument name="eventObject" xsi:type="string">rule_grid_collection</argument> <argument name="resourceModel" xsi:type="string">Vendor\Rules\Model\ResourceModel\Rule</argument> </аргументы> </тип> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <аргументы> <аргумент name="коллекции" xsi:type="массив"> <item name="vendor_rules_rule_listing_data_source" xsi:type="string">Vendor\Rules\Model\ResourceModel\Rule\Grid\Collection</item> </аргумент> </аргументы> </тип> </config>
VendorRulesRuleGridDataProvide — этот виртуальный тип предоставляет данные для сетки правил пользовательского интерфейса. VendorRulesRuleGridFilterPool , в свою очередь, добавляет функциональность фильтрации, которая позволяет добавлять/изменять любые существующие фильтры.
Обратите внимание, чтобы сетка правильно работала с этой конкретной коллекцией, вам нужно добавить ее в список всех доступных коллекций. Для этого добавьте vendor_rules_rule_listing_data_source с классом на основе значений коллекции: Vendor\Rules\Model\ResourceModel\Rule\Grid\Collection в коллекции Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory.
2) Для UI Grid нам нужна отдельная коллекция, которая будет представлять интерфейс `Magento\Framework\Api\Search\SearchResultInterface` .
Он содержит стандартные методы, которые позволят вам работать с сеткой и фильтрами. Этот класс можно настроить в соответствии с вашими личными потребностями, изменив способ работы поиска по коллекциям .
> приложение/код/Поставщик/Правила/Модель/РесурсМодель/Правило/Сетка/Collection.php
<?php пространство имен Vendor\Rules\Model\ResourceModel\Rule\Grid; используйте Vendor\Rules\Model\ResourceModel\Rule\Collection как RuleCollection; используйте Magento\Framework\Api\Search\SearchResultInterface; используйте Magento\Framework\Api\SearchCriteriaInterface; используйте Magento\Framework\Data\Collection\Db\FetchStrategyInterface; используйте Magento\Framework\Data\Collection\EntityFactory; используйте Magento\Framework\Event\ManagerInterface; используйте Magento\Framework\Model\ResourceModel\Db\AbstractDb; используйте Psr\Log\LoggerInterface; Коллекция классов расширяет RuleCollection, реализует SearchResultInterface { /** * Агрегации * * @var \Magento\Framework\Search\AggregationInterface */ защищенные $агрегации; /** * конструктор * * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy * @param \Magento\Framework\Event\ManagerInterface $eventManager * @параметр $mainTable * @param $eventPrefix * @параметр $eventObject * @param $resourceModel * @параметр $модель * @параметр $соединение * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource */ публичная функция __construct( EntityFactory $entityFactory, LoggerInterface $ регистратор, FetchStrategyInterface $fetchStrategy, МенеджерИнтерфейса $eventManager, $ основная таблица, $eventPrefix, $событиеОбъект, $ модель ресурса, $model = 'Magento\Framework\View\Element\UiComponent\DataProvider\Document', $ соединение = ноль, Абстрактная база данных $resource = null ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); $this->_eventPrefix = $eventPrefix; $this->_eventObject = $eventObject; $this->_init($model, $resourceModel); $this->setMainTable($mainTable); } /** * @return\Magento\Framework\Search\AggregationInterface */ публичная функция getAggregations() { вернуть $this->агрегации; } /** * @param \Magento\Framework\Search\AggregationInterface $aggregations * @вернуть $это */ общедоступная функция setAggregations($aggregations) { $this->агрегации = $агрегации; } /** * Получить все идентификаторы для коллекции * Обратная совместимость с коллекцией EAV * * @param int $limit * @param int $ смещение * @возвратный массив */ публичная функция getAllIds($limit = null, $offset = null) { вернуть $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams); } /** * Получить критерии поиска. * * @return \Magento\Framework\Api\SearchCriteriaInterface|null */ публичная функция getSearchCriteria() { вернуть ноль; } /** * Установить критерии поиска. * * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @вернуть $это * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ общедоступная функция setSearchCriteria (SearchCriteriaInterface $searchCriteria = null) { вернуть $это; } /** * Получить общее количество. * * @возврат внутр. */ публичная функция getTotalCount() { вернуть $this->getSize(); } /** * Установить общее количество. * * @param int $totalCount * @вернуть $это * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ общедоступная функция setTotalCount ($ totalCount) { вернуть $это; } /** * Установить список элементов. * * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items * @вернуть $это * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ публичная функция setItems (массив $items = null) { вернуть $это; } } ?>
3) Измените основную коллекцию способом, описанным ниже (это важно, так как наша пользовательская коллекция наследуется от нее). Вы должны внести следующие изменения:
> приложение/код/Поставщик/Правила/Модель/РесурсМодель/Правило/Collection.php
<?php пространство имен Vendor\Rules\Model\ResourceModel\Rule; Коллекция классов расширяет \Magento\Rule\Model\ResourceModel\Rule\Collection\AbstractCollection { /** * Установить модель ресурсов и определить сопоставление полей * * @возврат недействителен */ защищенная функция _construct() { $this->_init('Поставщик\Правила\Модель\Правило', 'Поставщик\Правила\Модель\РесурсМодель\Правило'); } /** * Фильтр коллекции по указанной дате. * Отфильтровать коллекцию только по активным правилам. * * @param string|null $теперь * @use $this->addStoreGroupDateFilter() * @вернуть $это */ общедоступная функция setValidationFilter($now = null) { если (!$this->getFlag('validation_filter')) { $this->addDateFilter($now); $this->addIsActiveFilter(); $this->setOrder('sort_order', self::SORT_ORDER_DESC); $this->setFlag('validation_filter', true); } вернуть $это; } /** * Фильтр с даты или до даты * * @параметр $сейчас * @вернуть $это */ публичная функция addDateFilter($now) { $this->getSelect()->где( 'from_date равно null или from_date <= ?', $сейчас )->где( 'to_date равно null или to_date >= ?', $сейчас ); вернуть $это; } } ?>
4) Далее убираем старую разметку с Grid layout и добавляем туда UI-листинг:
> app/code/Vendor/Rules/view/adminhtml/layout/vendor_rules_example_rule_index.xml
<?xml версия="1.0"?> <page xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <тело> <referenceBlock name="меню"> <метод действия="setActive"> <argument name="itemId" xsi:type="string">Vendor_Rules::vendor_rules</argument> </действие> </referenceBlock> <referenceBlock name="page.title"> <метод действия="setTitleClass"> <argument name="class" xsi:type="string">комплекс</argument> </действие> </referenceBlock> <referenceContainer name="content"> <uiComponent name="vendor_rules_rule_listing"/> </referenceContainer> </тело> </страница>
По сути, мы просто добавляем упомянутый ` vendor_rules_rule_listing` в содержимое страницы (основное действие), меняем статус нашего меню продукта на «Активно» и устанавливаем класс title.
5) На следующем шаге мы создаем листинг пользовательского интерфейса, который будет размещен здесь:
> app/code/Vendor/Rules/view/adminhtml/ui_component/vendor_rules_rule_listing.xml
<?xml версия="1.0"?> <listing xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd"> <аргумент имя="данные" xsi:type="массив"> <item name="js_config" xsi:type="массив"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing_data_source</item> <item name="deps" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing_data_source</item> </item> <item name="spinner" xsi:type="string">vendor_rules_rule_columns</item> <item name="кнопки" xsi:type="массив"> <item name="добавить" xsi:type="массив"> <item name="name" xsi:type="string">добавить</item> <item name="label" xsi:type="string" translate="true">Добавить новое правило</item> <item name="class" xsi:type="string">основной</item> <item name="url" xsi:type="string">*/*/newaction</item> </item> </item> </аргумент> <dataSource name="vendor_rules_rule_listing_data_source"> <argument name="dataProvider" xsi:type="configurableObject"> <argument name="class" xsi:type="string">VendorRulesRuleGridDataProvider</argument> <argument name="name" xsi:type="string">vendor_rules_rule_listing_data_source</argument> <argument name="primaryFieldName" xsi:type="string">rule_id</argument> <argument name="requestFieldName" xsi:type="string">rule_id</argument> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="update_url" xsi:type="url" path="mui/index/render"/> </item> </аргумент> </аргумент> <аргумент имя="данные" xsi:type="массив"> <item name="js_config" xsi:type="массив"> <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item> </item> </аргумент> </ источник данных> <имя контейнера="listing_top"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">пользовательский интерфейс/сетка/панель инструментов</item> <item name="stickyTmpl" xsi:type="string">пользовательский интерфейс/сетка/липкая/панель инструментов</item> </item> </аргумент> <закладка имя="закладки"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="namespace" xsi:type="string">vendor_rules_rule_listing</item> </item> </item> </аргумент> </закладка> <имя компонента="columns_controls"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="columnsData" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> </item> <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item> <item name="displayArea" xsi:type="string">действия dataGridActions</item> </item> </аргумент> </компонент> <имя фильтров="listing_filters"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="columnsProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.filters</item> </item> <item name="templates" xsi:type="массив"> <item name="фильтры" xsi:type="массив"> <item name="выбрать" xsi:type="массив"> <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item> <item name="template" xsi:type="string">пользовательский интерфейс/сетка/фильтры/элементы/пользовательский интерфейс-выбор</item> </item> </item> </item> <item name="childDefaults" xsi:type="массив"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.listing_filters</item> <item name="imports" xsi:type="array"> <item name="visible" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns.${ $.index }:visible</item> </item> </item> </item> <item name="наблюдатели" xsi:type="массив"> <item name="column" xsi:type="string">столбец</item> </item> </аргумент> </фильтры> <paging name="listing_paging"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.paging</item> </item> <item name="selectProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns.ids</item> </item> </аргумент> </пейджинг> </контейнер> <columns name="vendor_rules_rule_columns"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="storageConfig" xsi:type="array"> <item name="provider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">текущий</item> </item> </item> </аргумент> <selectionsColumn name="id"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="resizeEnabled" xsi:type="boolean">false</item> <item name="resizeDefaultWidth" xsi:type="string">55</item> <item name="indexField" xsi:type="string">rule_id</item> </item> </аргумент> </selectionsColumn> <имя_столбца="rule_id"> <аргумент имя="данные" xsi:type="массив"> <item name="js_config" xsi:type="массив"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">textRange</item> <item name="dataType" xsi:type="string">текст</item> <item name="sorting" xsi:type="string">по возрастанию</item> <item name="align" xsi:type="string">влево</item> <item name="label" xsi:type="string" translate="true">ID</item> <item name="sortOrder" xsi:type="number">1</item> </item> </аргумент> </колонка> <имя столбца="имя"> <аргумент имя="данные" xsi:type="массив"> <item name="js_config" xsi:type="массив"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">текст</item> <item name="dataType" xsi:type="string">текст</item> <item name="align" xsi:type="string">влево</item> <item name="label" xsi:type="string" translate="true">Имя</item> </item> </аргумент> </колонка> <имя столбца="is_active"> <аргумент имя="данные" xsi:type="массив"> <item name="options" xsi:type="массив"> <item name="active" xsi:type="массив"> <item name="value" xsi:type="string">1</item> <item name="label" xsi:type="string" translate="true">Активный</item> </item> <item name="inactive" xsi:type="массив"> <item name="value" xsi:type="string">0</item> <item name="label" xsi:type="string" translate="true">Неактивно</item> </item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">выбрать</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item> <item name="editor" xsi:type="string">выбрать</item> <item name="dataType" xsi:type="string">выбрать</item> <item name="label" xsi:type="string" translate="true">активен</item> <item name="sortOrder" xsi:type="number">65</item> </item> </аргумент> </колонка> <column name="sort_order"> <аргумент имя="данные" xsi:type="массив"> <item name="js_config" xsi:type="массив"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> </item> <item name="config" xsi:type="array"> <item name="filter" xsi:type="string">текст</item> <item name="dataType" xsi:type="string">число</item> <item name="align" xsi:type="string">влево</item> <item name="label" xsi:type="string" translate="true">Приоритет</item> </item> </аргумент> </колонка> <column name="from_date" class="Magento\Ui\Component\Listing\Columns\Date"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="sorting" xsi:type="string">описание</item> <item name="filter" xsi:type="string">диапазон дат</item> <item name="dataType" xsi:type="string">дата</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> <item name="label" xsi:type="string" translate="true">Начать</item> </item> </аргумент> </колонка> <column name="to_date" class="Magento\Ui\Component\Listing\Columns\Date"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="sorting" xsi:type="string">описание</item> <item name="filter" xsi:type="string">диапазон дат</item> <item name="dataType" xsi:type="string">дата</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> <item name="label" xsi:type="string" translate="true">Конец</item> </item> </аргумент> </колонка> <actionsColumn name="actions" class="Vendor\Rules\Ui\Component\Listing\Column\RuleActions"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="indexField" xsi:type="string">rule_id</item> <item name="urlEntityParamName" xsi:type="string">rule_id</item> <item name="sortOrder" xsi:type="number">70</item> </item> </аргумент> </actionsColumn> </столбцы> <имя контейнера="липкий"> <аргумент имя="данные" xsi:type="массив"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item> <item name="toolbarProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.listing_top</item> <item name="listingProvider" xsi:type="string">vendor_rules_rule_listing.vendor_rules_rule_listing.vendor_rules_rule_columns</item> </item> </аргумент> </контейнер> </листинг>
Листинг ` dataSource` содержит ссылку на ` dataProvider` — тип, который мы создали в ` di.xml` . Он содержит входные данные, необходимые для Grid.
Отсюда нам нужно определить поле ключа — в нашем случае это ` rule_id` .
Кроме того, вы также можете добавить свои пользовательские кнопки, просто опишите их в разделе «кнопки». В нашем примере мы добавили стандартную кнопку «Добавить» с адресом ` */*/newaction ` (* в пути соответствует текущему значению).
` container name="listing_top" ` содержит некоторые дополнительные компоненты листинга: фильтры, разбиение на страницы и т. д. Вы можете изменить их в соответствии с вашими личными требованиями.
` columns name=“vendor_rules_rule_columns” ` содержит столбцы, практически такие же, как и в сетке по умолчанию. Единственным существенным отличием является новый столбец ` actionsColumn` , в котором представлен набор действий: редактировать и удалять. Эти действия также могут быть расширены, если это необходимо.
Как вы, наверное, заметили, у этой колонки появился новый класс. Давайте узнаем, как мы можем его создать:
> приложение/код/Продавец/Правила/Ui/Компонент/Список/Столбец/RuleActions.php
<?php пространство имен Vendor\Rules\Ui\Component\Listing\Column; класс RuleActions расширяет \Magento\Ui\Component\Listing\Columns\Column { /** * URL-адрес для редактирования * * @var строка */ const URL_PATH_EDIT = 'vendor_rules/example_rule/edit'; /** * URL-адрес для удаления * * @var строка */ const URL_PATH_DELETE = 'vendor_rules/example_rule/delete'; /** * Создатель URL * * @var\Magento\Framework\UrlInterface */ защищенный $urlBuilder; /** * Конструктор * * @param\Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Framework\View\Element\UiComponent\ContextInterface $context * @param \Magento\Framework\View\Element\UiComponentFactory $uiComponentFactory * @param массив $компонентов * @param массив $данные */ публичная функция __construct( \Magento\Framework\UrlInterface $urlBuilder, \Magento\Framework\View\Element\UiComponent\ContextInterface $контекст, \Magento\Framework\View\Element\UiComponentFactory $uiComponentFactory, массив $компоненты = [], массив $данные = [] ) { $this->urlBuilder = $urlBuilder; parent::__construct($context, $uiComponentFactory, $components, $data); } /** * Подготовить источник данных * * массив @param $dataSource * @возвратный массив */ публичная функция prepareDataSource (массив $dataSource) { если (!isset($dataSource['data']['items'])) { вернуть $ источник данных; } foreach ($dataSource['data']['items'] as &$item) { если (!isset($item['rule_id'])) { Продолжать; } $item[$this->getData('имя')] = [ 'редактировать' => [ 'href' => $this->urlBuilder->getUrl( статический::URL_PATH_EDIT, [ 'id' => $item['rule_id'], ] ), 'метка' => __('Редактировать'), ], 'удалить' => [ 'href' => $this->urlBuilder->getUrl( статический::URL_PATH_DELETE, [ 'id' => $item['rule_id'], ] ), 'метка' => __('Удалить'), 'подтвердить' => [ 'title' => __('Удалить "${ $.$data.name }"'), 'message' => __('Вы уверены, что не хотите удалить правило "${ $.$data.name }" ?'), ], ], ]; } вернуть $ источник данных; } } ?>
Этот класс отвечает за обработку действий из сетки. Отсюда можно изменить URL-адреса или имя передаваемого параметра. В нашем случае это ключ rule_id (он передается под именем id, чтобы облегчить понимание его значения).
Это выглядит так:
Если вы все сделали правильно, ваша сетка должна выглядеть так:
Как видно из примера, преобразовать существующую стандартную сетку в пользовательский интерфейс довольно просто. Помимо расширения стандартной функциональности Grid, это также позволяет упростить работу с этой частью функционала Magento 2.
PS В следующей статье цикла мы опишем возможность добавления масс-действий и дополнительных столбцов.
Следите за обновлениями!