Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

289 linhas
15KB

  1. {# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #}
  2. {# @var entities \EasyCorp\Bundle\EasyAdminBundle\Collection\EntityDtoCollection #}
  3. {# @var paginator \EasyCorp\Bundle\EasyAdminBundle\Orm\EntityPaginator #}
  4. {% extends ea.templatePath('layout') %}
  5. {% trans_default_domain ea.i18n.translationDomain %}
  6. {% block body_id entities|length > 0 ? 'ea-index-' ~ entities|first.name : '' %}
  7. {% block body_class 'index' ~ (entities|length > 0 ? ' index-' ~ entities|first.name : '') %}
  8. {% block content_title %}
  9. {%- apply spaceless -%}
  10. {% set default_title = ea.crud.defaultPageTitle('index')|trans(ea.i18n.translationParameters, 'EasyAdminBundle') %}
  11. {{ ea.crud.customPageTitle is null ? default_title|raw : ea.crud.customPageTitle('index')|trans(ea.i18n.translationParameters)|raw }}
  12. {%- endapply -%}
  13. {% endblock %}
  14. {% set has_batch_actions = batch_actions|length > 0 %}
  15. {% block page_actions %}
  16. {% block global_actions %}
  17. <div class="global-actions">
  18. {% for action in global_actions %}
  19. {{ include(action.templatePath, { action: action }, with_context = false) }}
  20. {% endfor %}
  21. </div>
  22. {% endblock global_actions %}
  23. {% block batch_actions %}
  24. {% if has_batch_actions %}
  25. <div class="batch-actions" style="display: none">
  26. {% for action in batch_actions %}
  27. {{ include(action.templatePath, { action: action }, with_context = false) }}
  28. {% endfor %}
  29. </div>
  30. {% endif %}
  31. {% endblock %}
  32. {% endblock page_actions %}
  33. {% block main %}
  34. {# sort can be multiple; let's consider the sorting field the first one #}
  35. {% set sort_field_name = app.request.get('sort')|keys|first %}
  36. {% set sort_order = app.request.get('sort')|first %}
  37. {% set some_results_are_hidden = false %}
  38. {% set has_footer = entities|length != 0 %}
  39. {% set has_search = ea.crud.isSearchEnabled %}
  40. {% set has_filters = filters|length > 0 %}
  41. {% set has_datagrid_tools = has_search or has_filters %}
  42. {% embed '@LcSov/adminlte/embed/card.html.twig' %}
  43. {% block css %}card-table card-outline card-primary{% endblock %}
  44. {% block header %}
  45. <span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total">
  46. {{ paginator.numResults }} résultats
  47. </span>
  48. {% endblock %}
  49. {% block body %}
  50. <div class="table-responsive">
  51. <table class="table table-bordered table-hover table-striped">
  52. <thead>
  53. {% block table_head %}
  54. <tr>
  55. {% if has_batch_actions %}
  56. <th class="">
  57. <input type="hidden" id="batch_form_entityIds" value=""/>
  58. <span><input type="checkbox"
  59. class="form-check-input m-0 align-middle form-batch-checkbox-all"></span>
  60. </th>
  61. {% endif %}
  62. {% set ea_sort_asc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::ASC') %}
  63. {% set ea_sort_desc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::DESC') %}
  64. {% for field in fields ?? [] %}
  65. {% set field = field.getAsDto() %}
  66. {% if field.isDisplayedOn('index') %}
  67. {% set is_sorting_field = ea.search.isSortingField(field.property) %}
  68. {% set next_sort_direction = is_sorting_field ? (ea.search.sortDirection(field.property) == ea_sort_desc ? ea_sort_asc : ea_sort_desc) : ea_sort_desc %}
  69. {% set column_icon = is_sorting_field ? (next_sort_direction == ea_sort_desc ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %}
  70. <th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}"
  71. dir="{{ ea.i18n.textDirection }}">
  72. {% if field.isSortable %}
  73. <a href="{{ ea_url({ page: 1, sort: { (field.property): next_sort_direction } }).includeReferrer() }}">
  74. {{ field.label ? field.label|raw : field.getProperty|raw }} <i class="fa fa-fw {{ column_icon }}"></i>
  75. </a>
  76. {% else %}
  77. <span>{{ field.label ? field.label|raw : field.getProperty|raw }}</span>
  78. {% endif %}
  79. </th>
  80. {% endif %}
  81. {% endfor %}
  82. <th class="w-1" {% if ea.crud.showEntityActionsAsDropdown %}width="10px"{% endif %}
  83. dir="{{ ea.i18n.textDirection }}">
  84. <span class="sr-only">{{ 'action.entity_actions'|trans(ea.i18n.translationParameters, 'EasyAdminBundle') }}</span>
  85. </th>
  86. </tr>
  87. {% endblock table_head %}
  88. </thead>
  89. <tbody>
  90. {% block table_body %}
  91. {% for entity in entities %}
  92. {% if not entity.isAccessible %}
  93. {% set some_results_are_hidden = true %}
  94. {% else %}
  95. <tr data-id="{{ entity.primaryKeyValueAsString }}">
  96. {% if has_batch_actions %}
  97. <td><input type="checkbox" class="form-batch-checkbox"
  98. value="{{ entity.primaryKeyValue }}"></td>
  99. {% endif %}
  100. {% for field in entity.fields %}
  101. <td class="{{ field.property == sort_field_name ? 'sorted' }} text-{{ field.textAlign }} {{ field.cssClass }}"
  102. dir="{{ ea.i18n.textDirection }}">
  103. {{ include(field.templatePath, { field: field, entity: entity }, with_context = false) }}
  104. </td>
  105. {% endfor %}
  106. {% block entity_actions %}
  107. <td class="actions text-right">
  108. {% set in_dropdown_class = 'in-dropdown' %}
  109. {% for action in entity.actions %}
  110. {% if not (in_dropdown_class in action.cssClass) %}
  111. {{ include(action.templatePath, { action: action, entity: entity, isIncludedInDropdown: 0 }, with_context = false) }}
  112. {% endif %}
  113. {% endfor %}
  114. <div class="dropdown dropdown-actions">
  115. <a class="dropdown-toggle btn btn-secondary btn-sm" href="#"
  116. role="button" data-toggle="dropdown" aria-haspopup="true"
  117. aria-expanded="false">
  118. </a>
  119. <div class="dropdown-menu dropdown-menu-right">
  120. {% for action in entity.actions %}
  121. {% if in_dropdown_class in action.cssClass %}
  122. {{ include(action.templatePath, { action: action, isIncludedInDropdown: 1 }, with_context = false) }}
  123. {% endif %}
  124. {% endfor %}
  125. </div>
  126. </div>
  127. {% if not ea.crud.showEntityActionsAsDropdown %}
  128. {% else %}
  129. {% endif %}
  130. </td>
  131. {% endblock entity_actions %}
  132. </tr>
  133. {% endif %}
  134. {% else %}
  135. <tr>
  136. <td class="no-results" colspan="100">
  137. {{ 'datagrid.no_results'|trans(ea.i18n.translationParameters, 'EasyAdminBundle') }}
  138. </td>
  139. </tr>
  140. {% endfor %}
  141. {% if some_results_are_hidden %}
  142. <tr class="datagrid-row-empty">
  143. <td class="text-center" colspan="{{ entities|first.fields|length + 1 }}">
  144. <span class="datagrid-row-empty-message"><i
  145. class="fa fa-lock mr-1"></i> {{ 'datagrid.hidden_results'|trans({}, 'EasyAdminBundle') }}</span>
  146. </td>
  147. </tr>
  148. {% endif %}
  149. {% endblock table_body %}
  150. </tbody>
  151. </table>
  152. </div>
  153. {% endblock %}
  154. {% block footer %}
  155. <div class="row">
  156. {% block paginator %}
  157. {{ include(ea.templatePath('crud/paginator')) }}
  158. {% endblock paginator %}
  159. </div>
  160. {% endblock %}
  161. {% endembed %}
  162. {% block delete_form %}
  163. {{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', with_context = false) }}
  164. {% endblock delete_form %}
  165. {% if has_filters %}
  166. {{ include('@EasyAdmin/crud/includes/_filters_modal.html.twig') }}
  167. {% endif %}
  168. {% if has_batch_actions %}
  169. {{ include('@EasyAdmin/crud/includes/_batch_action_modal.html.twig', {}, with_context = false) }}
  170. {% endif %}
  171. {% endblock main %}
  172. {% block body_javascript %}
  173. {{ parent() }}
  174. <script type="text/javascript">
  175. $(function () {
  176. /* $('.action-delete').on('click', function (e) {
  177. e.preventDefault();
  178. const formAction = $(this).attr('formaction');
  179. $('#modal-delete').modal({backdrop: true, keyboard: true})
  180. .off('click', '#modal-delete-button')
  181. .on('click', '#modal-delete-button', function () {
  182. let deleteForm = $('#delete-form');
  183. deleteForm.attr('action', formAction);
  184. deleteForm.submit();
  185. });
  186. });*/
  187. {% if filters|length > 0 %}
  188. const filterModal = document.querySelector('#modal-filters');
  189. const removeFilter = function (field) {
  190. field.closest('form').querySelectorAll('input[name^="filters[' + field.dataset.filterProperty + ']"]').forEach(hidden => {
  191. hidden.remove();
  192. });
  193. field.remove();
  194. }
  195. document.querySelector('#modal-clear-button').addEventListener('click', function () {
  196. filterModal.querySelectorAll('.filter-field').forEach(filterField => {
  197. removeFilter(filterField);
  198. });
  199. filterModal.querySelector('form').submit();
  200. });
  201. document.querySelector('#modal-apply-button').addEventListener('click', function () {
  202. filterModal.querySelectorAll('.filter-checkbox:not(:checked)').forEach(notAppliedFilter => {
  203. removeFilter(notAppliedFilter.closest('.filter-field'));
  204. });
  205. filterModal.querySelector('form').submit();
  206. });
  207. // HTML5 specifies that a <script> tag inserted with innerHTML should not execute
  208. // https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#Security_considerations
  209. // That's why we can't use just 'innerHTML'. See https://stackoverflow.com/a/47614491/2804294
  210. let setInnerHTML = function (element, htmlContent) {
  211. element.innerHTML = htmlContent;
  212. Array.from(element.querySelectorAll('script')).forEach(oldScript => {
  213. const newScript = document.createElement('script');
  214. Array.from(oldScript.attributes)
  215. .forEach(attr => newScript.setAttribute(attr.name, attr.value));
  216. newScript.appendChild(document.createTextNode(oldScript.innerHTML));
  217. oldScript.parentNode.replaceChild(newScript, oldScript);
  218. });
  219. };
  220. let filterButton = document.querySelector('.action-filters-button');
  221. filterButton.addEventListener('click', function (event) {
  222. let filterModal = document.querySelector(filterButton.dataset.modal);
  223. let filterModalBody = filterModal.querySelector('.modal-body');
  224. $(filterModal).modal({backdrop: true, keyboard: true});
  225. filterModalBody.innerHTML = '<div class="fa-3x px-3 py-3 text-muted text-center"><i class="fas fa-circle-notch fa-spin"></i></div>';
  226. $.get(filterButton.getAttribute('href'), function (response) {
  227. setInnerHTML(filterModalBody, response);
  228. });
  229. event.preventDefault();
  230. event.stopPropagation();
  231. });
  232. filterButton.setAttribute('href', filterButton.getAttribute('data-href'));
  233. filterButton.removeAttribute('data-href');
  234. filterButton.classList.remove('disabled');
  235. {% endif %}
  236. {% if has_batch_actions %}
  237. {% endif %}
  238. });
  239. </script>
  240. {% if app.request.get('query') is not empty %}
  241. <script type="text/javascript">
  242. const search_query = "{{ ea.search.query|default('')|e('js') }}";
  243. // the original query is prepended to allow matching exact phrases in addition to single words
  244. $('#main').find('table tbody td:not(.actions)').highlight($.merge([search_query], search_query.split(' ')));
  245. </script>
  246. {% endif %}
  247. {% endblock %}