use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController; | use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField; | use EasyCorp\Bundle\EasyAdminBundle\Field\FormField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | ||||
use Lc\SovBundle\Doctrine\EntityManager; | |||||
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface; | use Lc\SovBundle\Doctrine\Extension\DevAliasInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\SeoInterface; | use Lc\SovBundle\Doctrine\Extension\SeoInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface; | use Lc\SovBundle\Doctrine\Extension\TranslatableInterface; | ||||
use Lc\SovBundle\Field\GalleryManagerField; | |||||
use Lc\SovBundle\Field\ImageManagerField; | |||||
use Lc\SovBundle\Field\StatusField; | |||||
use Symfony\Component\HttpFoundation\RequestStack; | use Symfony\Component\HttpFoundation\RequestStack; | ||||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | use Symfony\Component\HttpFoundation\Session\SessionInterface; | ||||
use Twig\Environment; | |||||
abstract class AbstractCrudController extends EaAbstractCrudController | abstract class AbstractCrudController extends EaAbstractCrudController | ||||
{ | { | ||||
protected $session; | protected $session; | ||||
protected $request; | protected $request; | ||||
public function __construct(SessionInterface $session, RequestStack $request) | |||||
public function __construct(SessionInterface $session, RequestStack $request, EntityManager $em, Environment $twig) | |||||
{ | { | ||||
$this->session = $session; | $this->session = $session; | ||||
$this->request = $request; | $this->request = $request; | ||||
$this->em = $em; | |||||
$this->twig = $twig; | |||||
} | } | ||||
public function configureActions(Actions $actions): Actions | public function configureActions(Actions $actions): Actions | ||||
); | ); | ||||
} | } | ||||
$actionSaveAndReturn = [ | |||||
'add-class' => 'float-right', | |||||
'icon' => 'check', | |||||
]; | |||||
$actionIndex = [ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
]; | |||||
/* Boutons des actions dans les listes */ | /* Boutons des actions dans les listes */ | ||||
$actionsArray[Crud::PAGE_INDEX] = [ | $actionsArray[Crud::PAGE_INDEX] = [ | ||||
Action::NEW => [ | |||||
'icon' => 'plus', | |||||
'label' => 'Créer', | |||||
], | |||||
Action::EDIT => [ | Action::EDIT => [ | ||||
'class' => 'btn btn-sm btn-primary', | 'class' => 'btn btn-sm btn-primary', | ||||
'icon' => 'edit', | 'icon' => 'edit', | ||||
'label' => false, | 'label' => false, | ||||
], | ], | ||||
Action::DELETE => [ | Action::DELETE => [ | ||||
'class' => 'btn btn-sm btn-default action-delete', | |||||
'icon' => 'trash', | 'icon' => 'trash', | ||||
'label' => false, | |||||
'dropdown' => true, | |||||
], | |||||
Action::BATCH_DELETE => [ | |||||
'class' => 'btn btn-danger', | |||||
'icon' => 'trash', | |||||
], | ], | ||||
]; | ]; | ||||
/* Boutons des actions dans l'édition */ | /* Boutons des actions dans l'édition */ | ||||
$actionSaveAndReturn = [ | |||||
'add-class' => 'float-right', | |||||
'icon' => 'check', | |||||
]; | |||||
$actionIndex = [ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
]; | |||||
$actionsArray[Crud::PAGE_EDIT] = [ | $actionsArray[Crud::PAGE_EDIT] = [ | ||||
Action::SAVE_AND_CONTINUE => [ | Action::SAVE_AND_CONTINUE => [ | ||||
'class' => 'btn btn-info float-right', | 'class' => 'btn btn-info float-right', | ||||
Action::SAVE_AND_RETURN => $actionSaveAndReturn, | Action::SAVE_AND_RETURN => $actionSaveAndReturn, | ||||
Action::INDEX => $actionIndex, | Action::INDEX => $actionIndex, | ||||
]; | ]; | ||||
$actionsArray[Crud::PAGE_NEW] = [ | $actionsArray[Crud::PAGE_NEW] = [ | ||||
Action::SAVE_AND_ADD_ANOTHER => [ | Action::SAVE_AND_ADD_ANOTHER => [ | ||||
'class' => 'btn btn-info float-right', | 'class' => 'btn btn-info float-right', | ||||
if (isset($button['add-class'])) { | if (isset($button['add-class'])) { | ||||
$action->addCssClass($button['add-class']); | $action->addCssClass($button['add-class']); | ||||
} | } | ||||
if (isset($button['class'])) { | if (isset($button['class'])) { | ||||
$action->setCssClass($button['class']); | $action->setCssClass($button['class']); | ||||
} | } | ||||
if (isset($button['icon'])) { | if (isset($button['icon'])) { | ||||
$action->setIcon('fa fa-'.$button['icon']); | $action->setIcon('fa fa-'.$button['icon']); | ||||
} | } | ||||
if (isset($button['label'])) { | if (isset($button['label'])) { | ||||
$action->setLabel($button['label']); | $action->setLabel($button['label']); | ||||
} | } | ||||
if (isset($button['dropdown']) && $button['dropdown']) { | |||||
$action->addCssClass('in-dropdown'); | |||||
} | |||||
return $action; | return $action; | ||||
} | } | ||||
public function configureCrud(Crud $crud): Crud | public function configureCrud(Crud $crud): Crud | ||||
{ | { | ||||
$crud = parent::configureCrud($crud);; | |||||
$crud = parent::configureCrud($crud); | |||||
$this->setMaxResults($crud); | $this->setMaxResults($crud); | ||||
$crud->setPaginatorPageSize($maxResults); | $crud->setPaginatorPageSize($maxResults); | ||||
} | } | ||||
public function index(AdminContext $context) | |||||
{ | |||||
$responseParameters = parent::index($context); | |||||
// Liste des fields | |||||
$responseParameters->set('fields', $this->configureFields('index')); | |||||
return $responseParameters; | |||||
} | |||||
public function configureFields(string $pageName): iterable | public function configureFields(string $pageName): iterable | ||||
{ | { | ||||
if (in_array(SeoInterface::class, class_implements($this->getEntityFqcn()))) { | if (in_array(SeoInterface::class, class_implements($this->getEntityFqcn()))) { | ||||
$seoPanel = [ | $seoPanel = [ | ||||
FormField::addPanel('Seo'), | FormField::addPanel('Seo'), | ||||
TextareaField::new('metaTitle')->setLabel('Meta Title')->setHelp('Affiché dans les résultats de recherche Google'), | |||||
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp('Affiché dans les résultats de recherche Google'), | |||||
TextareaField::new('metaTitle')->setLabel('Meta Title')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
), | |||||
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
), | |||||
]; | ]; | ||||
} | } | ||||
if (in_array(DevAliasInterface::class, class_implements($this->getEntityFqcn()))) { | if (in_array(DevAliasInterface::class, class_implements($this->getEntityFqcn()))) { | ||||
$confPanel = [ | $confPanel = [ | ||||
FormField::addPanel('Conf'), | FormField::addPanel('Conf'), | ||||
TextField::new('devAlias') | |||||
TextField::new('devAlias'), | |||||
]; | ]; | ||||
} | } | ||||
return array_merge($seoPanel, $confPanel); | return array_merge($seoPanel, $confPanel); | ||||
} | } | ||||
} | } | ||||
public function configureAssets(): Assets | public function configureAssets(): Assets | ||||
{ | { | ||||
$assets = parent::configureAssets(); | $assets = parent::configureAssets(); | ||||
$assets->addWebpackEncoreEntry('adminlte-common'); | $assets->addWebpackEncoreEntry('adminlte-common'); | ||||
$assets->addWebpackEncoreEntry('adminlte-index'); | |||||
return $assets; | return $assets; | ||||
} | } |
import 'adminlte-plugin/select2/css/select2.min.css'; | import 'adminlte-plugin/select2/css/select2.min.css'; | ||||
import 'adminlte-plugin/select2-bootstrap4-theme/select2-bootstrap4.min.css'; | import 'adminlte-plugin/select2-bootstrap4-theme/select2-bootstrap4.min.css'; | ||||
// Toastr | |||||
import toastr from 'toastr/toastr.js' ; | |||||
import 'toastr/toastr.scss' ; | |||||
global.toastr = toastr ; | |||||
// Tools | // Tools | ||||
import { Tools } from '../../../tools/tools.js'; | import { Tools } from '../../../tools/tools.js'; | ||||
global.Tools = Tools; | global.Tools = Tools; | ||||
import { Notification } from './js/notification.js'; | |||||
global.Notification = Notification; | |||||
// Common | // Common | ||||
import './common.scss'; | import './common.scss'; | ||||
import './common.js' | |||||
import './common.js' ; | |||||
@import 'scss/form/footer'; | @import 'scss/form/footer'; | ||||
@import 'scss/card'; | @import 'scss/card'; | ||||
@import 'scss/modal'; | @import 'scss/modal'; | ||||
@import 'scss/toastr'; | |||||
export class Notification { | |||||
static setNotifications(notifications) { | |||||
var currentNotifications = new Array(); | |||||
for (var type in notifications) { | |||||
for (var key in notifications[type]) { | |||||
if (!currentNotifications.includes(notifications[type][key])) { | |||||
currentNotifications.push(notifications[type][key]); | |||||
self.addNotification(type, notifications[type][key]); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
static addNotification(type, text) { | |||||
toastr.options.timeOut = 3000; | |||||
toastr.options.onHidden = function () { | |||||
if ($('#toast-container .toast').length == 0) $('#toast-close-all').remove(); | |||||
}; | |||||
toastr[type](text); | |||||
if ($('#toast-close-all').length == 0) { | |||||
$('#toast-container').prepend('<button id="toast-close-all"><i class="fa fa-times"></i></button>'); | |||||
} | |||||
$('#toast-close-all').off('click'); | |||||
$('#toast-close-all').on('click', function () { | |||||
toastr.remove(); | |||||
if ($('#toast-container .toast').length == 0) $('#toast-close-all').remove(); | |||||
}); | |||||
} | |||||
} |
#toast-container { | |||||
width: 350px; | |||||
} | |||||
.toast { | |||||
float: right | |||||
} | |||||
#toast-container:before:hover { | |||||
opacity: 1; | |||||
cursor: pointer; | |||||
} | |||||
#toast-close-all { | |||||
border: 0; | |||||
position: absolute; | |||||
pointer-events: auto; | |||||
z-index: 999999999999999999999; | |||||
background: #BD362F; | |||||
border-radius: 3px; | |||||
color: #fff; | |||||
opacity: 0.8; | |||||
top: 2px; | |||||
width: 50px; | |||||
height: 50px; | |||||
font-size: 30px; | |||||
left: 0px; | |||||
text-align: center; | |||||
-webkit-text-shadow: 0 1px 0 #fff; | |||||
text-shadow: 0 1px 0 #fff; | |||||
-moz-box-shadow: 0 0 12px #999; | |||||
-webkit-box-shadow: 0 0 12px #999; | |||||
box-shadow: 0 0 12px #999; | |||||
} | |||||
import './index.js' | |||||
import './index.scss' |
$(document).ready(function() { | |||||
lcCrudIndexToggle() ; | |||||
lcCrudIndexBatchActions() ; | |||||
}) ; | |||||
function lcCrudIndexToggle() { | |||||
const toggles = document.querySelectorAll('.custom-switch input[type="checkbox"]'); | |||||
for (i = 0; i < toggles.length; i++) { | |||||
toggles[i].addEventListener('change', function () { | |||||
const toggle = this; | |||||
const newValue = this.checked; | |||||
const oldValue = !newValue; | |||||
const toggleUrl = this.closest('.custom-switch').dataset.url + "&newValue=" + newValue.toString(); | |||||
let toggleRequest = $.ajax({type: "POST", url: toggleUrl, data: {}, dataType: 'json'}); | |||||
toggleRequest.done(function (response) { | |||||
Notification.addNotification('success', 'La propriété a bien été mise à jour.'); | |||||
}); | |||||
toggleRequest.fail(function () { | |||||
toggle.checked = oldValue; | |||||
toggle.disabled = true; | |||||
toggle.closest('.checkbox-switch').classList.add('disabled'); | |||||
Notification.addNotification('error', 'Une erreur est survenue.'); | |||||
}); | |||||
}); | |||||
} | |||||
} | |||||
function lcCrudIndexBatchActions() { | |||||
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-wrapper'); | |||||
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(); | |||||
}); | |||||
}); | |||||
} |
table.table { | |||||
.dropdown-actions { | |||||
display: inline-block ; | |||||
} | |||||
} |
{% block id %}{{ id_modal }}{% endblock %} | {% block id %}{{ id_modal }}{% endblock %} | ||||
{% block size %}modal-xl{% endblock %} | {% block size %}modal-xl{% endblock %} | ||||
{% block title %}{{ field.value.legend ? field.value.legend : 'Image' }}{% endblock %} | {% block title %}{{ field.value.legend ? field.value.legend : 'Image' }}{% endblock %} | ||||
{% block content %} | |||||
{% block body %} | |||||
<img src="{{ lc_liip(field.value.path, 'big') }}" alt="{{ field.value.legend }}" /> | <img src="{{ lc_liip(field.value.path, 'big') }}" alt="{{ field.value.legend }}" /> | ||||
{% endblock %} | {% endblock %} | ||||
{% block footer_wrapper %}{% endblock %} | {% block footer_wrapper %}{% endblock %} |
{% set item = entity.instance %} | {% set item = entity.instance %} | ||||
{% set property_name = field.getProperty() %} | {% set property_name = field.getProperty() %} | ||||
{% set id_toggle = 'toogle-'~item.id~'-'~property_name %} | {% set id_toggle = 'toogle-'~item.id~'-'~property_name %} | ||||
<div class="custom-control custom-switch custom-switch-on-success custom-switch-off-default" | <div class="custom-control custom-switch custom-switch-on-success custom-switch-off-default" | ||||
data-propertyname="{{ property_name }}" data-id={{ item.id }}> | |||||
data-url="{{ ea_url({crudAction: 'edit', entityId: item.id, fieldName: property_name }) }}"> | |||||
<input type="checkbox" class="custom-control-input" id="{{ id_toggle }}" {{ field.value ? 'checked' }}> | <input type="checkbox" class="custom-control-input" id="{{ id_toggle }}" {{ field.value ? 'checked' }}> | ||||
<label class="custom-control-label" for="{{ id_toggle }}"> | <label class="custom-control-label" for="{{ id_toggle }}"> | ||||
{{ field.getCustomOption('toggle_label') ?? field.label }}</label> | {{ field.getCustomOption('toggle_label') ?? field.label }}</label> |
{% set has_filters = filters|length > 0 %} | {% set has_filters = filters|length > 0 %} | ||||
{% set has_datagrid_tools = has_search or has_filters %} | {% set has_datagrid_tools = has_search or has_filters %} | ||||
<div class="card card-table card-outline card-primary"> | |||||
<div class="card-header"> | |||||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||||
{% block css %}card-table card-outline card-primary{% endblock %} | |||||
{% block header %} | |||||
<span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total"> | <span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total"> | ||||
{{ paginator.numResults }} résultats | {{ paginator.numResults }} résultats | ||||
</span> | </span> | ||||
</div> | |||||
<div class="card-body"> | |||||
{% endblock %} | |||||
{% block body %} | |||||
<div class="table-responsive"> | <div class="table-responsive"> | ||||
<table class="table table-bordered table-hover table-striped"> | <table class="table table-bordered table-hover table-striped"> | ||||
<thead> | <thead> | ||||
<tr> | <tr> | ||||
{% if has_batch_actions %} | {% if has_batch_actions %} | ||||
<th class=""><span><input type="checkbox" | |||||
class="form-check-input m-0 align-middle form-batch-checkbox-all"></span> | |||||
<th class=""> | |||||
<input type="hidden" id="batch_form_entityIds" value="" /> | |||||
<span><input type="checkbox" | |||||
class="form-check-input m-0 align-middle form-batch-checkbox-all"></span> | |||||
</th> | </th> | ||||
{% endif %} | {% endif %} | ||||
{% set ea_sort_asc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::ASC') %} | {% set ea_sort_asc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::ASC') %} | ||||
{% set ea_sort_desc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::DESC') %} | {% set ea_sort_desc = constant('EasyCorp\\Bundle\\EasyAdminBundle\\Config\\Option\\SortOrder::DESC') %} | ||||
{% for field in entities|first.fields ?? [] %} | |||||
{% for field in fields ?? [] %} | |||||
{% set field = field.getAsDto() %} | |||||
{% set is_sorting_field = ea.search.isSortingField(field.property) %} | {% 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 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' %} | {% set column_icon = is_sorting_field ? (next_sort_direction == ea_sort_desc ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %} | ||||
</th> | </th> | ||||
{% endfor %} | {% endfor %} | ||||
<th class="w-1" {% if ea.crud.showEntityActionsAsDropdown %}width="10px"{% endif %} dir="{{ ea.i18n.textDirection }}"> | |||||
<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> | <span class="sr-only">{{ 'action.entity_actions'|trans(ea.i18n.translationParameters, 'EasyAdminBundle') }}</span> | ||||
</th> | </th> | ||||
</tr> | </tr> | ||||
{% endfor %} | {% endfor %} | ||||
{% block entity_actions %} | {% block entity_actions %} | ||||
<td class="actions"> | |||||
<td class="actions text-right"> | |||||
{% set in_dropdown_class = 'in-dropdown' %} | |||||
{% for action in entity.actions %} | |||||
{% if not (in_dropdown_class in action.cssClass) %} | |||||
{{ include(action.templatePath, { action: action, entity: entity, isIncludedInDropdown: 0 }, with_context = false) }} | |||||
{% endif %} | |||||
{% endfor %} | |||||
<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"> | |||||
</a> | |||||
<div class="dropdown-menu dropdown-menu-right"> | |||||
{% for action in entity.actions %} | |||||
{% if in_dropdown_class in action.cssClass %} | |||||
{{ include(action.templatePath, { action: action, isIncludedInDropdown: 1 }, with_context = false) }} | |||||
{% endif %} | |||||
{% endfor %} | |||||
</div> | |||||
</div> | |||||
{% if not ea.crud.showEntityActionsAsDropdown %} | {% 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 %} | {% 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 %} | {% endif %} | ||||
</td> | </td> | ||||
{% endblock entity_actions %} | {% endblock entity_actions %} | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
</div> | |||||
{% if entities|length > 0 %} | |||||
<div class="card-footer"> | |||||
<div class="row"> | |||||
{% block paginator %} | |||||
{{ include(ea.templatePath('crud/paginator')) }} | |||||
{% endblock paginator %} | |||||
</div> | |||||
{% endblock %} | |||||
{% block footer %} | |||||
<div class="row"> | |||||
{% block paginator %} | |||||
{{ include(ea.templatePath('crud/paginator')) }} | |||||
{% endblock paginator %} | |||||
</div> | </div> | ||||
{% endif %} | |||||
</div> | |||||
{% endblock %} | |||||
{% endembed %} | |||||
{% block delete_form %} | {% block delete_form %} | ||||
{{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', with_context = false) }} | {{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', with_context = false) }} | ||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
$(function () { | $(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'); | |||||
/* $('.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(); | |||||
}); | |||||
});*/ | |||||
$('#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 %} | {% if filters|length > 0 %} | ||||
const filterModal = document.querySelector('#modal-filters'); | const filterModal = document.querySelector('#modal-filters'); | ||||
{% if has_batch_actions %} | {% 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 %} | {% endif %} | ||||
}); | }); | ||||
</script> | </script> |
<div class="card {% block css %}{% endblock %}" id="{% block id %}{% endblock %}"> | |||||
{% block header_wrapper %} | |||||
<div class="card-header"> | |||||
{% block header %} | |||||
{% endblock header %} | |||||
</div> | |||||
{% endblock header_wrapper %} | |||||
{% block body_wrapper %} | |||||
<div class="card-body"> | |||||
{% block body %} | |||||
{% endblock %} | |||||
</div> | |||||
{% endblock body_wrapper %} | |||||
{% block footer_wrapper %} | |||||
<div class="card-footer"> | |||||
{% block footer %} | |||||
{% endblock footer %} | |||||
</div> | |||||
{% endblock footer_wrapper %} | |||||
</div> |
<div class="modal fade show" id="{% block id %}{% endblock %}"> | <div class="modal fade show" id="{% block id %}{% endblock %}"> | ||||
<div class="modal-dialog {% block size %}{% endblock %}"> | <div class="modal-dialog {% block size %}{% endblock %}"> | ||||
{% block form_start %}{% endblock %} | {% block form_start %}{% endblock %} | ||||
<div class="modal-content"> | <div class="modal-content"> | ||||
</button> | </button> | ||||
</div> | </div> | ||||
<div class="modal-body"> | <div class="modal-body"> | ||||
{% block content %} | |||||
{% block body %} | |||||
{% endblock %} | {% endblock %} | ||||
</div> | </div> | ||||
{% block footer_wrapper %} | {% block footer_wrapper %} | ||||
{% block form_end %}{% endblock %} | {% block form_end %}{% endblock %} | ||||
<!-- /.modal-content --> | <!-- /.modal-content --> | ||||
</div> | </div> | ||||
</div> | </div> |