Skip to content
  1. Компоненты
  2. MiniShop3
  3. Интерфейс админки
  4. Утилиты
  5. Колонки гридов

Утилиты: Колонки гридов ​

Настройка отображения колонок в административных таблицах MiniShop3.

Назначение ​

Основной инструмент настройки колонок в административных таблицах MiniShop3:

Cookbook

Пошаговые примеры badge-колонки в заказах и inline-edit в категории: Cookbook колонок грида.

  • Включать и отключать колонки
  • Изменять порядок колонок
  • Настраивать сортировку и фильтрацию
  • Задавать ширину колонок
  • Добавлять кастомные колонки
  • Настраивать inline-редактирование (для грида category-products)

Начиная с версии 1.7.0

Системная настройка ms3_category_grid_fields удалена. Настройка колонок таблицы товаров в категории выполняется только через этот интерфейс.

Доступные гриды ​

ГридОписание
customersСписок покупателей
ordersСписок заказов
category-productsСписок товаров в категории
order_productsТовары в заказе
vendorsСписок производителей

Интерфейс ​

Выбор грида ​

В верхней части страницы выберите грид для настройки из выпадающего списка.

Таблица колонок ​

Отображает текущую конфигурацию колонок:

КолонкаОписание
ИмяСистемное имя поля
НазваниеОтображаемый заголовок
ВидимостьПоказывать ли колонку
СортировкаМожно ли сортировать
ФильтрМожно ли фильтровать
ЗамороженаФиксация при горизонтальной прокрутке
ШиринаШирина колонки в пикселях

Действия ​

  • Перетаскивание — изменение порядка колонок
  • Редактирование — клик на строку открывает диалог
  • Добавление — кнопка для создания новой колонки

Параметры колонки ​

Основные ​

ПараметрОписание
Имя поляИмя поля из модели или алиас
НазваниеЗаголовок колонки
ВидимостьОтображать колонку
СортировкаРазрешить сортировку по клику
ФильтрацияПоказать поле фильтра
ЗамороженаФиксировать при прокрутке

Размеры ​

ПараметрОписание
ШиринаШирина в пикселях или %
Мин. ширинаМинимальная ширина при изменении размера

Тип колонки ​

ТипОписание
modelПоле из модели данных
templateШаблонная колонка (HTML)
relationДанные из связанной таблицы
badgeЦветная метка (source_field, color_field)
optionЗначение опции товара (грид category-products)
computedВычисляемое значение
imageОтображение изображения
booleanФлаг да/нет
priceДенежное значение (displayConfig: валюта, decimals)
weightВес (displayConfig: unit, decimals)
datetimeДата и время (displayConfig: format)
actionsКолонка действий

Типы колонок ​

Model (Поле модели) ​

Стандартная колонка, отображающая значение поля.

Тип: model
Имя поля: email
Название: Email

Template (Шаблон) ​

Колонка с HTML-шаблоном для форматирования.

Тип: template
Шаблон: <a href="mailto:{email}">{email}</a>

Доступные переменные — поля текущей записи в фигурных скобках.

Badge (Метка) ​

Цветная метка по тексту и HEX-цвету из других полей строки. В гриде orders колонка order_status берёт подпись из status_name и цвет из status_color.

Тип: badge
source_field: status_name
color_field: status_color

Option (Опция товара) ​

Колонка опции в гриде category-products. В конфиге укажите option.key (ключ опции из msOption).

Тип: option
option.key: color

Relation (Связь) ​

Данные из связанной таблицы.

Параметры связи:

ПараметрОписание
ТаблицаИмя связанной таблицы
Внешний ключПоле для связи
Отображаемое полеКакое поле показывать
АгрегацияCOUNT, SUM, AVG, MIN, MAX

Пример — количество заказов покупателя:

Тип: relation
Таблица: msOrder
Внешний ключ: customer_id
Агрегация: COUNT

Computed (Вычисляемое) ​

Значение вычисляется на сервере. В JSON config обязателен ключ computed.className (класс реализует ComputedFieldInterface):

json
{
  "type": "computed",
  "computed": {
    "className": "MyComponent\\Columns\\TotalSpentColumn"
  }
}

Image (Изображение) ​

Отображение миниатюры изображения.

Тип: image
Имя поля: image

