@@ -37,12 +37,13 @@ class DashboardAdminController extends AbstractDashboardController | |||
{ | |||
$assets = parent::configureAssets(); | |||
$assets->addWebpackEncoreEntry('adminlte-common'); | |||
$assets->addWebpackEncoreEntry('adminlte-plugins'); | |||
$assets->addWebpackEncoreEntry('adminlte-index'); | |||
$assets->addWebpackEncoreEntry('adminlte-form'); | |||
$assets->addWebpackEncoreEntry('adminlte-sort'); | |||
$assets->addWebpackEncoreEntry('adminlte-field-collection'); | |||
$assets->addWebpackEncoreEntry('adminlte-field-filemanager'); | |||
$assets->addWebpackEncoreEntry('adminlte-main'); | |||
$assets->addWebpackEncoreEntry('sov-reminder'); | |||
return $assets; | |||
@@ -83,8 +84,8 @@ class DashboardAdminController extends AbstractDashboardController | |||
'main_menu' => '@LcSov/adminlte/block/menu.html.twig', | |||
'crud/index' => '@LcSov/adminlte/crud/index.html.twig', | |||
'crud/paginator' => '@LcSov/adminlte/crud/paginator.html.twig', | |||
'crud/edit' => '@LcSov/adminlte/crud/edit.html.twig', | |||
'crud/new' => '@LcSov/adminlte/crud/new.html.twig', | |||
'crud/edit' => '@LcSov/adminlte/crud/form.html.twig', | |||
'crud/new' => '@LcSov/adminlte/crud/form.html.twig', | |||
'flash_messages' => '@LcSov/adminlte/block/flash_messages.html.twig', | |||
] | |||
) |
@@ -12,11 +12,8 @@ use Lc\SovBundle\Field\StatusField; | |||
abstract class NewsletterAdminController extends AbstractAdminController | |||
{ | |||
public function configureFields(string $pageName): iterable | |||
{ | |||
$panel = parent::configureFields($pageName); | |||
return array_merge( | |||
[ | |||
FormField::addPanel('general'), | |||
@@ -27,7 +24,8 @@ abstract class NewsletterAdminController extends AbstractAdminController | |||
->hideOnIndex(), | |||
StatusField::new('status'), | |||
], | |||
$panel | |||
$this->getSeoPanel(), | |||
$this->getConfPanel() | |||
); | |||
} | |||
@@ -0,0 +1,11 @@ | |||
<?php | |||
namespace Lc\SovBundle\Repository; | |||
abstract class AbstractStore | |||
{ | |||
public function getRepositoryQuery() | |||
{ | |||
return $this->query; | |||
} | |||
} |
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\File; | |||
class FileStore implements FileStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class FileStore extends AbstractStore implements FileStoreInterface | |||
{ | |||
protected FileRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Newsletter; | |||
class NewsletterStore implements NewsletterStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class NewsletterStore extends AbstractStore implements NewsletterStoreInterface | |||
{ | |||
protected NewsletterRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Reminder; | |||
class ReminderStore implements ReminderStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class ReminderStore extends AbstractStore implements ReminderStoreInterface | |||
{ | |||
protected ReminderRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Setting; | |||
class SiteSettingStore implements SiteSettingStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class SiteSettingStore extends AbstractStore implements SiteSettingStoreInterface | |||
{ | |||
protected SiteSettingRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Site; | |||
class NewsStore implements NewsStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class NewsStore extends AbstractStore implements NewsStoreInterface | |||
{ | |||
protected NewsRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Site; | |||
class PageStore implements PageStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class PageStore extends AbstractStore implements PageStoreInterface | |||
{ | |||
protected PageRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Site; | |||
class SiteStore implements SiteStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class SiteStore extends AbstractStore implements SiteStoreInterface | |||
{ | |||
protected SiteRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Ticket; | |||
class TicketMessageStore implements TicketMessageStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class TicketMessageStore extends AbstractStore implements TicketMessageStoreInterface | |||
{ | |||
protected TicketMessageRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\Ticket; | |||
class TicketStore implements TicketStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class TicketStore extends AbstractStore implements TicketStoreInterface | |||
{ | |||
protected TicketRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\User; | |||
class GroupUserStore implements GroupUserStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class GroupUserStore extends AbstractStore implements GroupUserStoreInterface | |||
{ | |||
protected GroupUserRepositoryQueryInterface $query; | |||
@@ -2,7 +2,9 @@ | |||
namespace Lc\SovBundle\Repository\User; | |||
class UserStore implements UserStoreInterface | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class UserStore extends AbstractStore implements UserStoreInterface | |||
{ | |||
protected UserRepositoryQueryInterface $query; | |||
@@ -25,7 +25,7 @@ function initReminder() { | |||
id: $(this).data('id'), | |||
done: $(this).is(':checked') | |||
}, function(data) { | |||
Notification.add('success', 'Pense-bête mis à jour'); | |||
SovNotification.add('success', 'Pense-bête mis à jour'); | |||
}, 'json'); | |||
}) ; | |||
} |
@@ -7,9 +7,9 @@ jQuery(document).ready(function () { | |||
dataType: "json", | |||
success: function (data) { | |||
if (data.success) { | |||
Notification.add('success', 'Le status a bien été mise à jour.'); | |||
SovNotification.add('success', 'Le status a bien été mise à jour.'); | |||
} else { | |||
Notification.add('danger', 'Une erreur est survenue.'); | |||
SovNotification.add('danger', 'Une erreur est survenue.'); | |||
} | |||
} | |||
}); |
@@ -1,155 +0,0 @@ | |||
/* Notifications */ | |||
//Notification.init() ; | |||
setDateRange(); | |||
setAutoCompleteField(); | |||
/* Tooltip */ | |||
$('[data-toggle="tooltip"]').tooltip(); | |||
/* Select2 */ | |||
if ($('.select2, select.form-control').length) { | |||
$('form .form-widget>select.form-control, .select2').each(function (i, elm) { | |||
if (!$(this).hasClass('disable-select2')) { | |||
setSelect2($(elm)); | |||
} | |||
}); | |||
$('form select.form-control').each(function (i, elm) { | |||
if (!$(this).hasClass('disable-select2')) { | |||
setSelect2($(elm)); | |||
} | |||
}); | |||
} | |||
function setSelect2($select) { | |||
if (typeof $select.data('select2-id') === 'undefined') { | |||
$select.data('init', 'set') | |||
var options = { | |||
width: "100%", | |||
theme: "bootstrap4", | |||
dropdownAutoWidth: false, | |||
allowClear: true, | |||
minimumResultsForSearch: 8 | |||
}; | |||
if ($select.data('allow-clear') == 'false') { | |||
options.allowClear = false; | |||
} | |||
if ($select.data('width')) { | |||
options.width = 'auto' | |||
} | |||
if ($select.find('option[value=""]')) { | |||
options.placeholder = $select.find('option[value=""]').html() | |||
} | |||
/*if($select.is(':required') == false) { | |||
options.allowclear = true | |||
}*/ | |||
var myselect = $select.select2(options); | |||
myselect.on('select2:select', function (e) { | |||
var event = new Event('change'); | |||
e.target.dispatchEvent(event); | |||
}); | |||
myselect.on('select2:unselect', function (e) { | |||
var event = new Event('change'); | |||
e.target.dispatchEvent(event); | |||
}); | |||
return myselect; | |||
} | |||
} | |||
$('.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(); | |||
}); | |||
}); | |||
function setDateRange(){ | |||
$('.date-time-range, .date-range').each(function (i, picker) { | |||
options = { | |||
autoUpdateInput: false, | |||
locale: { | |||
"format": "DD/MM/YY", | |||
"separator": " - ", | |||
"applyLabel": "Appliquer", | |||
"cancelLabel": "Annuler", | |||
"fromLabel": "Du", | |||
"toLabel": "au", | |||
"customRangeLabel": "Custom", | |||
"daysOfWeek": ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], | |||
"monthNames": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], | |||
"firstDay": 1 | |||
} | |||
}; | |||
if ($(picker).hasClass('date-time-range')){ | |||
options = Object.assign(options, { | |||
timePicker: true, | |||
timePickerIncrement: 30, | |||
timePicker24Hour: true, | |||
locale: { | |||
"format": "DD/MM/YYYY HH:mm", | |||
} | |||
}); | |||
} | |||
if ($(picker).nextAll('.date-time-range-fields').find('.date-start').val()) { | |||
options.startDate = new Date($(picker).nextAll('.date-time-range-fields').find('.date-start').val()); | |||
options.autoUpdateInput = true; | |||
} | |||
if ($(picker).nextAll('.date-time-range-fields').find('.date-end').val()) { | |||
options.endDate = new Date($(picker).nextAll('.date-time-range-fields').find('.date-end').val()); | |||
options.autoUpdateInput = true; | |||
} | |||
$(picker).daterangepicker(options); | |||
$(picker).on('apply.daterangepicker', function (ev, pickerElm) { | |||
if ($(picker).hasClass('date-time-range')) { | |||
$(this).val(pickerElm.startDate.format('DD/MM/YY HH:mm') + ' - ' + pickerElm.endDate.format(options.locale.format)); | |||
}else{ | |||
$(this).val(pickerElm.startDate.format('DD/MM/YY') + ' - ' + pickerElm.endDate.format(options.locale.format)); | |||
} | |||
if ($(picker).hasClass('date-time-range')) { | |||
$(picker).nextAll('.date-time-range-fields').find('.date-start').val(pickerElm.startDate.format('YYYY-MM-DD HH:mm')); | |||
$(picker).nextAll('.date-time-range-fields').find('.date-end').val(pickerElm.endDate.format('YYYY-MM-DD HH:mm')); | |||
}else{ | |||
$(picker).nextAll('.date-time-range-fields').find('.date-start').val(pickerElm.startDate.format('YYYY-MM-DD')); | |||
$(picker).nextAll('.date-time-range-fields').find('.date-end').val(pickerElm.endDate.format('YYYY-MM-DD')); | |||
} | |||
}); | |||
}); | |||
} | |||
function setAutoCompleteField() { | |||
var autocompleteFields = $('[data-lc-autocomplete-url]'); | |||
autocompleteFields.each(function () { | |||
var $this = $(this), | |||
url = $this.data('lc-autocomplete-url'); | |||
$this.autoComplete({ | |||
noResultsText: 'Aucun résultat n\'a été trouvé.', | |||
resolverSettings: { | |||
url: url | |||
} | |||
}); | |||
}); | |||
} |
@@ -1,7 +0,0 @@ | |||
function log(name) { | |||
try { | |||
return console.log(name); | |||
} catch (e) { | |||
return null; | |||
} | |||
} |
@@ -18,14 +18,14 @@ function lcCrudIndexToggle() { | |||
let toggleRequest = $.ajax({type: "POST", url: toggleUrl, data: {}, dataType: 'json'}); | |||
toggleRequest.done(function (response) { | |||
Notification.add('success', 'La propriété a bien été mise à jour.'); | |||
SovNotification.add('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.add('error', 'Une erreur est survenue.'); | |||
SovNotification.add('error', 'Une erreur est survenue.'); | |||
}); | |||
}); | |||
} |
@@ -0,0 +1,3 @@ | |||
import './init.js'; | |||
import './common.scss'; |
@@ -0,0 +1,37 @@ | |||
SovNotification.init() ; | |||
SovWidgets.setDateRange(); | |||
SovWidgets.setAutoCompleteField(); | |||
/* Tooltip */ | |||
$('[data-toggle="tooltip"]').tooltip(); | |||
/* Select2 */ | |||
if ($('.select2, select.form-control').length) { | |||
$('form .form-widget>select.form-control, .select2').each(function (i, elm) { | |||
if (!$(this).hasClass('disable-select2')) { | |||
SovWidgets.setSelect2($(elm)); | |||
} | |||
}); | |||
$('form select.form-control').each(function (i, elm) { | |||
if (!$(this).hasClass('disable-select2')) { | |||
SovWidgets.setSelect2($(elm)); | |||
} | |||
}); | |||
} | |||
$('.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(); | |||
}); | |||
}); |
@@ -23,23 +23,22 @@ import toastr from 'toastr/toastr.js' ; | |||
import 'toastr/toastr.scss' ; | |||
global.toastr = toastr ; | |||
// DaterangePicker | |||
import 'moment' ; | |||
import 'daterangepicker/daterangepicker.js' ; | |||
import 'daterangepicker/daterangepicker.css' ; | |||
// Tools | |||
import { Tools } from '../../../tools/tools.js'; | |||
global.Tools = Tools; | |||
import { SovTools } from '../../../functions/tools.js'; | |||
global.SovTools = SovTools; | |||
// Widgets | |||
import { SovWidgets } from '../../../functions/widgets.js'; | |||
global.SovWidgets = SovWidgets; | |||
import { Notification } from './js/notification.js'; | |||
global.Notification = Notification; | |||
Notification.init() ; | |||
import { SovNotification } from '../../../functions/notification.js'; | |||
global.SovNotification = SovNotification; | |||
// Common | |||
import './common.scss'; | |||
import './common.js' ; | |||
@@ -1,5 +1,5 @@ | |||
export class Notification { | |||
export class SovNotification { | |||
static init() { | |||
toastr.options.timeOut = 3000; |
@@ -1,5 +1,5 @@ | |||
export class Tools { | |||
export class SovTools { | |||
static log(value) { | |||
try { |
@@ -0,0 +1,111 @@ | |||
export class SovWidgets { | |||
static setSelect2($select) { | |||
if (typeof $select.data('select2-id') === 'undefined') { | |||
$select.data('init', 'set') | |||
var options = { | |||
width: "100%", | |||
theme: "bootstrap4", | |||
dropdownAutoWidth: false, | |||
allowClear: true, | |||
minimumResultsForSearch: 8 | |||
}; | |||
if ($select.data('allow-clear') == 'false') { | |||
options.allowClear = false; | |||
} | |||
if ($select.data('width')) { | |||
options.width = 'auto' | |||
} | |||
if ($select.find('option[value=""]')) { | |||
options.placeholder = $select.find('option[value=""]').html() | |||
} | |||
/*if($select.is(':required') == false) { | |||
options.allowclear = true | |||
}*/ | |||
var myselect = $select.select2(options); | |||
myselect.on('select2:select', function (e) { | |||
var event = new Event('change'); | |||
e.target.dispatchEvent(event); | |||
}); | |||
myselect.on('select2:unselect', function (e) { | |||
var event = new Event('change'); | |||
e.target.dispatchEvent(event); | |||
}); | |||
return myselect; | |||
} | |||
} | |||
static setDateRange() { | |||
$('.date-time-range, .date-range').each(function (i, picker) { | |||
options = { | |||
autoUpdateInput: false, | |||
locale: { | |||
"format": "DD/MM/YY", | |||
"separator": " - ", | |||
"applyLabel": "Appliquer", | |||
"cancelLabel": "Annuler", | |||
"fromLabel": "Du", | |||
"toLabel": "au", | |||
"customRangeLabel": "Custom", | |||
"daysOfWeek": ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], | |||
"monthNames": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], | |||
"firstDay": 1 | |||
} | |||
}; | |||
if ($(picker).hasClass('date-time-range')) { | |||
options = Object.assign(options, { | |||
timePicker: true, | |||
timePickerIncrement: 30, | |||
timePicker24Hour: true, | |||
locale: { | |||
"format": "DD/MM/YYYY HH:mm", | |||
} | |||
}); | |||
} | |||
if ($(picker).nextAll('.date-time-range-fields').find('.date-start').val()) { | |||
options.startDate = new Date($(picker).nextAll('.date-time-range-fields').find('.date-start').val()); | |||
options.autoUpdateInput = true; | |||
} | |||
if ($(picker).nextAll('.date-time-range-fields').find('.date-end').val()) { | |||
options.endDate = new Date($(picker).nextAll('.date-time-range-fields').find('.date-end').val()); | |||
options.autoUpdateInput = true; | |||
} | |||
$(picker).daterangepicker(options); | |||
$(picker).on('apply.daterangepicker', function (ev, pickerElm) { | |||
if ($(picker).hasClass('date-time-range')) { | |||
$(this).val(pickerElm.startDate.format('DD/MM/YY HH:mm') + ' - ' + pickerElm.endDate.format(options.locale.format)); | |||
} else { | |||
$(this).val(pickerElm.startDate.format('DD/MM/YY') + ' - ' + pickerElm.endDate.format(options.locale.format)); | |||
} | |||
if ($(picker).hasClass('date-time-range')) { | |||
$(picker).nextAll('.date-time-range-fields').find('.date-start').val(pickerElm.startDate.format('YYYY-MM-DD HH:mm')); | |||
$(picker).nextAll('.date-time-range-fields').find('.date-end').val(pickerElm.endDate.format('YYYY-MM-DD HH:mm')); | |||
} else { | |||
$(picker).nextAll('.date-time-range-fields').find('.date-start').val(pickerElm.startDate.format('YYYY-MM-DD')); | |||
$(picker).nextAll('.date-time-range-fields').find('.date-end').val(pickerElm.endDate.format('YYYY-MM-DD')); | |||
} | |||
}); | |||
}); | |||
} | |||
static setAutoCompleteField() { | |||
var autocompleteFields = $('[data-lc-autocomplete-url]'); | |||
autocompleteFields.each(function () { | |||
var $this = $(this), | |||
url = $this.data('lc-autocomplete-url'); | |||
$this.autoComplete({ | |||
noResultsText: 'Aucun résultat n\'a été trouvé.', | |||
resolverSettings: { | |||
url: url | |||
} | |||
}); | |||
}); | |||
} | |||
} |
@@ -36,7 +36,7 @@ | |||
</div> | |||
<div class="col-8"> | |||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||
{% block css %}card-primary{% endblock %} | |||
{% block class %}card-primary{% endblock %} | |||
{% block header %} | |||
<h3 class="card-title"> | |||
Liste des messages |
@@ -1,119 +0,0 @@ | |||
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #} | |||
{% set form = edit_form %} | |||
{% extends '@LcSov/adminlte/crud/layout_form.html.twig' %} | |||
{% block body_id 'ea-edit-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% block body_class 'ea-edit ea-edit-' ~ entity.name %} | |||
{% block content_title %} | |||
{{ 'edit'|sov_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) }} | |||
{% endblock %} | |||
{% block delete_form %} | |||
{{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', { entity_id: entity.primaryKeyValue }, with_context = false) }} | |||
{% endblock delete_form %} | |||
{# | |||
{% block body_javascript %} | |||
{{ parent() }} | |||
<script type="text/javascript"> | |||
$(function () { | |||
$('.ea-edit-form').areYouSure({'message': '{{ 'form.are_you_sure'|trans({}, 'EasyAdminBundle')|e('js') }}'}); | |||
const entityForm = document.querySelector('form.ea-edit-form'); | |||
const inputFieldsSelector = 'input,select,textarea'; | |||
// Adding visual feedback for invalid fields: any ".form-group" with invalid fields | |||
// receives "has-error" class. The class is removed on click on the ".form-group" | |||
// itself to support custom/complex fields. | |||
entityForm.addEventListener('submit', function (submitEvent) { | |||
entityForm.querySelectorAll(inputFieldsSelector).forEach(function (input) { | |||
if (!input.validity.valid) { | |||
const formGroup = input.closest('div.form-group'); | |||
formGroup.classList.add('has-error'); | |||
formGroup.addEventListener('click', function onFormGroupClick() { | |||
formGroup.classList.remove('has-error'); | |||
formGroup.removeEventListener('click', onFormGroupClick); | |||
}); | |||
} | |||
}); | |||
const eaEvent = new CustomEvent('ea.form.submit', { | |||
cancelable: true, | |||
detail: {page: 'edit', form: entityForm} | |||
}); | |||
const eaEventResult = document.dispatchEvent(eaEvent); | |||
if (false === eaEventResult) { | |||
submitEvent.preventDefault(); | |||
submitEvent.stopPropagation(); | |||
} | |||
}); | |||
// forms with tabs require some special treatment for errors. The problem | |||
// is when the field with errors is included in a tab not currently visible. | |||
// Browser shows this error "An invalid form control with name='...' is not focusable." | |||
// So, the user clicks on Submit button, the form is not submitted and the error | |||
// is not displayed. This JavaScript code ensures that each tab shows a badge with | |||
// the number of errors in it. | |||
entityForm.addEventListener('submit', function () { | |||
const formTabPanes = entityForm.querySelectorAll('.tab-pane'); | |||
if (0 === formTabPanes.length) { | |||
return; | |||
} | |||
let firstNavTabItemWithError = null; | |||
formTabPanes.forEach(function (tabPane) { | |||
let tabPaneNumErrors = 0; | |||
tabPane.querySelectorAll(inputFieldsSelector).forEach(function (input) { | |||
if (!input.validity.valid) { | |||
tabPaneNumErrors++; | |||
} | |||
}); | |||
let navTabItem = entityForm.querySelector('.nav-item a[href="#' + tabPane.id + '"]'); | |||
let existingErrorBadge = navTabItem.querySelector('span.badge.badge-danger'); | |||
if (null !== existingErrorBadge) { | |||
navTabItem.removeChild(existingErrorBadge); | |||
} | |||
if (tabPaneNumErrors > 0) { | |||
let newErrorBadge = document.createElement('span'); | |||
newErrorBadge.classList.add('badge', 'badge-danger'); | |||
newErrorBadge.title = 'form.tab.error_badge_title'; | |||
newErrorBadge.textContent = tabPaneNumErrors; | |||
navTabItem.appendChild(newErrorBadge); | |||
if (null === firstNavTabItemWithError) { | |||
firstNavTabItemWithError = navTabItem; | |||
} | |||
} | |||
}); | |||
if (firstNavTabItemWithError) { | |||
firstNavTabItemWithError.click(); | |||
} | |||
}); | |||
$('.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 () { | |||
$('#delete-form').attr('action', formAction).trigger('submit'); | |||
}); | |||
}); | |||
}); | |||
</script> | |||
< | |||
{% endblock %} | |||
#} |
@@ -6,5 +6,5 @@ | |||
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' }}> | |||
<label class="custom-control-label" for="{{ id_toggle }}"> | |||
{{ field.getCustomOption('toggle_label') ?? field.label }}</label> | |||
{{ field.getCustomOption('toggle_label') ? field.label : field.property|sov_trans_admin_field(entity.instance) }}</label> | |||
</div> |
@@ -1,9 +1,38 @@ | |||
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #} | |||
{% extends ea.templatePath('layout') %} | |||
{% if ea.crud.currentAction == 'new' %} | |||
{% set form = new_form %} | |||
{% set body_id = 'ea-new-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-new ea-new-' ~ entity.name %} | |||
{% set content_title = 'new'|sov_trans_admin_title(ea.getEntity().getFqcn()) %} | |||
{% elseif ea.crud.currentAction == 'edit' %} | |||
{% set form = edit_form %} | |||
{% set body_id = 'ea-edit-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% set body_class = 'ea-edit ea-edit-' ~ entity.name %} | |||
{% set content_title = 'edit'|sov_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) %} | |||
{% endif %} | |||
{% form_theme form with ea.crud.formThemes only %} | |||
{% trans_default_domain ea.i18n.translationDomain %} | |||
{% block body_id body_id %} | |||
{% block body_class body_class %} | |||
{% block content_title %} | |||
{{ content_title }} | |||
{% endblock %} | |||
{% block configured_head_contents %} | |||
{{ parent() }} | |||
{% for htmlContent in form.vars.ea_crud_form.assets.headContents %} | |||
@@ -40,6 +69,8 @@ | |||
{% endblock page_actions_wrapper %} | |||
{% block main %} | |||
<div class="col-8"> | |||
{% block form %} | |||
@@ -64,5 +95,15 @@ | |||
{% endembed %} | |||
{% endblock form_footer %} | |||
{% block delete_form %}{% endblock delete_form %} | |||
{% endblock %} | |||
{% block delete_form %} | |||
{% if ea.crud.currentAction == 'edit' %} | |||
{{ include('@EasyAdmin/crud/includes/_delete_form.html.twig', { entity_id: entity.primaryKeyValue }, with_context = false) }} | |||
{% endif %} | |||
{% endblock delete_form %} | |||
{% endblock %} | |||
@@ -283,12 +283,15 @@ | |||
{{ widget|raw }} | |||
<span class="checkmark"></span> | |||
{# {% if translation_domain == 'lcshop' %} | |||
{{ name|lc_trad(easyadmin['entity']['name'], 'field') }} | |||
{% else %} #} | |||
{{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain))|raw -}} | |||
{# {{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain))|raw -}} #} | |||
{% set entityNameOrObject = form.parent.vars.data %} | |||
{% if not entityNameOrObject and form.parent.vars.errors.form.config.dataClass is defined %} | |||
{% set entityNameOrObject = form.parent.vars.errors.form.config.dataClass %} | |||
{% endif %} | |||
{{- (label is not empty and '.' in label) ? label|trans({}, 'admin') : name|sov_trans_admin_field(entityNameOrObject) -}} | |||
{# {% endif %} #} | |||
{{- form_errors(form) -}} | |||
</label> | |||
{%- endif -%} |
@@ -33,7 +33,7 @@ | |||
{% set has_datagrid_tools = has_search or has_filters %} | |||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||
{% block css %}card-table card-outline card-primary{% endblock %} | |||
{% block class %}card-table card-outline card-primary{% endblock %} | |||
{% block header %} | |||
<span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total"> | |||
{{ paginator.numResults }} résultats |
@@ -1,112 +0,0 @@ | |||
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #} | |||
{% set form = new_form %} | |||
{% extends '@LcSov/adminlte/crud/layout_form.html.twig' %} | |||
{% block body_id 'ea-new-' ~ entity.name ~ '-' ~ entity.primaryKeyValue %} | |||
{% block body_class 'ea-new ea-new-' ~ entity.name %} | |||
{% block content_title %} | |||
{{ 'new'|sov_trans_admin_title(ea.getEntity().getFqcn()) }} | |||
{% endblock %} | |||
{% block body_javascript %} | |||
{{ parent() }} | |||
{# <script type="text/javascript"> | |||
$(function () { | |||
$('.ea-new-form').areYouSure({'message': '{{ 'form.are_you_sure'|trans({}, 'EasyAdminBundle')|e('js') }}'}); | |||
const entityForm = document.querySelector('form.ea-new-form'); | |||
const inputFieldsSelector = 'input,select,textarea'; | |||
// Adding visual feedback for invalid fields: any ".form-group" with invalid fields | |||
// receives "has-error" class. The class is removed on click on the ".form-group" | |||
// itself to support custom/complex fields. | |||
entityForm.addEventListener('submit', function (submitEvent) { | |||
entityForm.querySelectorAll(inputFieldsSelector).forEach(function (input) { | |||
if (!input.validity.valid) { | |||
const formGroup = input.closest('div.form-group'); | |||
formGroup.classList.add('has-error'); | |||
formGroup.addEventListener('click', function onFormGroupClick() { | |||
formGroup.classList.remove('has-error'); | |||
formGroup.removeEventListener('click', onFormGroupClick); | |||
}); | |||
} | |||
}); | |||
const eaEvent = new CustomEvent('ea.form.submit', { | |||
cancelable: true, | |||
detail: {page: 'new', form: entityForm} | |||
}); | |||
const eaEventResult = document.dispatchEvent(eaEvent); | |||
if (false === eaEventResult) { | |||
submitEvent.preventDefault(); | |||
submitEvent.stopPropagation(); | |||
} | |||
}); | |||
// forms with tabs require some special treatment for errors. The problem | |||
// is when the field with errors is included in a tab not currently visible. | |||
// Browser shows this error "An invalid form control with name='...' is not focusable." | |||
// So, the user clicks on Submit button, the form is not submitted and the error | |||
// is not displayed. This JavaScript code ensures that each tab shows a badge with | |||
// the number of errors in it. | |||
entityForm.addEventListener('submit', function () { | |||
const formTabPanes = entityForm.querySelectorAll('.tab-pane'); | |||
if (0 === formTabPanes.length) { | |||
return; | |||
} | |||
let firstNavTabItemWithError = null; | |||
formTabPanes.forEach(function (tabPane) { | |||
let tabPaneNumErrors = 0; | |||
tabPane.querySelectorAll(inputFieldsSelector).forEach(function (input) { | |||
if (!input.validity.valid) { | |||
tabPaneNumErrors++; | |||
} | |||
}); | |||
let navTabItem = entityForm.querySelector('.nav-item a[href="#' + tabPane.id + '"]'); | |||
let existingErrorBadge = navTabItem.querySelector('span.badge.badge-danger'); | |||
if (null !== existingErrorBadge) { | |||
navTabItem.removeChild(existingErrorBadge); | |||
} | |||
if (tabPaneNumErrors > 0) { | |||
let newErrorBadge = document.createElement('span'); | |||
newErrorBadge.classList.add('badge', 'badge-danger'); | |||
newErrorBadge.title = 'form.tab.error_badge_title'; | |||
newErrorBadge.textContent = tabPaneNumErrors; | |||
navTabItem.appendChild(newErrorBadge); | |||
if (null === firstNavTabItemWithError) { | |||
firstNavTabItemWithError = navTabItem; | |||
} | |||
} | |||
}); | |||
if (firstNavTabItemWithError) { | |||
firstNavTabItemWithError.click(); | |||
} | |||
}); | |||
// prevent multiple form submissions to avoid creating duplicated entities | |||
entityForm.addEventListener('submit', function () { | |||
// this timeout is needed to include the disabled button into the submitted form | |||
setTimeout(function () { | |||
const submitButtons = entityForm.querySelectorAll('[type="submit"]'); | |||
submitButtons.forEach(function (button) { | |||
button.setAttribute('disabled', 'disabled'); | |||
}); | |||
}, 1); | |||
}, false); | |||
}); | |||
</script> | |||
{{ include('@EasyAdmin/crud/includes/_select2_widget.html.twig') }} #} | |||
{% endblock %} |
@@ -32,7 +32,7 @@ | |||
{{ form_start(sortable_form) }} | |||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||
{% block css %}card-table card-outline card-primary{% endblock %} | |||
{% block class %}card-table card-outline card-primary{% endblock %} | |||
{% block header %} | |||
<span data-toggle="tooltip" class="badge badge-light" data-original-title="Total" title="Total"> | |||
{{ paginator.numResults }} résultats |
@@ -1,4 +1,4 @@ | |||
<div class="card {% block css %}{% endblock %}" id="{% block id %}{% endblock %}"> | |||
<div class="card {% block class %}{% endblock %}" id="{% block id %}{% endblock %}"> | |||
{% block header_wrapper %} | |||
<div class="card-header {% block header_class %}{% endblock %}"> | |||
{% block header %} |
@@ -206,7 +206,7 @@ | |||
$(document).ready(function () { | |||
{% for label, messages in flash_messages %} | |||
{% for message in messages %} | |||
Notification.add("{{ label }}", "{{ message|trans|raw|replace({'"': '\"'}) }}"); | |||
SovNotification.add("{{ label }}", "{{ message|trans|raw|replace({'"': '\"'}) }}"); | |||
{% endfor %} | |||
{% endfor %} | |||
}); |