Browse Source

AdminLte intégration action sort

tags/0.1
Fab 3 years ago
parent
commit
1a4e2f08fa
10 changed files with 321 additions and 98 deletions
  1. +101
    -14
      Controller/Admin/AbstractCrudController.php
  2. +1
    -0
      Controller/Admin/DashboardController.php
  3. +68
    -65
      Doctrine/EntityManager.php
  4. +57
    -0
      EventSubscriber/Action/ActionEasyAdminSubscriber.php
  5. +62
    -0
      EventSubscriber/CreateEntityEventSubscriber.php
  6. +1
    -1
      EventSubscriber/Translation/TranslationEasyAdminSubscriber.php
  7. +1
    -1
      Field/CollectionField.php
  8. +5
    -1
      Resources/config/services.yaml
  9. +7
    -0
      Resources/views/adminlte/crud/action/index_children.html.twig
  10. +18
    -16
      Resources/views/adminlte/crud/index.html.twig

+ 101
- 14
Controller/Admin/AbstractCrudController.php View File

@@ -2,7 +2,10 @@

namespace Lc\SovBundle\Controller\Admin;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
@@ -11,6 +14,8 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController as EaAbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
@@ -31,6 +36,7 @@ use Lc\SovBundle\Doctrine\Extension\DevAliasInterface;
use Lc\SovBundle\Doctrine\Extension\SeoInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Field\CollectionField;
use Lc\SovBundle\Field\GalleryManagerField;
use Lc\SovBundle\Form\Type\Crud\PositionType;
@@ -56,7 +62,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController
public function configureActions(Actions $actions): Actions
{
/* Translatable */
if (in_array(TranslatableInterface::class, class_implements($this->getEntityFqcn()))) {
if ($this->isInstanceOf(TranslatableInterface::class)) {
$actions->update(
Crud::PAGE_INDEX,
Action::EDIT,
@@ -124,14 +130,26 @@ abstract class AbstractCrudController extends EaAbstractCrudController
$actions->add(Crud::PAGE_EDIT, Action::DELETE);
$actions->add(Crud::PAGE_NEW, Action::INDEX);

if (in_array(SortableInterface::class, class_implements($this->getEntityFqcn()))) {
if ($this->isInstanceOf(SortableInterface::class)) {
$sortAction = Action::new('sort', 'Ordonner', 'fa fa-sort')
->linkToCrudAction('sort')
->setCssClass('btn btn-info')
->setHtmlAttributes(array('entityId' => 'ncihe'))
->createAsGlobalAction();

$actions->add(Crud::PAGE_INDEX, $sortAction);
}


if ($this->isInstanceOf(TreeInterface::class)) {
$indexChildAction = Action::new('index_children', 'Afficher les enfants', 'fa fa-sort')
->linkToCrudAction(Action::INDEX)
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig')
->setCssClass('btn btn-info');

$actions->add(Crud::PAGE_INDEX, $indexChildAction);
}

$actions->reorder(Crud::PAGE_EDIT, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE]);
$actions->reorder(Crud::PAGE_NEW, [Action::INDEX, Action::SAVE_AND_RETURN, Action::SAVE_AND_ADD_ANOTHER]);

@@ -151,7 +169,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'])) {
@@ -193,7 +211,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) {
@@ -208,7 +226,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController

public function configureFields(string $pageName): iterable
{
if (in_array(SeoInterface::class, class_implements($this->getEntityFqcn()))) {
if ($this->isInstanceOf(SortableInterface::class)) {
$seoPanel = [
FormField::addPanel('Seo'),
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp(
@@ -224,7 +242,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController
];
}

if (in_array(DevAliasInterface::class, class_implements($this->getEntityFqcn()))) {
if ($this->isInstanceOf(DevAliasInterface::class)) {
$confPanel = [
FormField::addPanel('Conf'),
TextField::new('devAlias')->hideOnIndex(),
@@ -235,7 +253,6 @@ abstract class AbstractCrudController extends EaAbstractCrudController
}



public function sort(AdminContext $context)
{
$event = new BeforeCrudActionEvent($context);
@@ -244,10 +261,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController
return $event->getResponse();
}

if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !in_array(
SortableInterface::class,
class_implements($this->getEntityFqcn())
)) {
if (!$this->isGranted(Permission::EA_EXECUTE_ACTION) || !$this->isInstanceOf(SortableInterface::class)) {
throw new ForbiddenActionException($context);
}

@@ -276,13 +290,12 @@ abstract class AbstractCrudController extends EaAbstractCrudController
->getForm();

$entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn());
dump($entityManager);
$repository = $entityManager->getRepository($this->getEntityFqcn());

$sortableForm->handleRequest($context->getRequest());

if ($sortableForm->isSubmitted() && $sortableForm->isValid()) {
// $entityInstance = $event->getEntityInstance();

foreach ($sortableForm->get('entities')->getData() as $elm) {
$entityInstance = $repository->find($elm['id']);
$entityDto = $context->getEntity()->newWithInstance($entityInstance);
@@ -304,7 +317,7 @@ abstract class AbstractCrudController extends EaAbstractCrudController
$url = $this->get(AdminUrlGenerator::class)
->setAction(Action::INDEX)
->generateUrl();
$this->addFlash('success', 'Position modifié', array(), 'mweb');
$this->addFlash('success', 'Position modifié', array());

return $this->redirect($url);
}
@@ -332,5 +345,79 @@ abstract class AbstractCrudController extends EaAbstractCrudController

return $responseParameters;
}

public function createIndexQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder {
$queryBuilder = parent::createIndexQueryBuilder(
$searchDto,
$entityDto,
$fields,
$filters
);

dump(get_defined_vars());
if ($this->isInstanceOf(TreeInterface::class)) {
$entityId = $searchDto->getRequest()->get('entityId');
if ($entityId !== null) {
$queryBuilder->andWhere('entity.parent = :entityId');
$queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId'));
} else {
$queryBuilder->andWhere('entity.parent IS NULL');
}
}


return $queryBuilder;
}

public function createSortQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): QueryBuilder {
$queryBuilder = parent::createIndexQueryBuilder(
$searchDto,
$entityDto,
$fields,
$filters
);

if ($this->isInstanceOf(TreeInterface::class)) {
$entityId = $searchDto->getRequest()->get('entityId');
if ($entityId !== null) {
$queryBuilder->andWhere('entity.parent = :entityId');
$queryBuilder->setParameter('entityId', $searchDto->getRequest()->get('entityId'));
} else {
$queryBuilder->andWhere('entity.parent IS NULL');
}
}


return $queryBuilder;
}

public function isInstanceOf(string $interfaceName): bool
{
return in_array($interfaceName, class_implements($this->getEntityFqcn()));
}


public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->update($entityInstance);
$entityManager->flush();
}

public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$entityManager->create($entityInstance);
$entityManager->flush();
}

}


+ 1
- 0
Controller/Admin/DashboardController.php View File

@@ -82,6 +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',
]
)
->setFormThemes(

+ 68
- 65
Doctrine/EntityManager.php View File

@@ -2,6 +2,7 @@

namespace Lc\SovBundle\Doctrine;

use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\EntityManager as DoctrineEntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
@@ -11,92 +12,94 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* class EntityManager.
*
* @author Simon Vieille <simon@deblan.fr>
* @author La clic !!!!
*/
class EntityManager
class EntityManager extends EntityManagerDecorator
{
protected EventDispatcherInterface $eventDispatcher;
protected EventDispatcherInterface $eventDispatcher;

protected DoctrineEntityManager $entityManager;
protected DoctrineEntityManager $entityManager;

public function __construct(EventDispatcherInterface $eventDispatcher, EntityManagerInterface $entityManager)
{
$this->eventDispatcher = $eventDispatcher;
$this->entityManager = $entityManager;
}

public function getRepository($className)
{
return $this->entityManager->getRepository($this->getEntityName($className));
}
public function __construct(EntityManagerInterface $wrapped, EventDispatcherInterface $eventDispatcher)
{
$this->eventDispatcher = $eventDispatcher;
parent::__construct($wrapped);
}

public function new($className)
{
$entityName = $this->getEntityName($className);
return new $entityName;
}
public function getRepository($className)
{
return $this->wrapped->getRepository($this->getEntityName($className));
}

public function create(EntityInterface $entity): self
{
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::CREATE_EVENT);
public function new($className)
{
$entityName = $this->getEntityName($className);

return $this;
}
return new $entityName;
}

public function update(EntityInterface $entity): self
{
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::UPDATE_EVENT);
public function create(EntityInterface $entity): self
{
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::CREATE_EVENT);

return $this;
}
return $this;
}

public function delete(EntityInterface $entity): self
{
$this->remove($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::DELETE_EVENT);
public function update(EntityInterface $entity): self
{
$this->persist($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::UPDATE_EVENT);

return $this;
}
return $this;
}

public function flush(): self
{
$this->entityManager->flush();
public function delete(EntityInterface $entity): self
{
$this->remove($entity);
$this->eventDispatcher->dispatch(new EntityManagerEvent($entity), EntityManagerEvent::DELETE_EVENT);

return $this;
}
return $this;
}

public function clear(): self
{
$this->entityManager->clear();
public function flush($entity=null): self
{
$this->wrapped->flush($entity);

return $this;
}
return $this;
}

public function refresh(EntityInterface $entity): self
{
$this->entityManager->refresh($entity);
public function clear($objectName = null): self
{
$this->wrapped->clear($objectName);

return $this;
}
return $this;
}

protected function persist(EntityInterface $entity)
{
$this->entityManager->persist($entity);
}
public function refresh($object): self
{
$this->wrapped->refresh($object);

public function getClassMetadata($className){
return $this->entityManager->getClassMetadata($className);
}
return $this;
}

public function persist($entity)
{
$this->wrapped->persist($entity);
}

public function getEntityName($className)
{
if (substr($className, -9) === 'Interface') {
return $this->entityManager->getClassMetadata($className)->getName();
}else{
return $className;
}
public function getClassMetadata($className)
{
return $this->wrapped->getClassMetadata($className);
}

public function getEntityName($className)
{
if (substr($className, -9) === 'Interface') {
return $this->wrapped->getClassMetadata($className)->getName();
} else {
return $className;
}
}
}

+ 57
- 0
EventSubscriber/Action/ActionEasyAdminSubscriber.php View File

@@ -0,0 +1,57 @@
<?php

namespace Lc\SovBundle\EventSubscriber\Action;

use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Query;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Gedmo\Translatable\TranslatableListener;
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface;
use Lc\SovBundle\Doctrine\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use function Symfony\Component\Translation\t;

class ActionEasyAdminSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;

public function __construct(EntityManager $entityManager, AdminUrlGenerator $adminUrlGenerator)
{
$this->em = $entityManager;
$this->adminUrlGenerator = $adminUrlGenerator;
}

public static function getSubscribedEvents()
{
return [
AfterCrudActionEvent::class => ['overrideSortAction'],
];
}

public function overrideSortAction(AfterCrudActionEvent $event)
{
$actions = $event->getResponseParameters()->get('global_actions');
if ($actions) {
foreach ($actions as $action) {
if ($action->getName() == 'sort') {
$entityId = $event->getAdminContext()->getRequest()->get('entityId');
if ($entityId != null) {
$url = $this->adminUrlGenerator
->setController($event->getAdminContext()->getCrud()->getControllerFqcn())
->setAction($action->getName())
->set('entityId', $entityId)
->generateUrl();
$action->setLinkUrl($url);
}
}
}
}
}


}

