@@ -40,6 +40,7 @@ use Lc\SovBundle\Doctrine\Extension\TreeInterface; | |||
use Lc\SovBundle\Field\CollectionField; | |||
use Lc\SovBundle\Field\GalleryManagerField; | |||
use Lc\SovBundle\Form\Type\Crud\PositionType; | |||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\HttpFoundation\RequestStack; | |||
@@ -79,13 +80,13 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
Action::NEW => [ | |||
'icon' => 'plus', | |||
'label' => 'Créer', | |||
'add_class'=>'btn-sm' | |||
'add_class' => 'btn-sm' | |||
], | |||
Action::EDIT => [ | |||
'class' => 'btn btn-sm btn-primary', | |||
'icon' => 'edit', | |||
'label' => false, | |||
'html_attributes'=> array('data-toggle'=> 'tooltip', 'title'=> 'Éditer') | |||
'html_attributes' => array('data-toggle' => 'tooltip', 'title' => 'Éditer') | |||
], | |||
Action::DELETE => [ | |||
'icon' => 'trash', | |||
@@ -146,7 +147,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
$indexChildAction = Action::new('index_children', 'Afficher les enfants', 'fa fa-list') | |||
->linkToCrudAction(Action::INDEX) | |||
->setLabel('') | |||
->setHtmlAttributes(array('data-toggle'=> 'tooltip', 'title'=> 'Afficher les enfants')) | |||
->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants')) | |||
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig') | |||
->setCssClass('btn btn-sm btn-success'); | |||
@@ -178,7 +179,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
} | |||
if (isset($button['icon'])) { | |||
$action->setIcon('fa fa-'.$button['icon']); | |||
$action->setIcon('fa fa-' . $button['icon']); | |||
} | |||
if (isset($button['label'])) { | |||
@@ -190,7 +191,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
} | |||
if (isset($button['html_attributes']) && $button['html_attributes']) { | |||
$action->setHtmlAttributes( $button['html_attributes']); | |||
$action->setHtmlAttributes($button['html_attributes']); | |||
} | |||
return $action; | |||
@@ -204,6 +205,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
public function configureResponseParameters(KeyValueStore $responseParameters): KeyValueStore | |||
{ | |||
// fields sur la page index | |||
if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) { | |||
$responseParameters->set('fields', $this->configureFields('index')); | |||
} | |||
@@ -216,7 +218,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
$crud = parent::configureCrud($crud); | |||
$this->setMaxResults($crud); | |||
if($this->isInstanceOf(SortableInterface::class)){ | |||
if ($this->isInstanceOf(SortableInterface::class)) { | |||
$crud->setDefaultSort(['position' => 'ASC']); | |||
} | |||
return $crud; | |||
@@ -226,7 +228,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
{ | |||
$entityClass = $this->getEntityFqcn(); | |||
$paramListMaxResults = 'listMaxResults'; | |||
$paramSessionListMaxResults = $entityClass.'-'.$paramListMaxResults; | |||
$paramSessionListMaxResults = $entityClass . '-' . $paramListMaxResults; | |||
$requestListMaxResults = $this->request->getCurrentRequest()->get($paramListMaxResults); | |||
if ($requestListMaxResults) { | |||
@@ -243,7 +245,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
{ | |||
if ($this->isInstanceOf(SortableInterface::class)) { | |||
$seoPanel = [ | |||
FormField::addPanel('Seo'), | |||
FormField::addPanel('seo'), | |||
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp( | |||
'Affiché dans les résultats de recherche Google' | |||
)->hideOnIndex(), | |||
@@ -259,7 +261,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
if ($this->isInstanceOf(DevAliasInterface::class)) { | |||
$confPanel = [ | |||
FormField::addPanel('Conf'), | |||
FormField::addPanel('configuration'), | |||
TextField::new('devAlias')->hideOnIndex(), | |||
]; | |||
} | |||
@@ -305,7 +307,6 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
->getForm(); | |||
$entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn()); | |||
dump($entityManager); | |||
$repository = $entityManager->getRepository($this->getEntityFqcn()); | |||
$sortableForm->handleRequest($context->getRequest()); | |||
@@ -374,7 +375,6 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
$filters | |||
); | |||
dump(get_defined_vars()); | |||
if ($this->isInstanceOf(TreeInterface::class)) { | |||
$entityId = $searchDto->getRequest()->get('entityId'); | |||
if ($entityId !== null) { | |||
@@ -416,6 +416,18 @@ abstract class AbstractCrudController extends EaAbstractCrudController | |||
return $queryBuilder; | |||
} | |||
public function edit(AdminContext $context) | |||
{ | |||
$response = parent::edit($context); ; | |||
// on vide le flash bag si édition en ajax (notification déjà affichée en Javascript) | |||
if ($context->getRequest()->isXmlHttpRequest()) { | |||
$this->session->getFlashBag()->clear() ; | |||
} | |||
return $response ; | |||
} | |||
public function isInstanceOf(string $interfaceName): bool | |||
{ | |||
return in_array($interfaceName, class_implements($this->getEntityFqcn())); |
@@ -30,7 +30,7 @@ class DashboardController extends AbstractDashboardController | |||
// the path defined in this method is passed to the Twig asset() function | |||
->setFaviconPath('favicon.svg') | |||
// the domain used by default is 'messages' | |||
->setTranslationDomain('lcadmin'); | |||
->setTranslationDomain('admin'); | |||
} | |||
public function configureAssets(): Assets | |||
@@ -82,7 +82,7 @@ class DashboardController extends AbstractDashboardController | |||
'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/action' => '@LcSov/adminlte/crud/action/action.html.twig', | |||
'flash_messages' => '@LcSov/adminlte/block/flash_messages.html.twig', | |||
] | |||
) | |||
->setFormThemes( | |||
@@ -90,7 +90,8 @@ class DashboardController extends AbstractDashboardController | |||
'@LcSov/adminlte/crud/form_theme.html.twig', | |||
'@FOSCKEditor/Form/ckeditor_widget.html.twig' | |||
] | |||
); | |||
) | |||
; | |||
} | |||
} |
@@ -2,9 +2,11 @@ | |||
namespace Lc\SovBundle\Controller\Admin; | |||
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Form\Type\User\ChangePasswordFormType; | |||
use Lc\SovBundle\Form\Type\User\ProfileFormType; | |||
use Lc\SovBundle\Model\User\User; | |||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |||
use Symfony\Component\HttpFoundation\Request; | |||
use Symfony\Component\HttpFoundation\Response; | |||
@@ -37,7 +39,7 @@ class UserController extends AbstractController | |||
return $this->render( | |||
'@LcSov/user/profile.html.twig', | |||
[ | |||
'form' => $form->createView() | |||
'form' => $form->createView(), | |||
] | |||
); | |||
} | |||
@@ -65,6 +67,7 @@ class UserController extends AbstractController | |||
return $this->render( | |||
'@LcSov/user/change_password.html.twig', | |||
[ | |||
'entity_class' => User::class, | |||
'form' => $form->createView() | |||
] | |||
); |
@@ -0,0 +1,50 @@ | |||
<?php | |||
namespace Lc\SovBundle\EventSubscriber; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityDeletedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent; | |||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | |||
use Symfony\Component\Translation\TranslatableMessage; | |||
class EasyAdminEventSubscriber implements EventSubscriberInterface | |||
{ | |||
protected $session ; | |||
public function __construct(SessionInterface $session) | |||
{ | |||
$this->session = $session ; | |||
} | |||
public static function getSubscribedEvents(): array | |||
{ | |||
return [ | |||
AfterEntityPersistedEvent::class => ['flashMessageAfterPersist'], | |||
AfterEntityUpdatedEvent::class => ['flashMessageAfterUpdate'], | |||
AfterEntityDeletedEvent::class => ['flashMessageAfterDelete'], | |||
]; | |||
} | |||
public function flashMessageAfterPersist(AfterEntityPersistedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.create', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
public function flashMessageAfterUpdate(AfterEntityUpdatedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.update', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
public function flashMessageAfterDelete(AfterEntityDeletedEvent $event): void | |||
{ | |||
$this->session->getFlashBag()->add('success', new TranslatableMessage('flash_message.delete', [ | |||
'%name%' => (string) $event->getEntityInstance(), | |||
])); | |||
} | |||
} |
@@ -4,7 +4,7 @@ namespace Lc\SovBundle\Form\Type\Crud; | |||
use Lc\SovBundle\DataTransformer\FileManagerTypeToDataTransformer; | |||
use Lc\SovBundle\Entity\File\File; | |||
use Lc\SovBundle\Doctrine\Extension\FileInterface; | |||
use Lc\SovBundle\Model\File\FileInterface; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\DataTransformerInterface; |
@@ -4,8 +4,7 @@ namespace Lc\SovBundle\Form\Type\User; | |||
use Lc\SovBundle\DataTransformer\FileManagerTypeToDataTransformer; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Entity\File\File; | |||
use Lc\SovBundle\Doctrine\Extension\FileInterface; | |||
use Lc\SovBundle\Model\File\FileInterface; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\Extension\Core\Type\EmailType; | |||
@@ -25,6 +24,8 @@ class ProfileFormType extends AbstractType | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
$entityName = $this->em->getEntityName(UserInterface::class) ; | |||
$builder->add( | |||
'firstname', | |||
TextType::class, | |||
@@ -49,13 +50,15 @@ class ProfileFormType extends AbstractType | |||
) | |||
); | |||
$builder->add( | |||
'phone', | |||
TextType::class, | |||
array( | |||
'label' => 'Téléphone' | |||
) | |||
); | |||
if(property_exists($entityName, 'phone')) { | |||
$builder->add( | |||
'phone', | |||
TextType::class, | |||
array( | |||
'label' => 'Téléphone' | |||
) | |||
); | |||
} | |||
$builder->add( | |||
'submit', |
@@ -26,6 +26,7 @@ global.Tools = Tools; | |||
import { Notification } from './js/notification.js'; | |||
global.Notification = Notification; | |||
Notification.init() ; | |||
// Common | |||
import './common.scss'; |
@@ -1,4 +1,7 @@ | |||
/* Notifications */ | |||
//Notification.init() ; | |||
/* Tooltip */ | |||
$('[data-toggle="tooltip"]').tooltip(); | |||
@@ -1,34 +1,45 @@ | |||
export class Notification { | |||
static setNotifications(notifications) { | |||
static init() { | |||
toastr.options.timeOut = 3000; | |||
toastr.options.positionClass = 'toast-bottom-right'; | |||
toastr.options.onHidden = function () { | |||
if ($('#toast-container .toast').length == 1) { | |||
$('#toast-close-all').remove(); | |||
} | |||
}; | |||
} | |||
static set(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]); | |||
self.add(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(); | |||
}; | |||
static add(type, text) { | |||
toastr[type](text); | |||
if ($('#toast-close-all').length == 0) { | |||
$('#toast-container').prepend('<button id="toast-close-all"><i class="fa fa-times"></i></button>'); | |||
let $container = $('#toast-container') ; | |||
let selectorButtonCloseAll = '#toast-close-all' ; | |||
let countMessages = $container.find('.toast').length ; | |||
if ($(selectorButtonCloseAll).length == 0 && countMessages > 2) { | |||
$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 () { | |||
$(selectorButtonCloseAll).off('click').on('click', function () { | |||
toastr.remove(); | |||
if ($('#toast-container .toast').length == 0) $('#toast-close-all').remove(); | |||
if (countMessages == 0) { | |||
$('#toast-close-all').remove(); | |||
} | |||
}); | |||
} | |||
@@ -1,10 +1,29 @@ | |||
#toast-container { | |||
width: 350px; | |||
width: 400px; | |||
} | |||
.toast { | |||
float: right | |||
#toast-container .toast { | |||
float: right ; | |||
width: 400px ; | |||
opacity: 1 ; | |||
box-shadow: none !important; | |||
-moz-box-shadow: none !important; | |||
-o-box-shadow: none !important; | |||
-webkit-box-shadow: none !important; | |||
&.success { | |||
background-color: $success !important ; | |||
} | |||
&.danger, &.error { | |||
background-color: $danger !important ; | |||
} | |||
&.info { | |||
background-color: $info !important ; | |||
} | |||
&.warning { | |||
background-color: $warning !important ; | |||
} | |||
} | |||
#toast-container:before:hover { | |||
@@ -15,22 +34,21 @@ | |||
#toast-close-all { | |||
border: 0; | |||
position: absolute; | |||
bottom: 7px; | |||
left: -15px; | |||
pointer-events: auto; | |||
z-index: 999999999999999999999; | |||
z-index: 1000; | |||
background: #BD362F; | |||
border-radius: 3px; | |||
color: #fff; | |||
opacity: 0.8; | |||
top: 2px; | |||
width: 50px; | |||
height: 50px; | |||
font-size: 30px; | |||
left: 0px; | |||
font-size: 20px; | |||
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; | |||
//@include text-shadow(0 1px 0 #999) ; | |||
border-radius: 50px ; | |||
} | |||
@@ -9,7 +9,6 @@ $(document).ready(function () { | |||
function initCollectionWidget() { | |||
Tools.log('czefe'); | |||
$('.field-collection[data-prototype]').each(function (i, collectionWidget) { | |||
setCollectionWidgetSortable($(collectionWidget)); | |||
@@ -65,9 +64,7 @@ function getNumItems($collectionWidget) { | |||
} | |||
function reindexKeyCollectionWidget($collectionWidget) { | |||
Tools.log('ncncnc'); | |||
if ($collectionWidget.data('reindex-key')) { | |||
Tools.log('ncncnc'); | |||
$collectionWidget.find('.field-collection-item').each(function (i, item) { | |||
$(item).find('input,textarea').each(function (y, field) { | |||
let $field = $(field); |
@@ -17,14 +17,14 @@ function lcCrudIndexToggle() { | |||
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.'); | |||
Notification.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.addNotification('error', 'Une erreur est survenue.'); | |||
Notification.add('error', 'Une erreur est survenue.'); | |||
}); | |||
}); | |||
} |
@@ -1,3 +1,10 @@ | |||
_liip_imagine: | |||
resource: "@LiipImagineBundle/Resources/config/routing.yaml" | |||
artgris_bundle_file_manager: | |||
resource: "@ArtgrisFileManagerBundle/Controller" | |||
type: annotation | |||
prefix: /manager | |||
sov_login: | |||
path: /login |
@@ -0,0 +1,51 @@ | |||
flash_message: | |||
create: Le contenu "%name%" a été créé avec succès. | |||
update: Le contenu "%name%" a été mis à jour avec succès. | |||
delete: Le contenu "%name%" a été supprimé avec succès. | |||
menu: | |||
dashboard: Tableau de bord | |||
page: Pages | |||
user: | |||
label: Utilisateurs | |||
childs: | |||
index: Liste | |||
account: | |||
label: Mon compte | |||
childs: | |||
profile: Informations personnelles | |||
password: Mot de passe | |||
title: | |||
dashboard: Tableau de bord | |||
index: '%label_plurial%' | |||
sort: Ordonner "%label_plurial%" | |||
new: Ajouter "%label%" | |||
edit: Modifier "%label%" (#%id%) | |||
detail: Voir "%label%" (#%id%) | |||
account: | |||
profile: Mes informations personnelles | |||
change_password: Changer de mot de passe | |||
entity: | |||
user: | |||
label: Utilisateur | |||
label_plurial: Utilisateurs | |||
page: | |||
label: Page | |||
label_plurial: Pages | |||
default: | |||
fields: | |||
title: Titre | |||
position: Position | |||
position_help: Position help | |||
description: Description | |||
description_help: Description help | |||
file: Fichier | |||
status: Statut | |||
email: Email | |||
panels: | |||
general: Général | |||
configuration: Configuration | |||
gallery: Galerie | |||
seo: Référencement |
@@ -0,0 +1 @@ | |||
{# Gérés en Javascript dans layout.html.twig #} |
@@ -1,5 +1,6 @@ | |||
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||
{% macro render_menu_item(item, is_sub_item = false) %} | |||
{% if item.isMenuSection %} | |||
{% if item.icon is not empty %} | |||
<i class="fa fa-{{ item.icon }}"></i> | |||
@@ -11,7 +12,7 @@ | |||
{% if item.icon is not empty %} | |||
<i class="far fa-{{ item.icon }} nav-icon"></i> | |||
{% endif %} | |||
<p>{{ item.label|raw }}</p> | |||
<p>{{ item.label|lc_trans_admin_menu }}</p> | |||
{% if item.hasSubItems %}<i class="right fas fa-angle-left"></i>{% endif %} | |||
</a> | |||
{% endif %} |
@@ -7,11 +7,7 @@ | |||
{% block body_class 'ea-edit ea-edit-' ~ entity.name %} | |||
{% block content_title %} | |||
{%- apply spaceless -%} | |||
{{ ea.crud.customPageTitle is null | |||
? (ea.crud.defaultPageTitle|trans(ea.i18n.translationParameters, 'EasyAdminBundle'))|raw | |||
: ea.crud.customPageTitle|trans(ea.i18n.translationParameters)|raw }} | |||
{%- endapply -%} | |||
{{ 'edit'|lc_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) }} | |||
{% endblock %} | |||
{% block delete_form %} |
@@ -1,6 +1,86 @@ | |||
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||
{% use '@EasyAdmin/crud/form_theme.html.twig' %} | |||
{% block form_row %} | |||
{% set row_attr = row_attr|merge({ | |||
class: row_attr.class|default('') ~ ' form-group' | |||
}) %} | |||
<div {% with { attr: row_attr } %}{{ block('attributes') }}{% endwith %}> | |||
{{- form_label(form) -}} | |||
<div class="form-widget"> | |||
{% set has_prepend_html = ea.field.prepend_html|default(null) is not null %} | |||
{% set has_append_html = ea.field.append_html|default(null) is not null %} | |||
{% set has_input_groups = has_prepend_html or has_append_html %} | |||
{% if has_input_groups %}<div class="input-group">{% endif %} | |||
{% if has_prepend_html %} | |||
<div class="input-group-prepend"> | |||
<span class="input-group-text">{{ ea.field.prepend_html|raw }}</span> | |||
</div> | |||
{% endif %} | |||
{{ form_widget(form) }} | |||
{% if has_append_html %} | |||
<div class="input-group-append"> | |||
<span class="input-group-text">{{ ea.field.append_html|raw }}</span> | |||
</div> | |||
{% endif %} | |||
{% if has_input_groups %}</div>{% endif %} | |||
{% set nullable_fields_fqcn = [ | |||
'EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField', | |||
'EasyCorp\Bundle\EasyAdminBundle\Field\DateField', | |||
'EasyCorp\Bundle\EasyAdminBundle\Field\TimeField', | |||
] %} | |||
{% if form.vars.ea_crud_form.ea_field.fieldFqcn|default(false) in nullable_fields_fqcn and ea.field.nullable|default(false) %} | |||
<div class="nullable-control"> | |||
<label> | |||
<input type="checkbox" {% if data is null %}checked="checked"{% endif %}> | |||
{{ 'label.nullable_field'|trans({}, 'EasyAdminBundle')}} | |||
</label> | |||
</div> | |||
{% endif %} | |||
{% set help_message = name|lc_trans_admin_help(ea.getEntity().getFqcn()) %} | |||
{% if help_message != '' %} | |||
<small class="form-help">{{ help_message }}</small> | |||
{% endif %} | |||
{{- form_errors(form) -}} | |||
</div> | |||
</div> | |||
{% endblock form_row %} | |||
{% block form_label -%} | |||
{% if label is same as(false) -%} | |||
<label>{# the empty <label> is needed to not break the form design #}</label> | |||
{%- else -%} | |||
{%- if compound is defined and compound -%} | |||
{%- set element = 'legend' -%} | |||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} | |||
{%- else -%} | |||
{%- set label_attr = label_attr|merge({for: id, class: (label_attr.class|default('') ~ ' form-control-label')|trim}) -%} | |||
{%- endif -%} | |||
{% if required -%} | |||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %} | |||
{%- endif -%} | |||
{% if label is empty -%} | |||
{%- if label_format is not empty -%} | |||
{% set label = label_format|replace({ | |||
'%name%': name, | |||
'%id%': id, | |||
}) %} | |||
{%- else -%} | |||
{# {% set label = name|humanize %} #} | |||
{%- endif -%} | |||
{%- endif -%} | |||
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ (translation_domain is same as(false)) ? label : label|lower|lc_trans_admin_field(ea.getEntity().getFqcn()) }}</{{ element|default('label') }}> | |||
{%- endif -%} | |||
{%- endblock form_label %} | |||
{% block gallery_manager_row %} | |||
{{ block('collection_row') }} | |||
{% endblock gallery_manager_row %} | |||
@@ -9,7 +89,6 @@ | |||
{{ block('collection_widget') }} | |||
{% endblock gallery_manager_widget %} | |||
{% block collection_row %} | |||
{% if prototype is defined and not prototype.rendered %} | |||
{% set row_attr = row_attr|merge({ 'data-prototype': form_row(prototype) }) %} | |||
@@ -145,6 +224,7 @@ | |||
{{ 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 -}} | |||
{# {% endif %} #} | |||
{{- form_errors(form) -}} | |||
</label> | |||
@@ -156,6 +236,7 @@ | |||
{{ parent() }} | |||
{% if ea_crud_form.form_panels is defined %} | |||
<div class="card card-outline"> | |||
<div class="card-header p-0 border-bottom-0"> | |||
<ul id="nav-params" class="nav nav-pills" role="navigation"> | |||
@@ -164,7 +245,7 @@ | |||
<li class="nav-item"> | |||
<a href="#panel-{{ panel_name }} " class="nav-link {{ panel_name == 1 ? 'active' }}" data-toggle="tab" role="tab" | |||
aria-controls="panel-{{ panel_name }}"> | |||
{{ panel_config.label|raw }} | |||
{{ panel_config.label|lc_trans_admin_panel(ea.getEntity().getFqcn()) }} | |||
<i class="fa fa-exclamation-circle invalid-form"></i> | |||
</a> | |||
</li> | |||
@@ -202,7 +283,8 @@ | |||
{% if panel_config.icon|default(false) %} | |||
<i class="{{ panel_config.icon }}"></i> | |||
{% endif %} | |||
{{ panel_config.label|raw }} | |||
{{ panel_config.label|lc_trans_admin_panel(ea.getEntity().getFqcn()) }} | |||
{% if collapsible %} | |||
</a> |
@@ -2,16 +2,14 @@ | |||
{# @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 -%} | |||
{{ 'index'|lc_trans_admin_title(ea.getEntity().getFqcn()) }} | |||
{% endblock %} | |||
{% block content_breadcrumb %} | |||
@@ -24,6 +22,7 @@ | |||
{% 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 %} | |||
@@ -93,7 +92,7 @@ | |||
class="fa fa-fw {{ column_icon }}"></i> | |||
</a> | |||
{% else %} | |||
<span>{{ field.label ? field.label|raw : field.getProperty|raw }}</span> | |||
<span>{{ field.getProperty|lc_trans_admin_field(ea.getEntity().getFqcn()) }}</span> | |||
{% endif %} | |||
</th> | |||
{% endif %} | |||
@@ -207,6 +206,7 @@ | |||
{{ parent() }} | |||
<script type="text/javascript"> | |||
$(function () { | |||
/* $('.action-delete').on('click', function (e) { |
@@ -7,14 +7,9 @@ | |||
{% block body_class 'ea-new ea-new-' ~ entity.name %} | |||
{% block content_title %} | |||
{%- apply spaceless -%} | |||
{% set default_title = ea.crud.defaultPageTitle('new')|trans(ea.i18n.translationParameters, 'EasyAdminBundle') %} | |||
{{ ea.crud.customPageTitle is null ? default_title|raw : ea.crud.customPageTitle('new')|trans(ea.i18n.translationParameters)|raw }} | |||
{%- endapply -%} | |||
{{ 'new'|lc_trans_admin_title(ea.getEntity().getFqcn()) }} | |||
{% endblock %} | |||
{% block body_javascript %} | |||
{{ parent() }} | |||
@@ -26,13 +26,15 @@ | |||
</li> | |||
{% for page in paginator.pageRange %} | |||
<li class="page-item {{ page == paginator.currentPage ? 'active' }} {{ page is null ? 'disabled' }}"> | |||
{% if page is null %} | |||
<span class="page-link">…</span> | |||
{% else %} | |||
<a class="page-link" href="{{ paginator.generateUrlForPage(page) }}">{{ page }}</a> | |||
{% endif %} | |||
</li> | |||
{% if page != 0 %} | |||
<li class="page-item {{ page == paginator.currentPage ? 'active' }} {{ page is null ? 'disabled' }}"> | |||
{% if page is null %} | |||
<span class="page-link">…</span> | |||
{% else %} | |||
<a class="page-link" href="{{ paginator.generateUrlForPage(page) }}">{{ page }}</a> | |||
{% endif %} | |||
</li> | |||
{% endif %} | |||
{% endfor %} | |||
<li class="page-item {{ not paginator.hasNextPage ? 'disabled' }}"> |
@@ -8,10 +8,9 @@ | |||
{% block body_class 'index' ~ (entities|length > 0 ? ' index-' ~ entities|first.name : '') %} | |||
{% block content_title %} | |||
Édition position | |||
{{ 'sort'|lc_trans_admin_title(ea.getEntity().getFqcn()) }} | |||
{% endblock %} | |||
{% block content_breadcrumb %} | |||
{{ include('@LcSov/adminlte/block/breadcrumb.html.twig') }} | |||
{% endblock content_breadcrumb %} |
@@ -1,9 +1,10 @@ | |||
{% extends '@LcSov/adminlte/layout.html.twig' %} | |||
{% block content_title 'SovBundle' %} | |||
{% block content_title %} | |||
{{ 'dashboard'|lc_trans_admin_title }} | |||
{% endblock %} | |||
{% block main %} | |||
Bien sur votre tableau de bord | |||
Salut !!! | |||
Tableau de bord par défaut. | |||
{% endblock %} | |||
@@ -165,7 +165,7 @@ | |||
{% endfor %} | |||
{% for webpack_encore_entry in ea.assets.webpackEncoreEntries ?? [] %} | |||
{{ ea_call_function_if_exists('encore_entry_script_tags', webpack_encore_entry) }} | |||
{{ ea_call_function_if_exists('encore_entry_script_tags', webpack_encore_entry, null, '_default', {'defer': false}) }} | |||
{% endfor %} | |||
{% endblock %} | |||
@@ -179,6 +179,21 @@ | |||
{% include '@LcSov/adminlte/filemanager/file-manager-modal.html.twig' %} | |||
{% if app.session is not null and app.session.started %} | |||
{% set flash_messages = app.session.flashbag.all %} | |||
{% if flash_messages|length > 0 %} | |||
<script type="text/javascript"> | |||
$(document).ready(function() { | |||
{% for label, messages in flash_messages %} | |||
{% for message in messages %} | |||
Notification.add("{{ label }}", "{{ message|trans|raw|replace({'"': '\"'}) }}"); | |||
{% endfor %} | |||
{% endfor %} | |||
}); | |||
</script> | |||
{% endif %} | |||
{% endif %} | |||
</body> | |||
{% endblock body %} | |||
</html> |
@@ -2,7 +2,7 @@ | |||
{% extends '@LcSov/adminlte/layout.html.twig' %} | |||
{% block content_title %} | |||
Changer de mot de passe | |||
{{ 'account.change_password'|lc_trans_admin_title }} | |||
{% endblock %} | |||
{% block main %} |
@@ -1,7 +1,7 @@ | |||
{% extends '@LcSov/adminlte/layout.html.twig' %} | |||
{% block content_title %} | |||
Mes informations personnelles | |||
{{ 'account.profile'|lc_trans_admin_title }} | |||
{% endblock %} | |||
{% block main %} |
@@ -0,0 +1,125 @@ | |||
<?php | |||
namespace Lc\SovBundle\Translation; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | |||
use Symfony\Contracts\Translation\TranslatorInterface; | |||
class TranslatorAdmin | |||
{ | |||
protected $translator; | |||
const DOMAIN = 'admin'; | |||
public function __construct(TranslatorInterface $translator) | |||
{ | |||
$this->translator = $translator; | |||
} | |||
public function transField($fieldName, $entityClass): string | |||
{ | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true) | |||
); | |||
} | |||
public function transHelp($fieldName, $entityClass): string | |||
{ | |||
$fieldName = $fieldName . '_help'; | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdField($fieldName, $entityClass), | |||
$this->buildTransIdField($fieldName, $entityClass, true), | |||
true | |||
); | |||
} | |||
public function transPanel($panelName, $entityClass): string | |||
{ | |||
return $this->transEntityThenDefault( | |||
$this->buildTransIdPanel($panelName, $entityClass), | |||
$this->buildTransIdPanel($panelName, $entityClass, true) | |||
); | |||
} | |||
public function transTitle($pageName, $entityClass = null, $params = []) | |||
{ | |||
$entityName = $this->getEntityName($entityClass); | |||
$paramsTranslation = [] ; | |||
if($entityName) { | |||
$baseIdEntityLabel = 'entity.' . $entityName ; | |||
$paramsTranslation = [ | |||
'%label%' => $this->trans($baseIdEntityLabel . '.label'), | |||
'%label_plurial%' => $this->trans($baseIdEntityLabel . '.label_plurial'), | |||
] ; | |||
} | |||
if (isset($params['id'])) { | |||
$paramsTranslation['%id%'] = $params['id']; | |||
} | |||
return $this->trans( | |||
'title.' . $pageName, | |||
$paramsTranslation | |||
); | |||
} | |||
private function transEntityThenDefault($idTranslationEntity, $idTranslationDefault, $returnEmpty = false): string | |||
{ | |||
$translation = $this->trans($idTranslationEntity); | |||
if ($translation == $idTranslationEntity) { | |||
$translation = $this->trans($idTranslationDefault); | |||
if ($translation == $idTranslationDefault) { | |||
if ($returnEmpty) { | |||
$translation = ''; | |||
} else { | |||
$translation = $idTranslationEntity; | |||
} | |||
} | |||
} | |||
return $translation; | |||
} | |||
private function buildTransIdField($fieldName, $entityClass, $default = false): string | |||
{ | |||
if ($default) { | |||
$entityName = 'default'; | |||
} else { | |||
$entityName = $this->getEntityName($entityClass); | |||
} | |||
return 'entity.' . $entityName . '.fields.' . $fieldName; | |||
} | |||
private function buildTransIdPanel($panelName, $entityClass, $default = false): string | |||
{ | |||
if ($default) { | |||
$entityName = 'default'; | |||
} else { | |||
$entityName = $this->getEntityName($entityClass); | |||
} | |||
return 'entity.' . $entityName . '.panels.' . $panelName; | |||
} | |||
private function trans($id, $params = [], $domain = self::DOMAIN): string | |||
{ | |||
return $this->translator->trans($id, $params, $domain); | |||
} | |||
private function getEntityName($entityClass): string | |||
{ | |||
$entityNameExplode = explode('\\', $entityClass); | |||
return strtolower($entityNameExplode[count($entityNameExplode) - 1]); | |||
} | |||
} | |||
?> |
@@ -3,105 +3,153 @@ | |||
namespace Lc\SovBundle\Twig; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Liip\ImagineBundle\Imagine\Cache\CacheManager; | |||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | |||
use Symfony\Component\HttpFoundation\RequestStack; | |||
use Symfony\Component\HttpKernel\KernelInterface; | |||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |||
use Symfony\Contracts\Translation\TranslatorInterface; | |||
use Twig\Extension\AbstractExtension; | |||
use Twig\TwigFilter; | |||
use Twig\TwigFunction; | |||
class TwigExtension extends AbstractExtension | |||
{ | |||
protected $em; | |||
protected $kernel; | |||
protected $parameterBag; | |||
protected $cacheManager; | |||
protected $requestStack; | |||
protected $router; | |||
public function __construct(KernelInterface $kernel, ParameterBagInterface $parameterBag, CacheManager $cacheManager, EntityManagerInterface $entityManager, RequestStack $requestStack,UrlGeneratorInterface $router) | |||
{ | |||
$this->kernel = $kernel; | |||
$this->parameterBag = $parameterBag; | |||
$this->cacheManager = $cacheManager; | |||
$this->em = $entityManager; | |||
$this->requestStack = $requestStack; | |||
$this->router = $router; | |||
protected $em; | |||
protected $kernel; | |||
protected $parameterBag; | |||
protected $cacheManager; | |||
protected $requestStack; | |||
protected $router; | |||
protected $translator; | |||
protected $translatorAdmin; | |||
public function __construct( | |||
KernelInterface $kernel, | |||
ParameterBagInterface $parameterBag, | |||
CacheManager $cacheManager, | |||
EntityManagerInterface $entityManager, | |||
RequestStack $requestStack, | |||
UrlGeneratorInterface $router, | |||
TranslatorInterface $translator, | |||
TranslatorAdmin $translatorAdmin | |||
) { | |||
$this->kernel = $kernel; | |||
$this->parameterBag = $parameterBag; | |||
$this->cacheManager = $cacheManager; | |||
$this->em = $entityManager; | |||
$this->requestStack = $requestStack; | |||
$this->router = $router; | |||
$this->translator = $translator; | |||
$this->translatorAdmin = $translatorAdmin; | |||
} | |||
public function getFunctions() | |||
{ | |||
return array( | |||
new TwigFunction('lc_liip', [$this, 'lcLiip']), | |||
new TwigFunction('homepage_route', [$this, 'homepageRoute']), | |||
new TwigFunction('page_by_dev_alias', [$this, 'getPageByDevAlias']), | |||
new TwigFunction('translated_urls', [$this, 'getTranslatedUrls']) | |||
); | |||
} | |||
public function getFilters() | |||
{ | |||
return [ | |||
new TwigFilter('lc_cache', [$this, 'lcCache']), | |||
new TwigFilter('lc_trans_admin_field', [$this, 'lcTransAdminField']), | |||
new TwigFilter('lc_trans_admin_help', [$this, 'lcTransAdminHelp']), | |||
new TwigFilter('lc_trans_admin_panel', [$this, 'lcTransAdminPanel']), | |||
new TwigFilter('lc_trans_admin_menu', [$this, 'lcTransAdminMenu']), | |||
new TwigFilter('lc_trans_admin_title', [$this, 'lcTransAdminTitle']), | |||
]; | |||
} | |||
public function lcCache($file) | |||
{ | |||
$cacheTime = filemtime($this->kernel->getProjectDir() . '/public' . $file); | |||
if ($cacheTime) { | |||
return $file . '?c=' . $cacheTime; | |||
} else { | |||
return $file . "?c=0"; | |||
} | |||
public function getFunctions() | |||
{ | |||
return array( | |||
new TwigFunction('lc_liip', [$this, 'lcLiip']), | |||
new TwigFunction('homepage_route', [$this, 'homepageRoute']), | |||
new TwigFunction('page_by_dev_alias', [$this, 'getPageByDevAlias']), | |||
new TwigFunction('translated_urls', [$this, 'getTranslatedUrls']) | |||
); | |||
} | |||
public function lcTransAdminField($fieldName, $entityClass) | |||
{ | |||
return $this->translatorAdmin->transField($fieldName, $entityClass) ; | |||
} | |||
public function lcTransAdminHelp($fieldName, $entityClass) | |||
{ | |||
return $this->translatorAdmin->transHelp($fieldName, $entityClass) ; | |||
} | |||
public function lcTransAdminPanel($panelName, $entityClass) | |||
{ | |||
return $this->translatorAdmin->transPanel($panelName, $entityClass) ; | |||
} | |||
public function lcTransAdminMenu($menuName) | |||
{ | |||
return $this->translator->trans('menu.' . $menuName, [], 'admin');; | |||
} | |||
public function lcTransAdminTitle($pageName, $entityClass = null, $params = []) | |||
{ | |||
return $this->translatorAdmin->transTitle($pageName, $entityClass, $params) ; | |||
} | |||
public function lcLiip($path, $thumb = 'tile', $default = 'default.jpg') | |||
{ | |||
if (substr($path, 0, 1) === '/') { | |||
$path = substr($path, 1); | |||
} | |||
if ($path) { | |||
$fileManagerFolder = substr($this->getFileManagerFolder(), 1); | |||
public function getFilters() | |||
{ | |||
return [ | |||
new TwigFilter('lc_cache', [$this, 'lcCache']), | |||
]; | |||
} | |||
if (strpos($path, $fileManagerFolder) === false) { | |||
$path = $fileManagerFolder . '/' . $path; | |||
} | |||
public function lcCache($file) | |||
{ | |||
$cacheTime = filemtime($this->kernel->getProjectDir() . '/public' . $file); | |||
if ($cacheTime) { | |||
return $file . '?c=' . $cacheTime; | |||
} else { | |||
return $file . "?c=0"; | |||
} | |||
if (file_exists($path)) { | |||
return $this->cacheManager->getBrowserPath($path, $thumb); | |||
} | |||
} | |||
public function lcLiip($path, $thumb = 'tile', $default = 'default.jpg') | |||
{ | |||
if (substr($path, 0, 1) === '/') $path = substr($path, 1); | |||
if ($path) { | |||
$fileManagerFolder = substr($this->getFileManagerFolder(), 1) ; | |||
return $this->cacheManager->getBrowserPath($this->getFileManagerFolder() . '/' . $default, $thumb); | |||
} | |||
if (strpos($path, $fileManagerFolder) === false) { | |||
$path = $fileManagerFolder . '/' . $path; | |||
} | |||
function getTranslatedUrls() | |||
{ | |||
$ret = array(); | |||
$langs = $this->parameterBag->get('app.locales'); | |||
$currentRoute = $this->requestStack->getCurrentRequest()->get('_route'); | |||
if (file_exists($path)) { | |||
return $this->cacheManager->getBrowserPath($path, $thumb); | |||
} | |||
} | |||
$params = array_merge((array)$this->requestStack->getCurrentRequest()->get('_route_params'), $_GET); | |||
return $this->cacheManager->getBrowserPath($this->getFileManagerFolder() . '/' . $default, $thumb); | |||
if ($currentRoute) { | |||
foreach ($langs as $lg) { | |||
$ret[$lg] = $this->router->generate($currentRoute, array_merge($params, array('_locale' => $lg))); | |||
} | |||
} | |||
function getTranslatedUrls() | |||
{ | |||
$ret = array(); | |||
$langs = $this->parameterBag->get('app.locales'); | |||
$currentRoute = $this->requestStack->getCurrentRequest()->get('_route'); | |||
return $ret; | |||
} | |||
$params = array_merge((array)$this->requestStack->getCurrentRequest()->get('_route_params'), $_GET); | |||
public function getFileManagerFolder() | |||
{ | |||
return $this->parameterBag->get('app.path_uploads'); | |||
} | |||
if ($currentRoute) { | |||
foreach($langs as $lg) { | |||
$ret[$lg] = $this->router->generate($currentRoute, array_merge($params, array('_locale'=>$lg))); | |||
} | |||
} | |||
return $ret; | |||
} | |||
public function getFileManagerFolder() | |||
{ | |||
return $this->parameterBag->get('app.path_uploads'); | |||
} | |||
public function homepageRoute(){ | |||
return $this->parameterBag->get('lc_sov.homepage_route'); | |||
} | |||
public function homepageRoute() | |||
{ | |||
return $this->parameterBag->get('lc_sov.homepage_route'); | |||
} | |||
} |