@@ -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(); | |||
} | |||
} | |||
@@ -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( |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
@@ -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) |
@@ -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 |
@@ -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 %} |
@@ -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 %} |