117 lines
5.5 KiB
Twig
117 lines
5.5 KiB
Twig
{#
|
||
table.twig - Универсальный компонент таблицы с AJAX-загрузкой
|
||
|
||
Параметры:
|
||
- id: ID контейнера таблицы (обязательно)
|
||
- url: URL для AJAX-загрузки данных (обязательно)
|
||
- perPage: Количество записей на странице (по умолчанию 10)
|
||
- columns: Конфигурация колонок
|
||
Пример:
|
||
columns: {
|
||
name: { label: 'Имя', width: '40%' },
|
||
email: { label: 'Email' }
|
||
}
|
||
- items: Массив объектов для отображения
|
||
- actionsConfig: Конфигурация действий строки
|
||
Пример:
|
||
actionsConfig: [
|
||
{ label: 'Ред.', url: '/clients/edit/{id}', icon: 'bi bi-pencil', class: 'btn-outline-primary' },
|
||
{ label: 'Удалить', url: '/clients/delete/{id}', icon: 'bi bi-trash', class: 'btn-outline-danger' }
|
||
]
|
||
- can_edit: Разрешено ли редактирование (для фильтрации действий)
|
||
- can_delete: Разрешено ли удаление (для фильтрации действий)
|
||
- emptyMessage: Сообщение при отсутствии данных
|
||
- emptyActionUrl: URL для кнопки действия
|
||
- emptyActionLabel: Текст кнопки
|
||
- emptyIcon: FontAwesome иконка
|
||
- tableClass: Дополнительные классы для таблицы
|
||
#}
|
||
<div id="{{ id }}" class="data-table" data-url="{{ url }}" data-per-page="{{ perPage|default(10) }}">
|
||
<table class="table table-hover mb-0 {{ tableClass|default('') }}">
|
||
{# Заголовок таблицы #}
|
||
{{ include('@components/table/table_header.twig', {
|
||
columns: columns,
|
||
sort: sort|default(''),
|
||
order: order|default('asc'),
|
||
filters: filters|default({}),
|
||
actions: actions|default(false)
|
||
}) }}
|
||
|
||
{# Тело таблицы #}
|
||
<tbody>
|
||
{% if items is defined and items|length > 0 %}
|
||
{% for item in items %}
|
||
<tr>
|
||
{# Рендерим каждую колонку #}
|
||
{% for key, column in columns %}
|
||
<td>
|
||
{{ render_cell(item, key, column)|raw }}
|
||
</td>
|
||
{% endfor %}
|
||
|
||
{# Колонка действий #}
|
||
{% if actionsConfig is defined and actionsConfig|length > 0 %}
|
||
<td class="actions-cell text-end">
|
||
{# Фильтруем действия на основе прав доступа #}
|
||
{% set visibleActions = [] %}
|
||
{% for action in actionsConfig %}
|
||
{% set showAction = true %}
|
||
{% if action.type is defined %}
|
||
{% if action.type == 'edit' and not (can_edit|default(true)) %}
|
||
{% set showAction = false %}
|
||
{% elseif action.type == 'delete' and not (can_delete|default(true)) %}
|
||
{% set showAction = false %}
|
||
{% endif %}
|
||
{% endif %}
|
||
{% if showAction %}
|
||
{% set visibleActions = visibleActions|merge([action]) %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
{% if visibleActions|length > 0 %}
|
||
{{ render_actions(item, visibleActions)|raw }}
|
||
{% else %}
|
||
<span class="text-muted small">—</span>
|
||
{% endif %}
|
||
</td>
|
||
{% endif %}
|
||
</tr>
|
||
{% endfor %}
|
||
{% else %}
|
||
{# Пустое состояние #}
|
||
<tr>
|
||
<td colspan="{{ columns|length + (actions is defined and actions ? 1 : 0) }}"
|
||
class="text-center py-5">
|
||
{% if emptyIcon is defined and emptyIcon %}
|
||
<div class="mb-3">
|
||
<i class="{{ emptyIcon }} text-muted" style="font-size: 3rem;"></i>
|
||
</div>
|
||
{% endif %}
|
||
<p class="text-muted mb-3">{{ emptyMessage|default('Нет данных') }}</p>
|
||
{% if emptyActionUrl is defined and emptyActionUrl %}
|
||
<a href="{{ emptyActionUrl }}" class="btn btn-primary">
|
||
{% if emptyActionIcon is defined and emptyActionIcon %}
|
||
<i class="{{ emptyActionIcon }} me-2"></i>
|
||
{% endif %}
|
||
{{ emptyActionLabel|default('Добавить') }}
|
||
</a>
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endif %}
|
||
</tbody>
|
||
|
||
{# Футер с пагинацией #}
|
||
<tfoot>
|
||
<tr>
|
||
<td colspan="{{ columns|length + 1 }}">
|
||
{{ include('@components/table/pagination.twig', {
|
||
pagination: pagerDetails,
|
||
id: id
|
||
}) }}
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
</div>
|