+ 62
- 0
EventSubscriber/CreateEntityEventSubscriber.php View File

@@ -0,0 +1,62 @@
<?php

namespace Lc\SovBundle\EventSubscriber;

use Doctrine\ORM\EntityManagerInterface;

use Lc\SovBundle\Doctrine\EntityInterface;
use Lc\SovBundle\Doctrine\Extension\SortableInterface;
use Lc\SovBundle\Doctrine\Extension\StatusInterface;
use Lc\SovBundle\Doctrine\Extension\TreeInterface;
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent;
use Lc\SovBundle\Repository\AbstractRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CreateEntityEventSubscriber implements EventSubscriberInterface
{
protected $em;
protected $adminUrlGenerator;

public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}

public static function getSubscribedEvents()
{
return [
EntityManagerEvent::CREATE_EVENT => ['createEntity'],
];
}

public function createEntity(EntityManagerEvent $event)
{
$entity = $event->getEntity();
$entityRepository = $this->em->getRepository(get_class($entity));
if ($entity instanceof SortableInterface) {
$this->setSortableProperty($entity, $entityRepository);
}
}


private function setSortableProperty(EntityInterface $entity, AbstractRepositoryInterface $entityRepository)
{
if ($entity instanceof StatusInterface) {
$countParam['status'] = 1;
}

if ($entity instanceof TreeInterface) {
if($entity->getParent()){
$countParam['parent'] = $entity->getParent()->getId();
}else{
$countParam['parent'] = null;
}
}

$total = $entityRepository->count($countParam);

$entity->setPosition($total);
}


}