Boolean (Логическое) ​

Отображение флага с иконкой.

Тип: boolean
Имя поля: active

Price (Цена) ​

Форматирование числового поля как цены. Параметры в JSON displayConfig:

КлючОписание
decimalsЗнаков после запятой
currencyСимвол валюты
currency_positionbefore или after
thousands_separatorРазделитель тысяч
Тип: price
Имя поля: price
displayConfig: {"decimals":2,"currency":"₽","currency_position":"after","thousands_separator":" "}

Weight (Вес) ​

Тип: weight
Имя поля: weight
displayConfig: {"decimals":2,"unit":"кг","unit_position":"after"}

Datetime (Дата и время) ​

Тип: datetime
Имя поля: createdon
displayConfig: {"format":"dd.MM.yyyy HH:mm"}

Формат — шаблон PrimeVue date formatter (dd, MM, yyyy, HH, mm).

Actions (Действия) ​

Колонка с кнопками действий. Поддерживает встроенные и кастомные обработчики.

Конфигурация действий:

json
[
  {
    "name": "edit",
    "handler": "edit",
    "icon": "pi-pencil",
    "label": "Редактировать",
    "severity": null
  },
  {
    "name": "delete",
    "handler": "delete",
    "icon": "pi-trash",
    "label": "Удалить",
    "severity": "danger",
    "confirm": true,
    "confirmMessage": "Вы уверены, что хотите удалить запись?"
  }
]

Параметры действия:

ПараметрТипОписание
namestringУникальное имя действия
handlerstringИмя обработчика из реестра
iconstringИконка PrimeIcons (без pi- префикса)
labelstringТекст подсказки / ключ лексикона
severitystringСтиль кнопки: danger, success, secondary, info, warn
confirmbooleanТребовать подтверждение
confirmMessagestringТекст подтверждения
visiblebooleanВидимость кнопки
disabledboolean/functionОтключение кнопки
disabledFieldstringПоле записи для проверки disabled

Встроенные обработчики:

ОбработчикОписание
editОткрыть запись на редактирование
deleteУдалить запись
viewПросмотр записи
addressesУправление адресами (для покупателей)
refreshОбновить грид

Примеры настройки ​

Скрыть колонку ​

  1. Найдите колонку в списке
  2. Снимите флаг "Видимость"
  3. Нажмите "Сохранить"

Добавить колонку "Сумма заказов" ​

  1. Нажмите "Добавить колонку"
  2. Заполните:
    • Имя: total_spent
    • Название: Сумма заказов
    • Тип: relation
    • Таблица: msOrder
    • Внешний ключ: customer_id
    • Отображаемое поле: cost
    • Агрегация: SUM
  3. Сохраните

Изменить порядок колонок ​

Перетащите колонки в нужном порядке, используя drag-and-drop.

Добавить ссылку в email ​

  1. Найдите колонку email
  2. Измените тип на template
  3. Укажите шаблон: <a href="mailto:{email}">{email}</a>
  4. Сохраните

API Endpoints ​

Получение конфигурации грида ​

GET /api/mgr/grid-config/{grid_name}

Ответ:

json
{
  "success": true,
  "object": {
    "columns": [
      {
        "name": "id",
        "label": "ID",
        "visible": true,
        "sortable": true,
        "filterable": false,
        "frozen": true,
        "width": 60,
        "type": "model"
      }
    ],
    "direct_filter_keys": ["query", "status_id"],
    "editor_references": []
  }
}

Поле editor_references заполняется только для grid_key=category-products.

Сохранение конфигурации ​

PUT /api/mgr/grid-config/{grid_key}

Тело запроса:

json
{
  "fields": [
    {
      "name": "id",
      "label": "ID",
      "visible": true,
      "sortable": true,
      "filterable": false,
      "frozen": true,
      "width": 60,
      "type": "model"
    }
  ]
}

Права

GET /api/mgr/grid-config/{grid_key} требует view_document. Запись (PUT, POST, DELETE колонки) — mssetting_save.

Удаление колонки ​

DELETE /api/mgr/grid-config/{grid_key}/{field_name}

Системные колонки (is_system) удалить нельзя.

Системные колонки ​

Некоторые колонки помечены как системные и имеют ограничения:

  • Нельзя удалить
  • Нельзя изменить имя поля
  • Можно только скрыть

