|
- {# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #}
- {# @var entities \EasyCorp\Bundle\EasyAdminBundle\Collection\EntityDtoCollection #}
- {# @var paginator \EasyCorp\Bundle\EasyAdminBundle\Orm\EntityPaginator #}
- {% extends ea.templatePath('layout') %}
- {% trans_default_domain ea.i18n.translationDomain %}
-
- {% block body_id entities|length > 0 ? 'ea-index-' ~ entities|first.name : '' %}
- {% block body_class 'index' ~ (entities|length > 0 ? ' index-' ~ entities|first.name : '') %}
-
- {% block content_title %}
- {%- apply spaceless -%}
- {% set default_title = ea.crud.defaultPageTitle('index')|trans(ea.i18n.translationParameters, 'EasyAdminBundle') %}
- {{ ea.crud.customPageTitle is null ? default_title|raw : ea.crud.customPageTitle('index')|trans(ea.i18n.translationParameters)|raw }}
- {%- endapply -%}
- {% endblock %}
-
- {% set has_batch_actions = batch_actions|length > 0 %}
- {% block page_actions %}
- {% block global_actions %}
- <div class="global-actions">
- {% for action in global_actions %}
- {{ include(action.templatePath, { action: action }, with_context = false) }}
- {% endfor %}
- </div>
- {% endblock global_actions %}
- {% block batch_actions %}
- {% if has_batch_actions %}
- <div class="batch-actions" style="display: none">
- {% for action in batch_actions %}
- {{ include(action.templatePath, { action: action }, with_context = false) }}
- {% endfor %}
- </div>
- {% endif %}
- {% endblock %}
- {% endblock page_actions %}
-
- {% block main %}
- {# sort can be multiple; let's consider the sorting field the first one #}
- {% set sort_field_name = app.request.get('sort')|keys|first %}
- {% set sort_order = app.request.get('sort')|first %}
- {% set some_results_are_hidden = false %}
- {% set has_footer = entities|length != 0 %}
- {% set has_search = ea.crud.isSearchEnabled %}
- {% set has_filters = filters|length > 0 %}
- {% set has_datagrid_tools = has_search or has_filters %}
-
- <div class="card card-table card-outline card-primary">
- <div class="card-header">
- <span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total">
- {{ paginator.numResults }} résultats
- </span>
- </div>
-
- <div class="card-body">
- <div class="table-responsive">
- <table class="table table-bordered table-hover table-striped">
- <thead>
- {% block table_head %}
-
- <tr>
- {% if has_batch_actions %}
- <th class=""><span><input type="checkbox"
- class="form-check-input m-0 align-middle form-batch-checkbox-all"></span>
- </th>
- {% endif %}
-
- {% set ea_sort_asc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::ASC') %}
- {% set ea_sort_desc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::DESC') %}
- {% for field in entities|first.fields ?? [] %}
- {% set is_sorting_field = ea.search.isSortingField(field.property) %}
- {% set next_sort_direction = is_sorting_field ? (ea.search.sortDirection(field.property) == ea_sort_desc ? ea_sort_asc : ea_sort_desc) : ea_sort_desc %}
- {% set column_icon = is_sorting_field ? (next_sort_direction == ea_sort_desc ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %}
-
- <th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}"
- dir="{{ ea.i18n.textDirection }}">
- {% if field.isSortable %}
- <a href="{{ ea_url({ page: 1, sort: { (field.property): next_sort_direction } }).includeReferrer() }}">
- {{ field.label|raw }} <i class="fa fa-fw {{ column_icon }}"></i>
- </a>
- {% else %}
- <span>{{ field.label|raw }}</span>
- {% endif %}
- </th>
- {% endfor %}
-
- <th class="w-1" {% if ea.crud.showEntityActionsAsDropdown %}width="10px"{% endif %} dir="{{ ea.i18n.textDirection }}">
- <span class="sr-only">{{ 'action.entity_actions'|trans(ea.i18n.translationParameters, 'EasyAdminBundle') }}</span>
- </th>
- </tr>
- {% endblock table_head %}
- </thead>
-
- <tbody>
- {% block table_body %}
- {% for entity in entities %}
- {% if not entity.isAccessible %}
- {% set some_results_are_hidden = true %}
- {% else %}
- <tr data-id="{{ entity.primaryKeyValueAsString }}">
- {% if has_batch_actions %}
- <td><input type="checkbox" class="form-batch-checkbox"
- value="{{ entity.primaryKeyValue }}"></td>
- {% endif %}
-
- {% for field in entity.fields %}
- <td class="{{ field.property == sort_field_name ? 'sorted' }} text-{{ field.textAlign }} {{ field.cssClass }}"
- dir="{{ ea.i18n.textDirection }}">
- {{ include(field.templatePath, { field: field, entity: entity }, with_context = false) }}
- </td>
- {% endfor %}
-
- {% block entity_actions %}
- <td class="actions">
- {% if not ea.crud.showEntityActionsAsDropdown %}
- {% for action in entity.actions %}
- {{ include(action.templatePath, { action: action, entity: entity, isIncludedInDropdown: ea.crud.showEntityActionsAsDropdown }, with_context = false) }}
- {% endfor %}
- {% else %}
- <div class="dropdown dropdown-actions">
- <a class="dropdown-toggle btn btn-secondary btn-sm" href="#"
- role="button" data-toggle="dropdown" aria-haspopup="true"
- aria-expanded="false">
- <i class="fa fa-fw fa-ellipsis-h"></i>
- </a>
-
- <div class="dropdown-menu dropdown-menu-right">
- {% for action in entity.actions %}
- {{ include(action.templatePath, { action: action, isIncludedInDropdown: ea.crud.showEntityActionsAsDropdown }, with_context = false) }}
- {% endfor %}
- </div>
- </div>
- {% endif %}
- </td>
- {% endblock entity_actions %}
- </tr>
-
- {% endif %}
- {% else %}
- <tr>
- <td class="no-results" colspan="100">
- {{ 'datagrid.no_results'|trans(ea.i18n.translationParameters, 'EasyAdminBundle') }}
- </td>
- </tr>
- {% endfor %}
-
- {% if some_results_are_hidden %}
- <tr class="datagrid-row-empty">
- <td class="text-center" colspan="{{ entities|first.fields|length + 1 }}">
- <span class="datagrid-row-empty-message"><i
- class="fa fa-lock mr-1"></i> {{ 'datagrid.hidden_results'|trans({}, 'EasyAdminBundle') }}</span>
- </td>
- </tr>
- {% endif %}
- {% endblock table_body %}
- </tbody>
- </table>
- </div>
- </div>
-
- {% if entities|length > 0 %}
- <div class="card-footer">
- <div class="row">
- {% block paginator %}
- {{ include(ea.templatePath('crud/paginator')) }}
- {% endblock paginator %}
- </div>
- </div>
- {% endif %}
- </div>
-
- {% block delete_form %}
- {{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', with_context = false) }}
- {% endblock delete_form %}
-
- {% if has_filters %}
- {{ include('@EasyAdmin/crud/includes/_filters_modal.html.twig') }}
- {% endif %}
-
- {% if has_batch_actions %}
- {{ include('@EasyAdmin/crud/includes/_batch_action_modal.html.twig', {}, with_context = false) }}
- {% endif %}
- {% endblock main %}
-
- {% block body_javascript %}
- {{ parent() }}
-
- <script type="text/javascript">
- $(function () {
- const customSwitches = document.querySelectorAll('td.field-boolean .custom-control.custom-switch input[type="checkbox"]');
- for (i = 0; i < customSwitches.length; i++) {
- customSwitches[i].addEventListener('change', function () {
- const customSwitch = this;
- const newValue = this.checked;
- const oldValue = !newValue;
-
- const toggleUrl = this.getAttribute('data-toggle-url') + "&newValue=" + newValue.toString();
- let toggleRequest = $.ajax({type: "GET", url: toggleUrl, data: {}});
-
- toggleRequest.done(function (result) {
- });
-
- toggleRequest.fail(function () {
- // in case of error, restore the original value and disable the toggle
- customSwitch.checked = oldValue;
- customSwitch.disabled = true;
- customSwitch.closest('.custom-switch').classList.add('disabled');
- });
- });
- }
-
- $('.action-delete').on('click', function (e) {
- e.preventDefault();
- const formAction = $(this).attr('formaction');
-
- $('#modal-delete').modal({backdrop: true, keyboard: true})
- .off('click', '#modal-delete-button')
- .on('click', '#modal-delete-button', function () {
- let deleteForm = $('#delete-form');
- deleteForm.attr('action', formAction);
- deleteForm.submit();
- });
- });
-
- {% if filters|length > 0 %}
- const filterModal = document.querySelector('#modal-filters');
-
- const removeFilter = function (field) {
- field.closest('form').querySelectorAll('input[name^="filters[' + field.dataset.filterProperty + ']"]').forEach(hidden => {
- hidden.remove();
- });
- field.remove();
- }
-
- document.querySelector('#modal-clear-button').addEventListener('click', function () {
- filterModal.querySelectorAll('.filter-field').forEach(filterField => {
- removeFilter(filterField);
- });
- filterModal.querySelector('form').submit();
- });
-
- document.querySelector('#modal-apply-button').addEventListener('click', function () {
- filterModal.querySelectorAll('.filter-checkbox:not(:checked)').forEach(notAppliedFilter => {
- removeFilter(notAppliedFilter.closest('.filter-field'));
- });
- filterModal.querySelector('form').submit();
- });
-
- // HTML5 specifies that a <script> tag inserted with innerHTML should not execute
- // https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Security_considerations
- // That's why we can't use just 'innerHTML'. See https://stackoverflow.com/a/47614491/2804294
- let setInnerHTML = function (element, htmlContent) {
- element.innerHTML = htmlContent;
- Array.from(element.querySelectorAll('script')).forEach(oldScript => {
- const newScript = document.createElement('script');
- Array.from(oldScript.attributes)
- .forEach(attr => newScript.setAttribute(attr.name, attr.value));
- newScript.appendChild(document.createTextNode(oldScript.innerHTML));
- oldScript.parentNode.replaceChild(newScript, oldScript);
- });
- };
-
- let filterButton = document.querySelector('.action-filters-button');
- filterButton.addEventListener('click', function (event) {
- let filterModal = document.querySelector(filterButton.dataset.modal);
- let filterModalBody = filterModal.querySelector('.modal-body');
-
- $(filterModal).modal({backdrop: true, keyboard: true});
- filterModalBody.innerHTML = '<div class="fa-3x px-3 py-3 text-muted text-center"><i class="fas fa-circle-notch fa-spin"></i></div>';
-
- $.get(filterButton.getAttribute('href'), function (response) {
- setInnerHTML(filterModalBody, response);
- });
-
- event.preventDefault();
- event.stopPropagation();
- });
- filterButton.setAttribute('href', filterButton.getAttribute('data-href'));
- filterButton.removeAttribute('data-href');
- filterButton.classList.remove('disabled');
- {% endif %}
-
-
- {% if has_batch_actions %}
- const titleContent = $('.content-header-title > .title').html();
- $(document).on('click', '.deselect-batch-button', function () {
- $(this).closest('.content').find(':checkbox.form-batch-checkbox-all').prop('checked', false).trigger('change');
- });
- $(document).on('change', '.form-batch-checkbox-all', function () {
- $(this).closest('.content').find(':checkbox.form-batch-checkbox').prop('checked', $(this).prop('checked')).trigger('change');
- });
- $(document).on('change', '.form-batch-checkbox', function () {
- const $content = $(this).closest('.content');
- let $input = $content.find(':hidden#batch_form_entityIds');
- let ids = $input.val() ? $input.val().split(',') : [];
- const id = $(this).val();
-
- if ($(this).prop('checked')) {
- $(this).closest('tr').addClass('selected-row');
- if (-1 === ids.indexOf(id)) {
- ids.push(id);
- }
- } else {
- $(this).closest('tr').removeClass('selected-row');
- ids = ids.filter(function (value) {
- return value !== id
- });
- $content.find(':checkbox.form-batch-checkbox-all').prop('checked', false);
- }
-
- if (0 === ids.length) {
- $content.find('.global-actions').show();
- $content.find('.batch-actions').hide();
- $content.find('table').removeClass('table-batch');
- } else {
- $content.find('.batch-actions').show();
- $content.find('.global-actions').hide();
- $content.find('table').addClass('table-batch');
- }
-
- $input.val(ids.join(','));
- $content.find('.content-header-title > .title').html(0 === ids.length ? titleContent : '');
- });
-
- let modalTitle = $('#batch-action-confirmation-title');
- const titleContentWithPlaceholders = modalTitle.text();
-
- $('[data-action-batch]').on('click', function (event) {
- event.preventDefault();
- event.stopPropagation();
- let $actionElement = $(this);
-
- const actionName = $actionElement.attr('data-action-name');
- const selectedItems = $('input[type="checkbox"].form-batch-checkbox:checked');
- modalTitle.text(titleContentWithPlaceholders
- .replace('%action_name%', actionName)
- .replace('%num_items%', selectedItems.length));
-
- $('#modal-batch-action').modal({backdrop: true, keyboard: true})
- .off('click', '#modal-batch-action-button')
- .on('click', '#modal-batch-action-button', function () {
- $actionElement.unbind('click');
-
- $form = document.createElement('form');
- $form.setAttribute('action', $actionElement.attr('data-action-url'));
- $form.setAttribute('method', 'POST');
-
- $actionNameInput = document.createElement('input');
- $actionNameInput.setAttribute('type', 'hidden');
- $actionNameInput.setAttribute('name', 'batchActionName');
- $actionNameInput.setAttribute('value', $actionElement.attr('data-action-name'));
- $form.appendChild($actionNameInput);
-
- $entityFqcnInput = document.createElement('input');
- $entityFqcnInput.setAttribute('type', 'hidden');
- $entityFqcnInput.setAttribute('name', 'entityFqcn');
- $entityFqcnInput.setAttribute('value', $actionElement.attr('data-entity-fqcn'));
- $form.appendChild($entityFqcnInput);
-
- $actionUrlInput = document.createElement('input');
- $actionUrlInput.setAttribute('type', 'hidden');
- $actionUrlInput.setAttribute('name', 'batchActionUrl');
- $actionUrlInput.setAttribute('value', $actionElement.attr('data-action-url'));
- $form.appendChild($actionUrlInput);
-
- $csrfTokenInput = document.createElement('input');
- $csrfTokenInput.setAttribute('type', 'hidden');
- $csrfTokenInput.setAttribute('name', 'batchActionCsrfToken');
- $csrfTokenInput.setAttribute('value', $actionElement.attr('data-action-csrf-token'));
- $form.appendChild($csrfTokenInput);
-
- selectedItems.each((i, item) => {
- $entityIdInput = document.createElement('input');
- $entityIdInput.setAttribute('type', 'hidden');
- $entityIdInput.setAttribute('name', `batchActionEntityIds[${i}]`);
- $entityIdInput.setAttribute('value', item.value);
- $form.appendChild($entityIdInput);
- });
-
- document.body.appendChild($form);
-
- //modalTitle.text(titleContentWithPlaceholders);
- $form.submit();
- });
- });
- {% endif %}
- });
- </script>
-
- {% if app.request.get('query') is not empty %}
- <script type="text/javascript">
- const search_query = "{{ ea.search.query|default('')|e('js') }}";
- // the original query is prepended to allow matching exact phrases in addition to single words
- $('#main').find('table tbody td:not(.actions)').highlight($.merge([search_query], search_query.split(' ')));
- </script>
- {% endif %}
- {% endblock %}
|