+ 1
- 1
EventSubscriber/Translation/TranslationEasyAdminSubscriber.php View File

@@ -13,7 +13,7 @@ use Lc\SovBundle\Doctrine\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function Symfony\Component\Translation\t;

class TranslationEasyAdminSubscriber implements EventSubscriberInterface
class TranslationEasyAdminSubscriber implements EventSubscriberInterface
{
protected $em;


+ 1
- 1
Field/CollectionField.php View File

@@ -24,7 +24,7 @@ class CollectionField implements FieldInterface
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setTemplatePath('@LcSov/tabler/crud/field/collection.html.twig')
->setTemplatePath('@LcSov/adminlte/crud/field/collection.html.twig')
->setFormType(CollectionType::class)
->addWebpackEncoreEntries('adminlte-field-collection')
->setFormTypeOption('allow_add', true)

+ 5
- 1
Resources/config/services.yaml View File

@@ -20,5 +20,9 @@ services:
decorates: EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType
arguments: ['@form.type_guesser.doctrine', '@.inner']

Lc\SovBundle\Doctrine\EntityManager:
public: false
decorates: doctrine.orm.default_entity_manager
arguments: ["@.inner"]
# EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType:
# class: Lc\SovBundle\Form\Type\CrudFormType
# class: Lc\SovBundle\Form\Type\CrudFormType

+ 7
- 0
Resources/views/adminlte/crud/action/index_children.html.twig View File

@@ -0,0 +1,7 @@
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #}
{# @var action \EasyCorp\Bundle\EasyAdminBundle\Dto\ActionDto #}
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #}

{% if entity.instance.childrens|length > 0%}
{{ include('@EasyAdmin/crud/action.html.twig') }}
{% endif %}

+ 18
- 16
Resources/views/adminlte/crud/index.html.twig View File

@@ -60,7 +60,7 @@
<tr>
{% if has_batch_actions %}
<th class="">
<input type="hidden" id="batch_form_entityIds" value="" />
<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>
@@ -71,21 +71,23 @@

{% for field in fields ?? [] %}
{% set field = field.getAsDto() %}

{% set is_sorting_field = ea.search.isSortingField(field.property) %}
{% set next_sort_direction = is_sorting_field ? (ea.search.sortDirection(field.property) == ea_sort_desc ? ea_sort_asc : ea_sort_desc) : ea_sort_desc %}
{% set column_icon = is_sorting_field ? (next_sort_direction == ea_sort_desc ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %}

<th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}"
dir="{{ ea.i18n.textDirection }}">
{% if field.isSortable %}
<a href="{{ ea_url({ page: 1, sort: { (field.property): next_sort_direction } }).includeReferrer() }}">
{{ field.label|raw }} <i class="fa fa-fw {{ column_icon }}"></i>
</a>
{% else %}
<span>{{ field.label|raw }}</span>
{% endif %}
</th>
{% if field.isDisplayedOn('index') %}

{% set is_sorting_field = ea.search.isSortingField(field.property) %}
{% set next_sort_direction = is_sorting_field ? (ea.search.sortDirection(field.property) == ea_sort_desc ? ea_sort_asc : ea_sort_desc) : ea_sort_desc %}
{% set column_icon = is_sorting_field ? (next_sort_direction == ea_sort_desc ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %}

<th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}"
dir="{{ ea.i18n.textDirection }}">
{% if field.isSortable %}
<a href="{{ ea_url({ page: 1, sort: { (field.property): next_sort_direction } }).includeReferrer() }}">
{{ field.label ? field.label|raw : field.getProperty|raw }} <i class="fa fa-fw {{ column_icon }}"></i>
</a>
{% else %}
<span>{{ field.label ? field.label|raw : field.getProperty|raw }}</span>
{% endif %}
</th>
{% endif %}
{% endfor %}

<th class="w-1" {% if ea.crud.showEntityActionsAsDropdown %}width="10px"{% endif %}

Loading…
Cancel
Save