Системные колонки обычно включают id и колонки действий.

Кастомные действия ​

MiniShop3 предоставляет глобальный реестр действий MS3ActionRegistry для добавления собственных кнопок в колонку действий.

Реестр действий ​

Реестр доступен глобально через window.MS3ActionRegistry и позволяет:

  • Регистрировать новые обработчики действий
  • Добавлять хуки before/after для существующих действий
  • Переопределять встроенные обработчики

API реестра ​

register(name, handler, options) ​

Регистрирует новый обработчик действия.

Параметры:

ПараметрТипОписание
namestringИмя действия
handlerfunctionФункция-обработчик (data, context) => void
options.overridebooleanРазрешить перезапись существующего обработчика

Параметры handler:

  • data — объект данных строки грида
  • context — контекст выполнения:
    • gridId — идентификатор грида
    • emit(event, data) — отправка события
    • refresh() — обновление грида
    • toast — сервис уведомлений PrimeVue
    • confirm — сервис подтверждений PrimeVue
    • _(key) — функция локализации

registerBeforeHook(actionName, hook) ​

Регистрирует хук, выполняемый перед действием.

javascript
MS3ActionRegistry.registerBeforeHook('delete', (data, context) => {
  // Вернуть false для отмены действия
  if (data.is_system) {
    context.toast.add({
      severity: 'warn',
      summary: 'Запрещено',
      detail: 'Нельзя удалить системную запись'
    })
    return false
  }
  return true
})

registerAfterHook(actionName, hook) ​

Регистрирует хук, выполняемый после действия.

javascript
MS3ActionRegistry.registerAfterHook('delete', (data, context, result) => {
  console.log('Запись удалена:', data.id)
  // Можно отправить аналитику, логировать и т.д.
})

Другие методы ​

МетодОписание
has(name)Проверить наличие обработчика
get(name)Получить обработчик
unregister(name)Удалить обработчик (кроме встроенных)
getRegisteredActions()Получить список всех зарегистрированных действий
execute(name, data, context)Выполнить действие программно

Примеры кастомных действий ​

Пример 1: Блокировка покупателя ​

Шаг 1. Регистрация обработчика (в плагине MODX или кастомном JS):

javascript
// Файл: assets/components/mycomponent/js/customer-actions.js

document.addEventListener('DOMContentLoaded', () => {
  // Ждём загрузки реестра
  if (!window.MS3ActionRegistry) {
    console.error('MS3ActionRegistry not available')
    return
  }

  // Регистрируем действие "Заблокировать"
  MS3ActionRegistry.register('blockCustomer', async (data, context) => {
    try {
      const response = await fetch('/assets/components/minishop3/connector.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: new URLSearchParams({
          action: 'MyComponent\\Processors\\Customer\\Block',
          id: data.id,
          HTTP_MODAUTH: MODx.siteId
        })
      })

      const result = await response.json()

      if (result.success) {
        context.toast.add({
          severity: 'success',
          summary: 'Успех',
          detail: `Покупатель ${data.email} заблокирован`,
          life: 3000
        })
        context.refresh() // Обновить грид
      } else {
        throw new Error(result.message)
      }
    } catch (error) {
      context.toast.add({
        severity: 'error',
        summary: 'Ошибка',
        detail: error.message,
        life: 5000
      })
    }
  })

  // Регистрируем действие "Разблокировать"
  MS3ActionRegistry.register('unblockCustomer', async (data, context) => {
    const response = await fetch('/assets/components/minishop3/connector.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        action: 'MyComponent\\Processors\\Customer\\Unblock',
        id: data.id,
        HTTP_MODAUTH: MODx.siteId
      })
    })

    const result = await response.json()
    if (result.success) {
      context.toast.add({
        severity: 'success',
        summary: 'Покупатель разблокирован',
        life: 3000
      })
      context.refresh()
    }
  })
})

Шаг 2. Подключение скрипта через плагин MODX:

php
<?php
// Плагин: MyCustomerActions
// События: OnManagerPageBeforeRender

if ($modx->event->name !== 'OnManagerPageBeforeRender') return;

// Только на странице покупателей
$controller = $modx->controller ?? null;
if (!$controller || strpos(get_class($controller), 'Customers') === false) return;

$modx->regClientStartupScript(
    MODX_ASSETS_URL . 'components/mycomponent/js/customer-actions.js'
);

Шаг 3. Настройка колонки действий через интерфейс:

  1. Откройте Утилиты → Колонки гридов
  2. Выберите грид customers
  3. Найдите колонку actions и откройте редактор
  4. Добавьте новое действие:
    • Имя: blockCustomer
    • Обработчик: blockCustomer
    • Иконка: pi-ban
    • Стиль: danger
    • Подтверждение: Да
    • Сообщение: Заблокировать покупателя {email}?

Пример 2: Копирование товара ​

javascript
MS3ActionRegistry.register('duplicateProduct', async (data, context) => {
  const response = await fetch('/assets/components/minishop3/connector.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      action: 'MiniShop3\\Processors\\Product\\Duplicate',
      id: data.id,
      HTTP_MODAUTH: MODx.siteId
    })
  })

  const result = await response.json()

  if (result.success) {
    context.toast.add({
      severity: 'success',
      summary: 'Товар скопирован',
      detail: `Создан товар ID: ${result.object.id}`,
      life: 3000
    })
    context.refresh()
  }
})

Конфигурация действия:

json
{
  "name": "duplicate",
  "handler": "duplicateProduct",
  "icon": "pi-copy",
  "label": "Копировать",
  "severity": "secondary",
  "confirm": false
}

Пример 3: Отправка уведомления ​

javascript
MS3ActionRegistry.register('sendNotification', async (data, context) => {
  // Показать диалог выбора шаблона
  const template = prompt('Введите имя шаблона уведомления:')
  if (!template) return

  const response = await fetch('/assets/components/minishop3/connector.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      action: 'MiniShop3\\Processors\\Notification\\Send',
      customer_id: data.id,
      template: template,
      HTTP_MODAUTH: MODx.siteId
    })
  })

  const result = await response.json()

  if (result.success) {
    context.toast.add({
      severity: 'success',
      summary: 'Уведомление отправлено',
      detail: `Email: ${data.email}`,
      life: 3000
    })
  }
})

Пример 4: Условная видимость кнопки ​

Используйте функцию для disabled:

javascript
// В конфигурации колонки
{
  "name": "unblock",
  "handler": "unblockCustomer",
  "icon": "pi-unlock",
  "label": "Разблокировать",
  "severity": "success",
  // Кнопка неактивна, если покупатель не заблокирован
  "disabledField": "active"  // disabled когда active = true
}

Или проверка через поле данных:

json
{
  "name": "block",
  "handler": "blockCustomer",
  "icon": "pi-ban",
  "label": "Заблокировать",
  "severity": "danger",
  "disabledField": "blocked"  // disabled когда blocked = true
}

Хуки для встроенных действий ​

Логирование удалений ​

javascript
MS3ActionRegistry.registerAfterHook('delete', async (data, context, result) => {
  // Отправка в систему аудита
  await fetch('/api/audit/log', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      action: 'delete',
      entity: context.gridId,
      entityId: data.id,
      user: MODx.user?.id,
      timestamp: new Date().toISOString()
    })
  })
})

Предотвращение удаления ​

javascript
MS3ActionRegistry.registerBeforeHook('delete', (data, context) => {
  // Запретить удаление записей со статусом "оплачен"
  if (context.gridId === 'orders' && data.status === 2) {
    context.toast.add({
      severity: 'error',
      summary: 'Запрещено',
      detail: 'Нельзя удалить оплаченный заказ',
      life: 5000
    })
    return false // Отменить действие
  }
  return true // Продолжить
})

Доступные иконки ​

Используются иконки PrimeIcons. Популярные:

ИконкаКлассНазначение
✏️pi-pencilРедактирование
🗑️pi-trashУдаление
👁️pi-eyeПросмотр
📋pi-copyКопирование
⬇️pi-downloadСкачивание
📤pi-sendОтправка
🔒pi-lockБлокировка
🔓pi-unlockРазблокировка
🚫pi-banЗапрет
✅pi-checkПодтверждение
❌pi-timesОтмена
🔄pi-refreshОбновление
⚙️pi-cogНастройки
🖨️pi-printПечать
🔗pi-external-linkВнешняя ссылка