namespace Lc\SovBundle\Builder\Ticket; | namespace Lc\SovBundle\Builder\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | use Lc\SovBundle\Notification\MailMailjetNotification; | ||||
use Lc\SovBundle\Component\FormComponent; | use Lc\SovBundle\Component\FormComponent; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Lc\SovBundle\Repository\User\UserStore; | use Lc\SovBundle\Repository\User\UserStore; | ||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | ||||
use Symfony\Component\EventDispatcher\EventDispatcher; | |||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | ||||
use Symfony\Component\Security\Core\Security; | use Symfony\Component\Security\Core\Security; | ||||
protected TicketFactory $ticketFactory; | protected TicketFactory $ticketFactory; | ||||
protected AuthorizationCheckerInterface $authorizationChecker; | protected AuthorizationCheckerInterface $authorizationChecker; | ||||
protected UserStore $userStore; | protected UserStore $userStore; | ||||
protected EventDispatcherInterface $eventDispatcher; | |||||
public function __construct( | public function __construct( | ||||
Security $security, | Security $security, | ||||
ParameterBagInterface $parameterBag, | ParameterBagInterface $parameterBag, | ||||
AuthorizationCheckerInterface $authorizationChecker, | AuthorizationCheckerInterface $authorizationChecker, | ||||
TicketFactory $ticketFactory, | TicketFactory $ticketFactory, | ||||
UserStore $userStore | |||||
UserStore $userStore, | |||||
EventDispatcherInterface $eventDispatcher | |||||
) { | ) { | ||||
$this->security = $security; | $this->security = $security; | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->ticketFactory = $ticketFactory; | $this->ticketFactory = $ticketFactory; | ||||
$this->userStore = $userStore; | $this->userStore = $userStore; | ||||
$this->authorizationChecker = $authorizationChecker; | $this->authorizationChecker = $authorizationChecker; | ||||
$this->eventDispatcher = $eventDispatcher; | |||||
} | } | ||||
public function create(array $params = []): TicketInterface | public function create(array $params = []): TicketInterface | ||||
$this->init($ticket, $params); | $this->init($ticket, $params); | ||||
$user = $ticket->getUser(); | |||||
if ($ticket->getUser()) { | |||||
$email = $user->getEmail(); | |||||
$firstname = $user->getFirstname(); | |||||
} else { | |||||
$email = $params['visitorEmail']; | |||||
$firstname = $params['visitorFirstname']; | |||||
} | |||||
$this->entityManager->create($ticket); | $this->entityManager->create($ticket); | ||||
$this->entityManager->flush(); | $this->entityManager->flush(); | ||||
if (isset($params['createByAdmin']) && $params['createByAdmin']) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Vous avez reçu un nouveau message', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new-by-admin', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} else { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouvelle demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
// notifyAdmin | |||||
$usersToNotify = $this->userStore->getByTicketTypesNotification($ticket->getType()); | |||||
foreach ($usersToNotify as $userToNotify) { | |||||
if ($this->authorizationChecker->isGranted('ROLE_ADMIN', $userToNotify)) { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouveau ticket sur Place du Local', | |||||
MailMailjetNotification::TO_EMAIL => $userToNotify->getEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-notification', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $userToNotify->getFirstname(), | |||||
'ticket' => $ticket, | |||||
'ticketMessage' => $ticket->getTicketMessages()[0], | |||||
], | |||||
] | |||||
); | |||||
} | |||||
} | |||||
$this->eventDispatcher->dispatch(new TicketEvent($ticket), TicketEvent::NEW_TICKET_EVENT); | |||||
return $ticket; | return $ticket; | ||||
} | } | ||||
public function init(TicketInterface $ticket, array $params = []): void | public function init(TicketInterface $ticket, array $params = []): void | ||||
{ | { | ||||
$user = $this->security->getUser(); | $user = $this->security->getUser(); | ||||
if($user) { | |||||
if ($user) { | |||||
$ticket->setCreatedBy($user); | $ticket->setCreatedBy($user); | ||||
} | } | ||||
if (isset($params['section'])) { | |||||
$ticket->setSection($params['section']); | |||||
} | |||||
$ticket->setMerchant($params['merchant']); | |||||
if (isset($params['user'])) { | if (isset($params['user'])) { | ||||
$ticket->setUser($params['user']); | $ticket->setUser($params['user']); | ||||
} else { | } else { | ||||
$ticket->setVisitorFirstname($params['visitorFirstname']); | $ticket->setVisitorFirstname($params['visitorFirstname']); | ||||
$ticket->setVisitorLastname($params['visitorLastname']); | $ticket->setVisitorLastname($params['visitorLastname']); |
namespace Lc\SovBundle\Builder\Ticket; | namespace Lc\SovBundle\Builder\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | use Lc\SovBundle\Notification\MailMailjetNotification; | ||||
use Lc\SovBundle\Component\FormComponent; | use Lc\SovBundle\Component\FormComponent; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | ||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||||
class TicketMessageBuilder | class TicketMessageBuilder | ||||
{ | { | ||||
protected EntityManagerInterface $entityManager; | protected EntityManagerInterface $entityManager; | ||||
protected MailMailjetNotification $mailMailjetNotification; | protected MailMailjetNotification $mailMailjetNotification; | ||||
protected TicketMessageFactory $ticketMessageFactory; | protected TicketMessageFactory $ticketMessageFactory; | ||||
protected EventDispatcherInterface $eventDispatcher; | |||||
public function __construct( | public function __construct( | ||||
EntityManagerInterface $entityManager, | EntityManagerInterface $entityManager, | ||||
MailMailjetNotification $mailMailjetNotification, | MailMailjetNotification $mailMailjetNotification, | ||||
TicketMessageFactory $ticketMessageFactory | |||||
TicketMessageFactory $ticketMessageFactory, | |||||
EventDispatcherInterface $eventDispatcher | |||||
) { | ) { | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->mailMailjetNotification = $mailMailjetNotification; | $this->mailMailjetNotification = $mailMailjetNotification; | ||||
$this->ticketMessageFactory = $ticketMessageFactory; | $this->ticketMessageFactory = $ticketMessageFactory; | ||||
$this->eventDispatcher = $eventDispatcher; | |||||
} | } | ||||
public function create(array $params = []): TicketMessageInterface | public function create(array $params = []): TicketMessageInterface | ||||
$ticketMessage->setStatus(1); | $ticketMessage->setStatus(1); | ||||
$ticketMessage->setTicket($ticket); | $ticketMessage->setTicket($ticket); | ||||
$ticketMessage->setMessage($params['message']); | $ticketMessage->setMessage($params['message']); | ||||
if (isset($params['answerByAdmin']) && $params['answerByAdmin']) { | if (isset($params['answerByAdmin']) && $params['answerByAdmin']) { | ||||
$ticketMessage->setAnswerByAdmin($params['answerByAdmin']); | $ticketMessage->setAnswerByAdmin($params['answerByAdmin']); | ||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Réponse à votre demande', | |||||
MailMailjetNotification::TO_EMAIL => $ticket->getUser() ? $ticket->getUser()->getEmail( | |||||
) : $ticket->getVisitorEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-response', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $ticket->getUser() ? $ticket->getUser()->getFirstname( | |||||
) : $ticket->getVisitorFirstname(), | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | } | ||||
$this->entityManager->persist($ticketMessage); | $this->entityManager->persist($ticketMessage); | ||||
$ticket->setUpdatedAt(new \DateTime()); | $ticket->setUpdatedAt(new \DateTime()); | ||||
$this->entityManager->persist($ticket); | |||||
$this->entityManager->create($ticket); | |||||
$this->entityManager->flush(); | $this->entityManager->flush(); | ||||
$this->eventDispatcher->dispatch(new TicketEvent($ticket), TicketEvent::NEW_MESSAGE_EVENT); | |||||
return $ticketMessage; | return $ticketMessage; | ||||
} | } | ||||
namespace Lc\SovBundle\Container\Ticket; | namespace Lc\SovBundle\Container\Ticket; | ||||
use Lc\SovBundle\Builder\Ticket\TicketBuilder; | use Lc\SovBundle\Builder\Ticket\TicketBuilder; | ||||
use Lc\SovBundle\Definition\Field\Ticket\TicketFieldDefinition; | |||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery; | use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery; | ||||
use Lc\SovBundle\Repository\Ticket\TicketStore; | use Lc\SovBundle\Repository\Ticket\TicketStore; | ||||
protected TicketRepositoryQuery $repositoryQuery; | protected TicketRepositoryQuery $repositoryQuery; | ||||
protected TicketStore $store; | protected TicketStore $store; | ||||
protected TicketSolver $solver; | protected TicketSolver $solver; | ||||
protected TicketFieldDefinition $fieldDefinition; | |||||
public function __construct( | public function __construct( | ||||
TicketFactory $factory, | TicketFactory $factory, | ||||
TicketBuilder $builder, | TicketBuilder $builder, | ||||
TicketRepositoryQuery $repositoryQuery, | TicketRepositoryQuery $repositoryQuery, | ||||
TicketStore $store, | TicketStore $store, | ||||
TicketSolver $solver | |||||
TicketSolver $solver, | |||||
TicketFieldDefinition $fieldDefinition | |||||
) { | ) { | ||||
$this->factory = $factory; | $this->factory = $factory; | ||||
$this->builder = $builder; | $this->builder = $builder; | ||||
$this->repositoryQuery = $repositoryQuery; | $this->repositoryQuery = $repositoryQuery; | ||||
$this->store = $store; | $this->store = $store; | ||||
$this->solver = $solver; | $this->solver = $solver; | ||||
$this->fieldDefinition = $fieldDefinition; | |||||
} | } | ||||
public function getFactory(): TicketFactory | public function getFactory(): TicketFactory | ||||
{ | { | ||||
return $this->solver; | return $this->solver; | ||||
} | } | ||||
public function getFieldDefinition(): TicketFieldDefinition | |||||
{ | |||||
return $this->fieldDefinition; | |||||
} | |||||
} | } |
use Lc\SovBundle\Doctrine\Extension\DevAliasInterface; | use Lc\SovBundle\Doctrine\Extension\DevAliasInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\SeoInterface; | use Lc\SovBundle\Doctrine\Extension\SeoInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\SortableInterface; | use Lc\SovBundle\Doctrine\Extension\SortableInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\StatusInterface; | |||||
use Lc\SovBundle\Doctrine\Extension\TranslatableInterface; | use Lc\SovBundle\Doctrine\Extension\TranslatableInterface; | ||||
use Lc\SovBundle\Doctrine\Extension\TreeInterface; | use Lc\SovBundle\Doctrine\Extension\TreeInterface; | ||||
use Lc\SovBundle\Field\CollectionField; | use Lc\SovBundle\Field\CollectionField; | ||||
use Lc\SovBundle\Field\Filter\FilterManager; | use Lc\SovBundle\Field\Filter\FilterManager; | ||||
use Lc\SovBundle\Form\Common\FiltersFormType; | use Lc\SovBundle\Form\Common\FiltersFormType; | ||||
use Lc\SovBundle\Form\Common\PositionType; | use Lc\SovBundle\Form\Common\PositionType; | ||||
use Lc\SovBundle\Model\User\UserInterface; | |||||
use Lc\SovBundle\Repository\EntityRepository; | use Lc\SovBundle\Repository\EntityRepository; | ||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | use Lc\SovBundle\Repository\RepositoryQueryInterface; | ||||
use Lc\SovBundle\Translation\FlashBagTranslator; | use Lc\SovBundle\Translation\FlashBagTranslator; | ||||
use ControllerTrait; | use ControllerTrait; | ||||
protected FormInterface $filtersForm; | protected FormInterface $filtersForm; | ||||
protected bool $isRepositoryQueryFiltered = false; | |||||
abstract public function getRepositoryQuery(): RepositoryQueryInterface; | abstract public function getRepositoryQuery(): RepositoryQueryInterface; | ||||
if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) { | if (Crud::PAGE_INDEX === $responseParameters->get('pageName')) { | ||||
$responseParameters->set('fields', $this->configureFields('index')); | $responseParameters->set('fields', $this->configureFields('index')); | ||||
//TODO supprimer ce code rapport au filtre dans les index | |||||
/*if ($this->filtersForm === null) { | |||||
die('nncncd'); | |||||
$options['fields'] = $responseParameters->get('fields'); | |||||
$options['entity_class'] = $this->getEntityFqcn(); | |||||
$options['entity_name'] = $responseParameters->get('entity')->getName(); | |||||
$this->filtersForm = $this->createForm(FiltersFormType::class, null, $options); | |||||
}*/ | |||||
$responseParameters->set('filters_form', $this->filtersForm); | |||||
if(isset($this->filtersForm)) { | |||||
$responseParameters->set('filters_form', $this->filtersForm); | |||||
} | |||||
} | } | ||||
$responseParameters->set('translation_entity_name', $this->getTranslationEntityName()); | $responseParameters->set('translation_entity_name', $this->getTranslationEntityName()); | ||||
if ($entity !== null) { | if ($entity !== null) { | ||||
if ($entity->getParent() !== null) { | if ($entity->getParent() !== null) { | ||||
$url = $adminUrlGenerator | $url = $adminUrlGenerator | ||||
->setController($context->getCrud()->getControllerFqcn()) | |||||
->set('entityId', $entity->getParent()->getId()) | |||||
->generateUrl(); | |||||
->setController($context->getCrud()->getControllerFqcn()) | |||||
->set('entityId', $entity->getParent()->getId()) | |||||
->generateUrl(); | |||||
$action->setLinkUrl($url); | $action->setLinkUrl($url); | ||||
} | } | ||||
} else { | } else { | ||||
$entityId = $context->getRequest()->get('entityId'); | $entityId = $context->getRequest()->get('entityId'); | ||||
if ($entityId != null) { | if ($entityId != null) { | ||||
$url = $adminUrlGenerator | $url = $adminUrlGenerator | ||||
->setController($context->getCrud()->getControllerFqcn()) | |||||
->setAction($action->getName()) | |||||
->set('entityId', $entityId) | |||||
->generateUrl(); | |||||
->setController($context->getCrud()->getControllerFqcn()) | |||||
->setAction($action->getName()) | |||||
->set('entityId', $entityId) | |||||
->generateUrl(); | |||||
$action->setLinkUrl($url); | $action->setLinkUrl($url); | ||||
} | } | ||||
} | } | ||||
if ($action->getName() == ActionDefinition::WRITE_TO_USER) { | |||||
$entity = $context->getEntity()->getInstance(); | |||||
if ($entity !== null) { | |||||
if(method_exists($entity, 'getUser')){ | |||||
$url = $this->generateEaUrl(UserA) ->setController($context->getCrud()->getControllerFqcn()) | |||||
->set('entityId', $entity->getParent()->getId()) | |||||
->generateUrl(); | |||||
$action->setLinkUrl($url); | |||||
} | |||||
} else { | |||||
unset($actions[$i]); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
protected function getRequestCrudAction() :string{ | |||||
return $this->getRequestStack()->getCurrentRequest()->get('crudAction'); | |||||
} | |||||
public function configureCrud(Crud $crud): Crud | public function configureCrud(Crud $crud): Crud | ||||
{ | { | ||||
$crud = parent::configureCrud($crud); | $crud = parent::configureCrud($crud); | ||||
$this->setMaxResults($crud); | |||||
if($this->getRequestCrudAction() === ActionDefinition::SORT) { | |||||
$crud->setPaginatorPageSize(9999); | |||||
}else { | |||||
$this->setMaxResults($crud); | |||||
} | |||||
$crud->setFormOptions(['translation_entity_name' => $this->getTranslationEntityName()]); | $crud->setFormOptions(['translation_entity_name' => $this->getTranslationEntityName()]); | ||||
$this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults); | $this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults); | ||||
} | } | ||||
$maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get( | $maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get( | ||||
$paramSessionListMaxResults | |||||
$paramSessionListMaxResults | |||||
) : 30; | ) : 30; | ||||
$crud->setPaginatorPageSize($maxResults); | $crud->setPaginatorPageSize($maxResults); | ||||
{ | { | ||||
if ($this->isInstanceOf(SeoInterface::class)) { | if ($this->isInstanceOf(SeoInterface::class)) { | ||||
return [ | return [ | ||||
FormField::addPanel('seo')->setTemplateName('crud/field/generic'), | |||||
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
)->hideOnIndex(), | |||||
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
FormField::addPanel('seo')->setTemplateName('crud/field/generic'), | |||||
TextField::new('metaTitle')->setLabel('Meta Title')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
)->hideOnIndex(), | |||||
TextareaField::new('metaDescription')->setLabel('Meta description')->setHelp( | |||||
'Affiché dans les résultats de recherche Google' | |||||
)->hideOnIndex(), | |||||
CollectionField::new('oldUrls') | |||||
->setFormTypeOption('entry_type', TextType::class)->setLabel( | |||||
'Anciennes urls du document' | |||||
)->hideOnIndex(), | )->hideOnIndex(), | ||||
CollectionField::new('oldUrls') | |||||
->setFormTypeOption('entry_type', TextType::class)->setLabel( | |||||
'Anciennes urls du document' | |||||
)->hideOnIndex(), | |||||
]; | ]; | ||||
} else { | } else { | ||||
return null; | return null; | ||||
{ | { | ||||
if ($this->isInstanceOf(DevAliasInterface::class)) { | if ($this->isInstanceOf(DevAliasInterface::class)) { | ||||
return [ | return [ | ||||
FormField::addPanel('configuration')->setTemplateName('crud/field/generic'), | |||||
TextField::new('devAlias')->hideOnIndex(), | |||||
FormField::addPanel('configuration')->setTemplateName('crud/field/generic'), | |||||
TextField::new('devAlias')->hideOnIndex(), | |||||
]; | ]; | ||||
} else { | } else { | ||||
return null; | return null; | ||||
$fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX)); | $fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX)); | ||||
$filters = $this->get(FilterFactory::class)->create( | $filters = $this->get(FilterFactory::class)->create( | ||||
$context->getCrud()->getFiltersConfig(), | |||||
$fields, | |||||
$context->getEntity() | |||||
$context->getCrud()->getFiltersConfig(), | |||||
$fields, | |||||
$context->getEntity() | |||||
); | ); | ||||
$queryBuilder = $this->createIndexQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters); | |||||
$queryBuilder = $this->createSortQueryBuilder($context->getSearch(), $context->getEntity(), $fields, $filters); | |||||
$paginator = $this->get(PaginatorFactory::class)->create($queryBuilder); | $paginator = $this->get(PaginatorFactory::class)->create($queryBuilder); | ||||
$entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults()); | $entities = $this->get(EntityFactory::class)->createCollection($context->getEntity(), $paginator->getResults()); | ||||
$this->get(EntityFactory::class)->processFieldsForAll($entities, $fields); | $this->get(EntityFactory::class)->processFieldsForAll($entities, $fields); | ||||
$sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults())) | $sortableForm = $this->createFormBuilder(array('entities', $paginator->getResults())) | ||||
->add( | |||||
'entities', | |||||
CollectionType::class, | |||||
array( | |||||
'required' => true, | |||||
'allow_add' => true, | |||||
'entry_type' => PositionType::class, | |||||
) | |||||
->add( | |||||
'entities', | |||||
CollectionType::class, | |||||
array( | |||||
'required' => true, | |||||
'allow_add' => true, | |||||
'entry_type' => PositionType::class, | |||||
) | ) | ||||
->getForm(); | |||||
) | |||||
->getForm(); | |||||
$entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn()); | $entityManager = $this->getDoctrine()->getManagerForClass($this->getEntityFqcn()); | ||||
$repository = $entityManager->getRepository($this->getEntityFqcn()); | $repository = $entityManager->getRepository($this->getEntityFqcn()); | ||||
} | } | ||||
$url = $this->get(AdminUrlGenerator::class) | $url = $this->get(AdminUrlGenerator::class) | ||||
->setAction(ActionDefinition::INDEX) | |||||
->generateUrl(); | |||||
->setAction(ActionDefinition::INDEX) | |||||
->generateUrl(); | |||||
$this->addFlashTranslator('success', 'sorted'); | $this->addFlashTranslator('success', 'sorted'); | ||||
return $this->redirect($url); | return $this->redirect($url); | ||||
} | } | ||||
$responseParameters = $this->configureResponseParameters( | $responseParameters = $this->configureResponseParameters( | ||||
KeyValueStore::new( | |||||
[ | |||||
'pageName' => Crud::PAGE_INDEX, | |||||
'templatePath' => '@LcSov/adminlte/crud/sort.html.twig', | |||||
'entities' => $entities, | |||||
'paginator' => $paginator, | |||||
'global_actions' => array(), | |||||
'batch_actions' => array(), | |||||
'filters' => $filters, | |||||
'sortable_form' => $sortableForm, | |||||
] | |||||
) | |||||
KeyValueStore::new( | |||||
[ | |||||
'pageName' => Crud::PAGE_INDEX, | |||||
'templatePath' => '@LcSov/adminlte/crud/sort.html.twig', | |||||
'entities' => $entities, | |||||
'paginator' => $paginator, | |||||
'global_actions' => array(), | |||||
'batch_actions' => array(), | |||||
'filters' => $filters, | |||||
'sortable_form' => $sortableForm, | |||||
] | |||||
) | |||||
); | ); | ||||
$responseParameters->set('fields', $this->configureFields('index')); | $responseParameters->set('fields', $this->configureFields('index')); | ||||
$event = new AfterCrudActionEvent($context, $responseParameters); | $event = new AfterCrudActionEvent($context, $responseParameters); | ||||
} | } | ||||
public function duplicate( | public function duplicate( | ||||
AdminContext $context, | |||||
EntityComponent $entityComponent, | |||||
TranslatorAdmin $translatorAdmin, | |||||
EntityManagerInterface $em | |||||
AdminContext $context, | |||||
EntityComponent $entityComponent, | |||||
TranslatorAdmin $translatorAdmin, | |||||
EntityManagerInterface $em | |||||
) { | ) { | ||||
if (!$this->isGranted( | if (!$this->isGranted( | ||||
Permission::EA_EXECUTE_ACTION, | |||||
['action' => "duplicate", 'entity' => $context->getEntity()] | |||||
Permission::EA_EXECUTE_ACTION, | |||||
['action' => "duplicate", 'entity' => $context->getEntity()] | |||||
)) { | )) { | ||||
throw new ForbiddenActionException($context); | throw new ForbiddenActionException($context); | ||||
} | } | ||||
$em->flush(); | $em->flush(); | ||||
$url = $this->get(AdminUrlGenerator::class) | $url = $this->get(AdminUrlGenerator::class) | ||||
->setAction(ActionDefinition::EDIT) | |||||
->setEntityId($newEntity->getId()) | |||||
->generateUrl(); | |||||
->setAction(ActionDefinition::EDIT) | |||||
->setEntityId($newEntity->getId()) | |||||
->generateUrl(); | |||||
$this->addFlashTranslator('success', 'duplicated'); | $this->addFlashTranslator('success', 'duplicated'); | ||||
return $this->redirect($url); | return $this->redirect($url); | ||||
} | } | ||||
public function isRepositoryQueryFiltered():bool{ | |||||
if(($this->filtersForm && $this->filtersForm->isSubmitted()) || $this->isRepositoryQueryFiltered){ | |||||
return true; | |||||
}else{ | |||||
return false; | |||||
} | |||||
} | |||||
public function createIndexRepositoryQuery( | public function createIndexRepositoryQuery( | ||||
SearchDto $searchDto, | SearchDto $searchDto, | ||||
EntityDto $entityDto, | EntityDto $entityDto, | ||||
FieldCollection $fields, | FieldCollection $fields, | ||||
FilterCollection $filters | FilterCollection $filters | ||||
): RepositoryQueryInterface | |||||
{ | |||||
$repositoryQuery = $this->get(EntityRepository::class)->createRepositoryQuery($this->getRepositoryQuery(), $searchDto, $entityDto, $fields, $filters); | |||||
): RepositoryQueryInterface { | |||||
$repositoryQuery = $this->get(EntityRepository::class)->createRepositoryQuery( | |||||
$this->getRepositoryQuery(), | |||||
$searchDto, | |||||
$entityDto, | |||||
$fields, | |||||
$filters | |||||
); | |||||
// TODO : déplacer dans EntotyRepository | // TODO : déplacer dans EntotyRepository | ||||
if ($this->isInstanceOf(TreeInterface::class)) { | if ($this->isInstanceOf(TreeInterface::class)) { | ||||
$repositoryQuery->filterIsParent(); | $repositoryQuery->filterIsParent(); | ||||
} | } | ||||
} | } | ||||
if ($this->isInstanceOf(StatusInterface::class)) { | |||||
$repositoryQuery->filterIsOnlineAndOffline(); | |||||
} | |||||
$this->filtersForm = $this->createForm( | $this->filtersForm = $this->createForm( | ||||
FiltersFormType::class, | FiltersFormType::class, | ||||
$this->filtersForm->handleRequest($searchDto->getRequest()); | $this->filtersForm->handleRequest($searchDto->getRequest()); | ||||
$filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto); | |||||
$this->isRepositoryQueryFiltered = $filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto); | |||||
return $repositoryQuery; | return $repositoryQuery; | ||||
} | } | ||||
public function createIndexQueryBuilder( | |||||
public function createSortRepositoryQuery( | |||||
SearchDto $searchDto, | SearchDto $searchDto, | ||||
EntityDto $entityDto, | EntityDto $entityDto, | ||||
FieldCollection $fields, | FieldCollection $fields, | ||||
FilterCollection $filters | FilterCollection $filters | ||||
): QueryBuilder { | |||||
$repositoryQuery = $this->createIndexRepositoryQuery($searchDto, $entityDto, $fields, $filters); | |||||
return $repositoryQuery->getQueryBuilder(); | |||||
): RepositoryQueryInterface { | |||||
return $this->createIndexRepositoryQuery($searchDto,$entityDto, $fields, $filters); | |||||
} | |||||
public function createIndexQueryBuilder( | |||||
SearchDto $searchDto, | |||||
EntityDto $entityDto, | |||||
FieldCollection $fields, | |||||
FilterCollection $filters | |||||
): QueryBuilder { | |||||
$repositoryQuery = $this->createIndexRepositoryQuery($searchDto, $entityDto, $fields, $filters); | |||||
return $repositoryQuery->getQueryBuilder(); | |||||
} | } | ||||
public function createSortQueryBuilder( | public function createSortQueryBuilder( | ||||
SearchDto $searchDto, | |||||
EntityDto $entityDto, | |||||
FieldCollection $fields, | |||||
FilterCollection $filters | |||||
SearchDto $searchDto, | |||||
EntityDto $entityDto, | |||||
FieldCollection $fields, | |||||
FilterCollection $filters | |||||
): QueryBuilder { | ): QueryBuilder { | ||||
$queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters); | |||||
return $queryBuilder; | |||||
$repositoryQuery = $this->createSortRepositoryQuery($searchDto, $entityDto, $fields, $filters); | |||||
return $repositoryQuery->getQueryBuilder(); | |||||
} | } | ||||
public function edit(AdminContext $context) | public function edit(AdminContext $context) | ||||
$context = $this->get(AdminContextProvider::class)->getContext(); | $context = $this->get(AdminContextProvider::class)->getContext(); | ||||
return $context->getCrudControllers()->findCrudFqcnByEntityFqcn( | return $context->getCrudControllers()->findCrudFqcnByEntityFqcn( | ||||
$this->get(EntityManagerInterface::class)->getEntityName($interface) | |||||
$this->get(EntityManagerInterface::class)->getEntityName($interface) | |||||
); | ); | ||||
} | } | ||||
$entityManager->delete($entityInstance); | $entityManager->delete($entityInstance); | ||||
$entityManager->flush(); | $entityManager->flush(); | ||||
$this->get(FlashBagTranslator::class)->add('success', 'deleted', $this->getTranslationEntityName()); | $this->get(FlashBagTranslator::class)->add('success', 'deleted', $this->getTranslationEntityName()); | ||||
} | } | ||||
public function configureActions(Actions $actions): Actions | public function configureActions(Actions $actions): Actions | ||||
public function getDuplicateAction(): Action | public function getDuplicateAction(): Action | ||||
{ | { | ||||
$duplicateAction = Action::new( | $duplicateAction = Action::new( | ||||
ActionDefinition::DUPLICATE, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::DUPLICATE), | |||||
'fa fa-fw fa-copy' | |||||
ActionDefinition::DUPLICATE, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::DUPLICATE), | |||||
'fa fa-fw fa-copy' | |||||
) | ) | ||||
->linkToCrudAction(ActionDefinition::DUPLICATE) | |||||
->setLabel($this->get(TranslatorAdmin::class)->transAction(ActionDefinition::DUPLICATE)) | |||||
->setCssClass('in-dropdown text-info action-confirm'); | |||||
->linkToCrudAction(ActionDefinition::DUPLICATE) | |||||
->setLabel($this->get(TranslatorAdmin::class)->transAction(ActionDefinition::DUPLICATE)) | |||||
->setCssClass('in-dropdown text-info action-confirm'); | |||||
return $duplicateAction; | return $duplicateAction; | ||||
} | } | ||||
$actions->add(Crud::PAGE_INDEX, $this->getDuplicateAction()); | $actions->add(Crud::PAGE_INDEX, $this->getDuplicateAction()); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::NEW, | |||||
[ | |||||
'icon' => 'plus', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('create'), | |||||
'add_class' => 'btn-sm', | |||||
] | |||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::NEW, | |||||
[ | |||||
'icon' => 'plus', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('create'), | |||||
'add_class' => 'btn-sm', | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::EDIT, | |||||
[ | |||||
'class' => 'btn btn-sm btn-primary', | |||||
'icon' => 'edit', | |||||
'label' => false, | |||||
'html_attributes' => array( | |||||
'data-toggle' => 'tooltip', | |||||
'title' => $this->get(TranslatorAdmin::class)->transAction('edit'), | |||||
), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::EDIT, | |||||
[ | |||||
'class' => 'btn btn-sm btn-primary', | |||||
'icon' => 'edit', | |||||
'label' => false, | |||||
'html_attributes' => array( | |||||
'data-toggle' => 'tooltip', | |||||
'title' => $this->get(TranslatorAdmin::class)->transAction('edit'), | |||||
), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::DETAIL, | |||||
[ | |||||
'icon' => 'eye', | |||||
'add_class' => 'btn btn-sm btn-success', | |||||
'label' => false, | |||||
'html_attributes' => array( | |||||
'data-toggle' => 'tooltip', | |||||
'title' => $this->get(TranslatorAdmin::class)->transAction('detail'), | |||||
), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::DETAIL, | |||||
[ | |||||
'icon' => 'eye', | |||||
'add_class' => 'btn btn-sm btn-success', | |||||
'label' => false, | |||||
'html_attributes' => array( | |||||
'data-toggle' => 'tooltip', | |||||
'title' => $this->get(TranslatorAdmin::class)->transAction('detail'), | |||||
), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::DELETE, | |||||
[ | |||||
'icon' => 'trash', | |||||
'dropdown' => true, | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
'class' => 'dropdown-item text-danger in-dropdown action-delete', | |||||
] | |||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::DELETE, | |||||
[ | |||||
'icon' => 'trash', | |||||
'dropdown' => true, | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
'class' => 'dropdown-item text-danger in-dropdown action-delete', | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::BATCH_DELETE, | |||||
[ | |||||
'class' => 'btn btn-sm btn-danger', | |||||
'icon' => 'trash', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::BATCH_DELETE, | |||||
[ | |||||
'class' => 'btn btn-sm btn-danger', | |||||
'icon' => 'trash', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
] | |||||
); | ); | ||||
} | } | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_RETURN, | |||||
[ | |||||
'add_class' => 'float-right ', | |||||
'icon' => 'check', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_RETURN, | |||||
[ | |||||
'add_class' => 'float-right ', | |||||
'icon' => 'check', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::INDEX, | |||||
[ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::INDEX, | |||||
[ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_CONTINUE, | |||||
[ | |||||
'class' => 'btn btn-info float-right action-save-continue', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_continue'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_CONTINUE, | |||||
[ | |||||
'class' => 'btn btn-info float-right action-save-continue', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_continue'), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::DELETE, | |||||
[ | |||||
'icon' => 'trash', | |||||
'class' => 'btn btn-outline-danger action-delete', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::DELETE, | |||||
[ | |||||
'icon' => 'trash', | |||||
'class' => 'btn btn-outline-danger action-delete', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('delete'), | |||||
] | |||||
); | ); | ||||
} | } | ||||
$actions->add(Crud::PAGE_NEW, ActionDefinition::INDEX); | $actions->add(Crud::PAGE_NEW, ActionDefinition::INDEX); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_RETURN, | |||||
[ | |||||
'add_class' => 'float-right', | |||||
'icon' => 'check', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_RETURN, | |||||
[ | |||||
'add_class' => 'float-right', | |||||
'icon' => 'check', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_return'), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::INDEX, | |||||
[ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::INDEX, | |||||
[ | |||||
'icon' => 'chevron-left', | |||||
'class' => 'btn btn-link', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('back_index'), | |||||
] | |||||
); | ); | ||||
$this->actionUpdate( | $this->actionUpdate( | ||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_ADD_ANOTHER, | |||||
[ | |||||
'class' => 'btn btn-info float-right', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_add_another'), | |||||
] | |||||
$actions, | |||||
Crud::PAGE_EDIT, | |||||
ActionDefinition::SAVE_AND_ADD_ANOTHER, | |||||
[ | |||||
'class' => 'btn btn-info float-right', | |||||
'label' => $this->get(TranslatorAdmin::class)->transAction('save_and_add_another'), | |||||
] | |||||
); | ); | ||||
} | } | ||||
{ | { | ||||
if ($this->isInstanceOf(TranslatableInterface::class)) { | if ($this->isInstanceOf(TranslatableInterface::class)) { | ||||
$actions->update( | $actions->update( | ||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::EDIT, | |||||
function (Action $action) { | |||||
$action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig'); | |||||
Crud::PAGE_INDEX, | |||||
ActionDefinition::EDIT, | |||||
function (Action $action) { | |||||
$action->setTemplatePath('@LcSov/adminlte/crud/action/translatable.html.twig'); | |||||
return $action; | |||||
} | |||||
return $action; | |||||
} | |||||
); | ); | ||||
} | } | ||||
} | } | ||||
public function handleSortableEntityActions(Actions $actions): void | public function handleSortableEntityActions(Actions $actions): void | ||||
{ | { | ||||
if ($this->isInstanceOf(SortableInterface::class)) { | if ($this->isInstanceOf(SortableInterface::class)) { | ||||
$sortAction = Action::new(ActionDefinition::SORT, $this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SORT), 'fa fa-sort') | |||||
->linkToCrudAction(ActionDefinition::SORT) | |||||
->setCssClass('btn btn-sm btn-success') | |||||
->createAsGlobalAction(); | |||||
$sortAction = Action::new( | |||||
ActionDefinition::SORT, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SORT), | |||||
'fa fa-sort' | |||||
) | |||||
->linkToCrudAction(ActionDefinition::SORT) | |||||
->setCssClass('btn btn-sm btn-success') | |||||
->createAsGlobalAction(); | |||||
$actions->add(Crud::PAGE_INDEX, $sortAction); | $actions->add(Crud::PAGE_INDEX, $sortAction); | ||||
} | } | ||||
} | } | ||||
public function handleTreeEntityActions(Actions $actions): void | public function handleTreeEntityActions(Actions $actions): void | ||||
{ | { | ||||
if ($this->isInstanceOf(TreeInterface::class)) { | if ($this->isInstanceOf(TreeInterface::class)) { | ||||
$indexChildAction = Action::new( | $indexChildAction = Action::new( | ||||
ActionDefinition::INDEX_CHILDREN, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::INDEX_CHILDREN), | |||||
'fa fa-list' | |||||
ActionDefinition::INDEX_CHILDREN, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::INDEX_CHILDREN), | |||||
'fa fa-list' | |||||
) | ) | ||||
->linkToCrudAction(ActionDefinition::INDEX) | |||||
->setLabel('') | |||||
->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants')) | |||||
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig') | |||||
->setCssClass('btn btn-sm btn-success'); | |||||
->linkToCrudAction(ActionDefinition::INDEX) | |||||
->setLabel('') | |||||
->setHtmlAttributes(array('data-toggle' => 'tooltip', 'title' => 'Afficher les enfants')) | |||||
->setTemplatePath('@LcSov/adminlte/crud/action/index_children.html.twig') | |||||
->setCssClass('btn btn-sm btn-success'); | |||||
$backParentAction = Action::new( | $backParentAction = Action::new( | ||||
ActionDefinition::INDEX_PARENT, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::INDEX_PARENT), | |||||
'fa fa-chevron-left' | |||||
ActionDefinition::INDEX_PARENT, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::INDEX_PARENT), | |||||
'fa fa-chevron-left' | |||||
) | ) | ||||
->linkToCrudAction(ActionDefinition::INDEX) | |||||
->setCssClass('btn btn-sm btn-info') | |||||
->createAsGlobalAction(); | |||||
->linkToCrudAction(ActionDefinition::INDEX) | |||||
->setCssClass('btn btn-sm btn-info') | |||||
->createAsGlobalAction(); | |||||
$actions->add(Crud::PAGE_INDEX, $backParentAction); | $actions->add(Crud::PAGE_INDEX, $backParentAction); | ||||
$actions->add(Crud::PAGE_INDEX, $indexChildAction); | $actions->add(Crud::PAGE_INDEX, $indexChildAction); | ||||
{ | { | ||||
if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) { | if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) { | ||||
$actions->update( | $actions->update( | ||||
$crudActionName, | |||||
$actionName, | |||||
function (Action $action) use ($button) { | |||||
if (isset($button['add_class'])) { | |||||
$action->addCssClass($button['add_class']); | |||||
} | |||||
if (isset($button['class'])) { | |||||
$action->setCssClass($button['class']); | |||||
} | |||||
$crudActionName, | |||||
$actionName, | |||||
function (Action $action) use ($button) { | |||||
if (isset($button['add_class'])) { | |||||
$action->addCssClass($button['add_class']); | |||||
} | |||||
if (isset($button['icon'])) { | |||||
$action->setIcon('fa fa-' . $button['icon']); | |||||
} | |||||
if (isset($button['class'])) { | |||||
$action->setCssClass($button['class']); | |||||
} | |||||
if (isset($button['label'])) { | |||||
$action->setLabel($button['label']); | |||||
} | |||||
if (isset($button['icon'])) { | |||||
$action->setIcon('fa fa-' . $button['icon']); | |||||
} | |||||
if (isset($button['dropdown']) && $button['dropdown']) { | |||||
$action->addCssClass('in-dropdown'); | |||||
} | |||||
if (isset($button['label'])) { | |||||
$action->setLabel($button['label']); | |||||
} | |||||
if (isset($button['html_attributes']) && $button['html_attributes']) { | |||||
$action->setHtmlAttributes($button['html_attributes']); | |||||
} | |||||
if (isset($button['dropdown']) && $button['dropdown']) { | |||||
$action->addCssClass('in-dropdown'); | |||||
} | |||||
return $action; | |||||
if (isset($button['html_attributes']) && $button['html_attributes']) { | |||||
$action->setHtmlAttributes($button['html_attributes']); | |||||
} | } | ||||
return $action; | |||||
} | |||||
); | ); | ||||
} | } | ||||
} | } | ||||
public function autocompleteFilter(AdminContext $context): JsonResponse | public function autocompleteFilter(AdminContext $context): JsonResponse | ||||
{ | { | ||||
$queryBuilder = $this->createIndexQueryBuilder( | $queryBuilder = $this->createIndexQueryBuilder( | ||||
$context->getSearch(), | |||||
$context->getEntity(), | |||||
FieldCollection::new([]), | |||||
FilterCollection::new() | |||||
$context->getSearch(), | |||||
$context->getEntity(), | |||||
FieldCollection::new([]), | |||||
FilterCollection::new() | |||||
); | ); | ||||
$autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT); | $autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT); | ||||
/** @var CrudControllerInterface $controller */ | /** @var CrudControllerInterface $controller */ | ||||
$controller = $this->get(ControllerFactory::class)->getCrudControllerInstance( | $controller = $this->get(ControllerFactory::class)->getCrudControllerInstance( | ||||
$autocompleteContext[EA::CRUD_CONTROLLER_FQCN], | |||||
ActionDefinition::INDEX, | |||||
$context->getRequest() | |||||
$autocompleteContext[EA::CRUD_CONTROLLER_FQCN], | |||||
ActionDefinition::INDEX, | |||||
$context->getRequest() | |||||
); | ); | ||||
/** @var FieldDto $field */ | /** @var FieldDto $field */ | ||||
$field = FieldCollection::new( | $field = FieldCollection::new( | ||||
$controller->configureFields($autocompleteContext['originatingPage']) | |||||
$controller->configureFields($autocompleteContext['originatingPage']) | |||||
)->getByProperty($autocompleteContext['propertyName']); | )->getByProperty($autocompleteContext['propertyName']); | ||||
$filterManager = $this->get(FilterManager::class); | $filterManager = $this->get(FilterManager::class); | ||||
{ | { | ||||
if ($dataInOption) { | if ($dataInOption) { | ||||
$data = $entity; | $data = $entity; | ||||
}else{ | |||||
} else { | |||||
$data = null; | $data = null; | ||||
} | } | ||||
$options['action'] = $this->get(AdminUrlGenerator::class) | $options['action'] = $this->get(AdminUrlGenerator::class) | ||||
->setAction($action) | |||||
->setController($controller) | |||||
->setEntityId($entity->getId()) | |||||
->generateUrl(); | |||||
->setAction($action) | |||||
->setController($controller) | |||||
->setEntityId($entity->getId()) | |||||
->generateUrl(); | |||||
return $this->createForm($class, $data, $options); | return $this->createForm($class, $data, $options); | ||||
} | } |
use Lc\CaracoleBundle\Resolver\MerchantResolver; | use Lc\CaracoleBundle\Resolver\MerchantResolver; | ||||
use Lc\CaracoleBundle\Resolver\SectionResolver; | use Lc\CaracoleBundle\Resolver\SectionResolver; | ||||
use Lc\SovBundle\Container\Reminder\ReminderContainer; | use Lc\SovBundle\Container\Reminder\ReminderContainer; | ||||
use Lc\SovBundle\Controller\ControllerTrait; | |||||
use Lc\SovBundle\Factory\Reminder\ReminderFactory; | use Lc\SovBundle\Factory\Reminder\ReminderFactory; | ||||
use Lc\SovBundle\Form\Reminder\ReminderAdminFormType; | use Lc\SovBundle\Form\Reminder\ReminderAdminFormType; | ||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
class ReminderAdminController extends AbstractController | class ReminderAdminController extends AbstractController | ||||
{ | { | ||||
use ControllerTrait; | |||||
protected EntityManagerInterface $entityManager; | protected EntityManagerInterface $entityManager; | ||||
protected ReminderContainer $reminderContainer; | protected ReminderContainer $reminderContainer; |
namespace Lc\SovBundle\Controller\Ticket; | namespace Lc\SovBundle\Controller\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | ||||
use Lc\SovBundle\Container\Ticket\TicketContainer; | |||||
use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | use Lc\SovBundle\Container\Ticket\TicketMessageContainer; | ||||
use Lc\SovBundle\Definition\ActionDefinition; | use Lc\SovBundle\Definition\ActionDefinition; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | |||||
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface; | |||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory; | |||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface; | |||||
use Lc\SovBundle\Form\Ticket\TicketFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageFormType; | |||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageAdminFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketStatusType; | use Lc\SovBundle\Form\Ticket\TicketStatusType; | ||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Lc\SovBundle\Controller\AbstractAdminController; | use Lc\SovBundle\Controller\AbstractAdminController; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | use Lc\SovBundle\Repository\RepositoryQueryInterface; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
use Symfony\Component\HttpFoundation\JsonResponse; | use Symfony\Component\HttpFoundation\JsonResponse; | ||||
use Symfony\Component\HttpFoundation\RequestStack; | use Symfony\Component\HttpFoundation\RequestStack; | ||||
abstract class TicketAdminController extends AbstractAdminController | abstract class TicketAdminController extends AbstractAdminController | ||||
{ | { | ||||
public function getRepositoryQuery() :RepositoryQueryInterface | |||||
public function getRepositoryQuery(): RepositoryQueryInterface | |||||
{ | { | ||||
return $this->getTicketContainer()->getRepositoryQuery(); | return $this->getTicketContainer()->getRepositoryQuery(); | ||||
} | } | ||||
public function createEntity(string $entityFqcn) | public function createEntity(string $entityFqcn) | ||||
{ | { | ||||
return $this->getTicketContainer()->getFactory()->create(); | |||||
$ticket = $this->getTicketContainer()->getFactory()->create(); | |||||
return $ticket; | |||||
} | } | ||||
public function configureAssets(Assets $assets): Assets | |||||
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void | |||||
{ | { | ||||
$assets = parent::configureAssets($assets); | |||||
$assets->addWebpackEncoreEntry('sov-ticket'); | |||||
parent::persistEntity($entityManager, $entityInstance); | |||||
$this->getEventDispatcher()->dispatch(new TicketEvent($entityInstance), TicketEvent::NEW_TICKET_EVENT); | |||||
} | |||||
return $assets; | |||||
public function configureCrud(Crud $crud): Crud | |||||
{ | |||||
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub | |||||
$crud->setDefaultSort(array('updatedAt' => 'DESC')); | |||||
return $crud; | |||||
} | } | ||||
public function configureFields(string $pageName): iterable | public function configureFields(string $pageName): iterable | ||||
{ | { | ||||
$translatorAdmin = $this->get(TranslatorAdmin::class); | |||||
return [ | |||||
IntegerField::new('id') | |||||
->hideOnForm(), | |||||
DateField::new('createdAt')->setFormat('short') | |||||
->hideOnForm(), | |||||
TextField::new('visitorFirstname') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | |||||
->hideOnForm(), | |||||
TextField::new('visitorLastname') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | |||||
->hideOnForm(), | |||||
TextField::new('visitorEmail') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | |||||
->hideOnForm(), | |||||
AssociationField::new('user') | |||||
->hideOnIndex(), | |||||
TextField::new('subject'), | |||||
TextField::new('lastMessage') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig') | |||||
->hideOnForm(), | |||||
ChoiceField::new('type') | |||||
->autocomplete() | |||||
->setChoices( | |||||
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getTypeChoices(), 'Ticket', 'type') | |||||
), | |||||
ChoiceField::new('status') | |||||
->autocomplete() | |||||
->setChoices( | |||||
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getStatusChoices(), 'Ticket', 'status') | |||||
) | |||||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig') | |||||
->hideOnForm(), | |||||
]; | |||||
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | |||||
} | } | ||||
public function configureActions(Actions $actions): Actions | |||||
public function configureAssets(Assets $assets): Assets | |||||
{ | { | ||||
$actions | |||||
->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL) | |||||
->remove(Crud::PAGE_INDEX, ActionDefinition::EDIT); | |||||
$assets = parent::configureAssets($assets); | |||||
$assets->addWebpackEncoreEntry('sov-ticket'); | |||||
return parent::configureActions($actions); | |||||
return $assets; | |||||
} | } | ||||
public function new(AdminContext $context) | |||||
public function configureActions(Actions $actions): Actions | |||||
{ | { | ||||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | |||||
$actions->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL); | |||||
$actions = parent::configureActions($actions); | |||||
$actions->disable( ActionDefinition::EDIT, ActionDefinition::DUPLICATE); | |||||
return $actions; | |||||
$ticket = $this->createEntity($context->getEntity()->getFqcn()); | |||||
} | |||||
$form = $this->createForm(TicketFormType::class, $ticket); | |||||
public function createIndexRepositoryQuery( | |||||
SearchDto $searchDto, | |||||
EntityDto $entityDto, | |||||
FieldCollection $fields, | |||||
FilterCollection $filters | |||||
): RepositoryQueryInterface { | |||||
$repositoryQuery = parent::createIndexRepositoryQuery( | |||||
$searchDto, | |||||
$entityDto, | |||||
$fields, | |||||
$filters | |||||
); | |||||
$form->handleRequest($context->getRequest()); | |||||
if ($form->isSubmitted() && $form->isValid()) { | |||||
$ticket = $form->getData(); | |||||
if(!$this->isRepositoryQueryFiltered()){ | |||||
$this->get(EntityManagerInterface::class)->create($ticket); | |||||
$this->get(EntityManagerInterface::class)->flush(); | |||||
$repositoryQuery->filterByStatus(array( | |||||
TicketModel::TICKET_STATUS_OPEN, | |||||
TicketModel::TICKET_STATUS_BEING_PROCESSED, | |||||
TicketModel::TICKET_STATUS_PROCESSED | |||||
)); | |||||
} | |||||
$url = $adminUrlGenerator | |||||
->setAction('index') | |||||
->generateUrl(); | |||||
return $repositoryQuery; | |||||
} | |||||
return $this->redirect($url); | |||||
} | |||||
return $this->render( | |||||
'@LcSov/admin/ticket/new.html.twig', | |||||
[ | |||||
'form' => $form->createView(), | |||||
] | |||||
); | |||||
} | |||||
public function detail(AdminContext $context) | public function detail(AdminContext $context) | ||||
{ | { | ||||
$ticket = $context->getEntity()->getInstance(); | $ticket = $context->getEntity()->getInstance(); | ||||
$url = $adminUrlGenerator | $url = $adminUrlGenerator | ||||
->setAction('ticketStatusAction') | |||||
->generateUrl(); | |||||
->setAction('ticketStatusAction') | |||||
->generateUrl(); | |||||
$formTicketStatus = $this->createForm( | $formTicketStatus = $this->createForm( | ||||
TicketStatusType::class, | |||||
$ticket, | |||||
[ | |||||
'action' => $url, | |||||
'method' => 'POST', | |||||
] | |||||
TicketStatusType::class, | |||||
$ticket, | |||||
[ | |||||
'action' => $url, | |||||
'method' => 'POST', | |||||
] | |||||
); | ); | ||||
$ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); | $ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); | ||||
$formAddTicketMessage = $this->createForm(TicketMessageFormType::class, $ticketMessage); | |||||
$formAddTicketMessage = $this->createForm(TicketMessageAdminFormType::class, $ticketMessage); | |||||
$formAddTicketMessage->handleRequest($this->get(RequestStack::class)->getMainRequest()); | $formAddTicketMessage->handleRequest($this->get(RequestStack::class)->getMainRequest()); | ||||
if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) { | if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) { | ||||
$ticketMessage->setAnswerByAdmin(true); | $ticketMessage->setAnswerByAdmin(true); | ||||
$this->get(EntityManagerInterface::class)->create($ticketMessage); | $this->get(EntityManagerInterface::class)->create($ticketMessage); | ||||
$this->get(EntityManagerInterface::class)->flush(); | $this->get(EntityManagerInterface::class)->flush(); | ||||
$this->getEventDispatcher()->dispatch(new TicketEvent($ticket), TicketEvent::NEW_MESSAGE_EVENT); | |||||
return $this->redirect($this->generateEaUrl()); | |||||
} | } | ||||
return $this->render( | return $this->render( | ||||
'@LcSov/admin/ticket/detail.html.twig', | |||||
[ | |||||
'form_ticket_status' => $formTicketStatus->createView(), | |||||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||||
'ticket' => $ticket, | |||||
] | |||||
'@LcSov/admin/ticket/detail.html.twig', | |||||
[ | |||||
'form_ticket_status' => $formTicketStatus->createView(), | |||||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||||
'ticket' => $ticket, | |||||
] | |||||
); | ); | ||||
} | } | ||||
public function ticketStatusAction() | |||||
public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager) | |||||
{ | { | ||||
$request = $this->get('request')->getMasterRequest(); | |||||
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance(); | |||||
$ticket = $context->getEntity()->getInstance(); | |||||
$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); | $formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); | ||||
$formTicketStatusForm->handleRequest($request); | |||||
$formTicketStatusForm->handleRequest($context->getRequest()); | |||||
$success = false; | $success = false; | ||||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | ||||
$this->get('em')->persist($ticket); | |||||
$this->get('em')->flush(); | |||||
$entityManager->update($ticket); | |||||
$entityManager->flush(); | |||||
$success = true; | $success = true; | ||||
} | } | ||||
namespace Lc\SovBundle\Controller\User; | namespace Lc\SovBundle\Controller\User; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; | use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use Lc\SovBundle\Container\User\UserContainer; | use Lc\SovBundle\Container\User\UserContainer; | ||||
use Lc\SovBundle\Controller\AbstractAdminController; | use Lc\SovBundle\Controller\AbstractAdminController; | ||||
use Lc\SovBundle\Definition\ActionDefinition; | |||||
use Lc\SovBundle\Definition\RolesDefinition; | use Lc\SovBundle\Definition\RolesDefinition; | ||||
use Lc\SovBundle\Definition\RolesDefinitionInterface; | use Lc\SovBundle\Definition\RolesDefinitionInterface; | ||||
use Lc\SovBundle\Doctrine\EntityManager; | use Lc\SovBundle\Doctrine\EntityManager; | ||||
{ | { | ||||
protected RolesDefinitionInterface $rolesDefinition; | protected RolesDefinitionInterface $rolesDefinition; | ||||
public function __construct( | |||||
SessionInterface $session, | |||||
RequestStack $request, | |||||
EntityManager $em, | |||||
TranslatorAdmin $translatorAdmin, | |||||
RolesDefinitionInterface $rolesDefinition | |||||
) { | |||||
$this->rolesDefinition = $rolesDefinition; | |||||
public function buildIndexActions(Actions $actions): void | |||||
{ | |||||
parent::buildIndexActions($actions); // TODO: Change the autogenerated stub | |||||
$actions->add(Crud::PAGE_INDEX, $this->getSwitchUserAction()); | |||||
} | |||||
public function getSwitchUserAction(): Action | |||||
{ | |||||
$switchAction = Action::new( | |||||
ActionDefinition::SWITCH_USER, | |||||
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SWITCH_USER), | |||||
'fa fa-fw fa-user-secret' | |||||
) | |||||
->linkToCrudAction(ActionDefinition::SWITCH_USER) | |||||
->setLabel($this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SWITCH_USER)) | |||||
->setCssClass('in-dropdown text-info action-confirm action_switch'); | |||||
return $switchAction; | |||||
} | |||||
public function overrideEntitiesActions(?EntityCollection $entities): void | |||||
{ | |||||
parent::overrideEntitiesActions($entities); // TODO: Change the autogenerated stub | |||||
foreach ($entities as $entity) { | |||||
foreach ($entity->getActions() as $action){ | |||||
if($action->getName() == ActionDefinition::SWITCH_USER){ | |||||
$url = $this->generateUrl($this->getParameter('lc_sov.homepage_route'), array('_switch_user' => $entity->getInstance()->getEmail())); | |||||
$action->setLinkUrl($url); | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
public function configureFields(string $pageName): iterable | public function configureFields(string $pageName): iterable |
public const SAVE_AND_ADD_ANOTHER = 'saveAndAddAnother'; | public const SAVE_AND_ADD_ANOTHER = 'saveAndAddAnother'; | ||||
public const SAVE_AND_CONTINUE = 'saveAndContinue'; | public const SAVE_AND_CONTINUE = 'saveAndContinue'; | ||||
public const SAVE_AND_RETURN = 'saveAndReturn'; | public const SAVE_AND_RETURN = 'saveAndReturn'; | ||||
public const SWITCH_USER = 'switchUser'; | |||||
public const WRITE_TO_USER = 'writeToUser'; | |||||
} | } |
namespace Lc\SovBundle\Definition\Field; | namespace Lc\SovBundle\Definition\Field; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField; | use EasyCorp\Bundle\EasyAdminBundle\Field\FormField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; | ||||
->hideOnIndex(), | ->hideOnIndex(), | ||||
'devAlias' => TextField::new('devAlias')->hideOnIndex(), | 'devAlias' => TextField::new('devAlias')->hideOnIndex(), | ||||
'status' => StatusField::new('status')->setSortable(true), | 'status' => StatusField::new('status')->setSortable(true), | ||||
'createdAt' => DateTimeField::new('createdAt')->setSortable(true), | |||||
'updatedAt' => DateTimeField::new('updatedAt')->setSortable(true), | |||||
]; | ]; | ||||
} | } | ||||
throw new \Exception($method . ' n\'existe pas '); | throw new \Exception($method . ' n\'existe pas '); | ||||
} | } | ||||
$fieldPanel = FormField::addPanel($panel); | |||||
$method = 'panel'.ucfirst($panel).'CustomOptions'; | |||||
if(method_exists($this, $method)) { | |||||
foreach ($this->$method() as $customOptionKey => $customOptionValue){ | |||||
$fieldPanel->setCustomOption($customOptionKey, $customOptionValue); | |||||
} | |||||
} | |||||
return array_merge( | return array_merge( | ||||
['panel_' . $panel => FormField::addPanel($panel)], | |||||
[ | |||||
'panel_' . $panel => $fieldPanel | |||||
], | |||||
$this->buildFieldArray($panelFieldArray) | $this->buildFieldArray($panelFieldArray) | ||||
); | ); | ||||
} | } | ||||
} | |||||
} |
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField; | use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | ||||
use Lc\SovBundle\Field\BooleanField; | use Lc\SovBundle\Field\BooleanField; | ||||
use Lc\SovBundle\Field\CKEditorField; | |||||
use Lc\SovBundle\Field\ImageManagerField; | use Lc\SovBundle\Field\ImageManagerField; | ||||
class NewsFieldDefinition extends AbstractFieldDefinition | class NewsFieldDefinition extends AbstractFieldDefinition | ||||
'newsletter' => AssociationField::new('newsletter')->setSortable(true), | 'newsletter' => AssociationField::new('newsletter')->setSortable(true), | ||||
'image' => ImageManagerField::new('image'), | 'image' => ImageManagerField::new('image'), | ||||
'position' => NumberField::new('position'), | 'position' => NumberField::new('position'), | ||||
'description' => TextEditorField::new('description'), | |||||
'description' => CKEditorField::new('description'), | |||||
'isSent' => BooleanField::new('isSent')->setSortable(true), | 'isSent' => BooleanField::new('isSent')->setSortable(true), | ||||
]; | ]; | ||||
} | } |
<?php | |||||
namespace Lc\SovBundle\Definition\Field\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketEmailFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketFirstnameFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\TicketLastnameFilter; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageAdminFormType; | |||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | |||||
use Lc\SovBundle\Field\CollectionField; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageType; | |||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
class TicketFieldDefinition extends AbstractFieldDefinition | |||||
{ | |||||
public function __construct(TranslatorAdmin $translatorAdmin) | |||||
{ | |||||
parent::__construct($translatorAdmin); | |||||
} | |||||
public function configureIndex(): array | |||||
{ | |||||
return [ | |||||
'id', | |||||
'createdAt', | |||||
'visitorFirstname', | |||||
'visitorLastname', | |||||
'visitorEmail', | |||||
'subject', | |||||
'updatedAt', | |||||
'type', | |||||
'status' | |||||
]; | |||||
} | |||||
public function configureForm(): array | |||||
{ | |||||
return [ | |||||
'user', | |||||
'type', | |||||
'subject', | |||||
'ticketMessages' | |||||
]; | |||||
} | |||||
public function configurePanels(): array | |||||
{ | |||||
return []; | |||||
} | |||||
public function configureFields(): array | |||||
{ | |||||
return [ | |||||
'id' => IdField::new('id') | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'createdAt' => DateTimeField::new('createdAt') | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'visitorFirstname' => TextField::new('visitorFirstname') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | |||||
->setCustomOption('filter_fqcn', TicketFirstnameFilter::class) | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'visitorLastname' => TextField::new('visitorLastname') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | |||||
->setCustomOption('filter_fqcn', TicketLastnameFilter::class) | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'visitorEmail' => TextField::new('visitorEmail') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | |||||
->setCustomOption('filter_fqcn', TicketEmailFilter::class) | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'user' => AssociationField::new('user') | |||||
->hideOnIndex(), | |||||
'subject' => TextField::new('subject') | |||||
->setSortable(true), | |||||
'updatedAt' => DateTimeField::new('updatedAt') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig') | |||||
->setSortable(true) | |||||
->hideOnForm(), | |||||
'type' => ChoiceField::new('type') | |||||
->autocomplete() | |||||
->setSortable(true) | |||||
->setChoices( | |||||
$this->translatorAdmin->transChoices( | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | |||||
'type' | |||||
) | |||||
), | |||||
'status' => ChoiceField::new('status') | |||||
->autocomplete() | |||||
->setSortable(true) | |||||
->setChoices( | |||||
$this->translatorAdmin->transChoices( | |||||
TicketSolver::getStatusChoices(), | |||||
'Ticket', | |||||
'status' | |||||
) | |||||
) | |||||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig'), | |||||
'ticketMessages' => CollectionField::new('ticketMessages') | |||||
->setFormTypeOption('entry_type', TicketMessageAdminFormType::class) | |||||
->setFormTypeOption('allow_add', false) | |||||
->setFormTypeOption('allow_delete', false) | |||||
]; | |||||
} | |||||
} |
use Lc\CaracoleBundle\Field\AssociationField; | use Lc\CaracoleBundle\Field\AssociationField; | ||||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | ||||
use Lc\SovBundle\Definition\RolesDefinition; | use Lc\SovBundle\Definition\RolesDefinition; | ||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Lc\SovBundle\Solver\User\UserSolver; | use Lc\SovBundle\Solver\User\UserSolver; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | use Lc\SovBundle\Translation\TranslatorAdmin; | ||||
'email', | 'email', | ||||
'phone', | 'phone', | ||||
'birthdate', | 'birthdate', | ||||
'groupUsers' | |||||
'groupUsers', | |||||
'ticketTypesNotification' | |||||
]; | ]; | ||||
} | } | ||||
'firstname' => TextField::new('firstname')->setSortable(true), | 'firstname' => TextField::new('firstname')->setSortable(true), | ||||
'email' => TextField::new('email')->setSortable(true), | 'email' => TextField::new('email')->setSortable(true), | ||||
'phone' => TextField::new('phone')->setSortable(true), | 'phone' => TextField::new('phone')->setSortable(true), | ||||
'birthdate' => DateField::new('birthdate')->setSortable(true), | |||||
'birthdate' => DateField::new('birthdate') | |||||
->setFormTypeOption('required', false) | |||||
->setSortable(true), | |||||
'groupUsers' => AssociationField::new('groupUsers')->setSortable(true), | 'groupUsers' => AssociationField::new('groupUsers')->setSortable(true), | ||||
'ticketTypesNotification' => ChoiceField::new('ticketTypesNotification') | |||||
->setSortable(true) | |||||
->setFormTypeOption('expanded', false) | |||||
->setFormTypeOption('multiple', true) | |||||
->setChoices($this->translatorAdmin->transChoices( | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | |||||
'type' | |||||
)), | |||||
'roles' => ChoiceField::new('roles') | 'roles' => ChoiceField::new('roles') | ||||
->allowMultipleChoices() | ->allowMultipleChoices() | ||||
->autocomplete() | ->autocomplete() |
'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, | 'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, | ||||
] | ] | ||||
); | ); | ||||
$this->addSettingText( | |||||
[ | |||||
'category' => self::CATEGORY_EMAIL, | |||||
'name' => self::SETTING_EMAIL_FROM, | |||||
] | |||||
); | |||||
$this->addSettingText( | |||||
[ | |||||
'category' => self::CATEGORY_EMAIL, | |||||
'name' => self::SETTING_EMAIL_FROM_NAME, | |||||
] | |||||
); | |||||
} | } | ||||
public function getCategories() | public function getCategories() | ||||
{ | { | ||||
return [ | return [ | ||||
self::CATEGORY_GENERAL, | self::CATEGORY_GENERAL, | ||||
self::CATEGORY_EMAIL | |||||
]; | ]; | ||||
} | } | ||||
<?php | |||||
namespace Lc\SovBundle\Event\Ticket; | |||||
use Lc\SovBundle\Doctrine\EntityInterface; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Symfony\Contracts\EventDispatcher\Event; | |||||
/** | |||||
* class EntityEvent. | |||||
* | |||||
* @author Simon Vieille <simon@deblan.fr> | |||||
*/ | |||||
class TicketEvent extends Event | |||||
{ | |||||
const NEW_TICKET_EVENT = 'ticket_event.new_ticket'; | |||||
const NEW_MESSAGE_EVENT = 'ticket_event.new_message'; | |||||
protected TicketInterface $ticket; | |||||
public function __construct(TicketInterface $ticket) | |||||
{ | |||||
$this->ticket = $ticket; | |||||
} | |||||
public function getTicket(): TicketInterface | |||||
{ | |||||
return $this->ticket; | |||||
} | |||||
} |
{ | { | ||||
return $this->siteStore->getOneByDevAlias('default'); | return $this->siteStore->getOneByDevAlias('default'); | ||||
} | } | ||||
} | } |
<?php | |||||
namespace Lc\SovBundle\EventSubscriber\Ticket; | |||||
use Lc\SovBundle\Event\EntityManager\EntityManagerEvent; | |||||
use Lc\SovBundle\Event\Ticket\TicketEvent; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||||
use Lc\SovBundle\Notification\MailMailjetNotification; | |||||
use Lc\SovBundle\Repository\User\UserStore; | |||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | |||||
class SendNotificationTicketEventSubscriber implements EventSubscriberInterface | |||||
{ | |||||
protected MailMailjetNotification $mailMailjetNotification; | |||||
protected UserStore $userStore; | |||||
protected AuthorizationCheckerInterface $authorizationChecker; | |||||
protected TicketSolver $ticketSolver; | |||||
public function __construct( | |||||
MailMailjetNotification $mailMailjetNotification, | |||||
UserStore $userStore, | |||||
AuthorizationCheckerInterface $authorizationChecker, | |||||
TicketSolver $ticketSolver | |||||
) { | |||||
$this->mailMailjetNotification = $mailMailjetNotification; | |||||
$this->userStore = $userStore; | |||||
$this->authorizationChecker = $authorizationChecker; | |||||
$this->ticketSolver = $ticketSolver; | |||||
} | |||||
public static function getSubscribedEvents() | |||||
{ | |||||
return [ | |||||
TicketEvent::NEW_MESSAGE_EVENT => ['sendNotificationAfterNewMessage'], | |||||
TicketEvent::NEW_TICKET_EVENT => ['sendNotificationAfterNewTicket'], | |||||
]; | |||||
} | |||||
public function sendNotificationAfterNewTicket(TicketEvent $ticketEvent) | |||||
{ | |||||
$ticket = $ticketEvent->getTicket(); | |||||
$lastMessage = $this->ticketSolver->getLastMessage($ticket); | |||||
if ($ticket->getUser()) { | |||||
$firstname = $ticket->getUser()->getFirstname(); | |||||
$email = $ticket->getUser()->getEmail(); | |||||
} else { | |||||
$firstname = $ticket->getVisitorFirstname(); | |||||
$email = $ticket->getVisitorEmail(); | |||||
} | |||||
if ($lastMessage->getAnswerByAdmin()) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Vous avez reçu un nouveau message', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new-by-admin', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} else { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouvelle demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-new', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
$this->notifyUser($ticket); | |||||
} | |||||
public function sendNotificationAfterNewMessage(TicketEvent $ticketEvent) | |||||
{ | |||||
$ticket = $ticketEvent->getTicket(); | |||||
$lastMessage = $this->ticketSolver->getLastMessage($ticket); | |||||
if ($ticket->getUser()) { | |||||
$firstname = $ticket->getUser()->getFirstname(); | |||||
$email = $ticket->getUser()->getEmail(); | |||||
} else { | |||||
$firstname = $ticket->getVisitorFirstname(); | |||||
$email = $ticket->getVisitorEmail(); | |||||
} | |||||
if ($lastMessage->getAnswerByAdmin()) { | |||||
// envoi email au client | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Réponse à votre demande', | |||||
MailMailjetNotification::TO_EMAIL => $email, | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-response', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $firstname, | |||||
'ticket' => $ticket, | |||||
], | |||||
] | |||||
); | |||||
} | |||||
$this->notifyUser($ticket); | |||||
} | |||||
protected function notifyUser(TicketInterface $ticket): void | |||||
{ | |||||
// notifyAdmin | |||||
$usersToNotify = $this->userStore->getByTicketTypesNotification($ticket->getType()); | |||||
foreach ($usersToNotify as $userToNotify) { | |||||
if ($this->authorizationChecker->isGranted('ROLE_ADMIN', $userToNotify)) { | |||||
$this->mailMailjetNotification->send( | |||||
[ | |||||
MailMailjetNotification::SUBJECT => 'Nouveau ticket sur Place du Local', | |||||
MailMailjetNotification::TO_EMAIL => $userToNotify->getEmail(), | |||||
MailMailjetNotification::CONTENT_TEMPLATE => 'mail/ticket-notification', | |||||
MailMailjetNotification::CONTENT_DATA => [ | |||||
'firstname' => $userToNotify->getFirstname(), | |||||
'ticket' => $ticket, | |||||
'ticketMessage' => $ticket->getTicketMessages()[0], | |||||
], | |||||
] | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
{ | { | ||||
$news = new News(); | $news = new News(); | ||||
$news->setStatus(1); | |||||
return $news; | return $news; | ||||
} | } | ||||
{ | { | ||||
$page = new Page(); | $page = new Page(); | ||||
$page->setStatus(1); | |||||
return $page; | return $page; | ||||
} | } | ||||
} | } |
{ | { | ||||
$groupUser = new GroupUser(); | $groupUser = new GroupUser(); | ||||
$groupUser->setStatus(1); | |||||
return $groupUser; | return $groupUser; | ||||
} | } | ||||
} | } |
return (new self()) | return (new self()) | ||||
->setProperty($propertyName) | ->setProperty($propertyName) | ||||
->setLabel($label) | ->setLabel($label) | ||||
->setTemplatePath('@LcSov/adminlte/crud/field/boolean.html.twig') | |||||
->setTemplatePath('@LcSov/adminlte/crud/field/toggle.html.twig') | |||||
->setFormType(CheckboxType::class); | ->setFormType(CheckboxType::class); | ||||
} | } | ||||
{ | { | ||||
$fieldProperty = $this->getFieldProperty($fieldDto); | $fieldProperty = $this->getFieldProperty($fieldDto); | ||||
if ($filteredValue !== null) { | if ($filteredValue !== null) { | ||||
// if ($this->isRelationField($fieldProperty)) { | |||||
// $aliasRelation = $this->getFieldPropertyRelationAlias($fieldProperty); | |||||
// if (array_search($aliasRelation, $repositoryQuery->getAllAliases()) === false) { | |||||
// $repositoryQuery->innerJoin('entity.'.$aliasRelation, $aliasRelation); | |||||
// } | |||||
// $repositoryQuery->andWhere( | |||||
// $fieldProperty.' LIKE :'.$this->getFieldPropertySnake($fieldProperty).'' | |||||
// ); | |||||
// $repositoryQuery->setParameter( | |||||
// $this->getFieldPropertySnake($fieldProperty), | |||||
// '%'.$filteredValue.'%' | |||||
// ); | |||||
// } else { | |||||
$repositoryQuery->andWhere( | $repositoryQuery->andWhere( | ||||
'.'.$fieldProperty.' LIKE :'.$fieldProperty.'' | '.'.$fieldProperty.' LIKE :'.$fieldProperty.'' | ||||
); | ); | ||||
$repositoryQuery->setParameter($fieldProperty, '%'.$filteredValue.'%'); | |||||
$repositoryQuery->setParameter($fieldProperty, $filteredValue); | |||||
} | } | ||||
} | } |
class FilterManager | class FilterManager | ||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected bool $isFiltered = false; | |||||
use FilterTrait; | use FilterTrait; | ||||
} | } | ||||
public function handleFiltersForm(RepositoryQueryInterface $repositoryQuery, Form $filtersForm, $fields, EntityDto $entityDto) | |||||
public function handleFiltersForm(RepositoryQueryInterface $repositoryQuery, Form $filtersForm, $fields, EntityDto $entityDto):bool | |||||
{ | { | ||||
foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
$fieldDto->getProperty(), | $fieldDto->getProperty(), | ||||
'dateEnd' | 'dateEnd' | ||||
); | ); | ||||
if($filteredValue['dateStart'] || $filteredValue['dateEnd']){ | |||||
$this->isFiltered = true; | |||||
} | |||||
} else { | } else { | ||||
$filteredValue['value'] = $this->getFilteredValue( | $filteredValue['value'] = $this->getFilteredValue( | ||||
$filtersForm, | $filtersForm, | ||||
$entityDto->getFqcn(), | $entityDto->getFqcn(), | ||||
$fieldDto->getProperty() | $fieldDto->getProperty() | ||||
); | ); | ||||
if($filteredValue['value'] ){ | |||||
$this->isFiltered = true; | |||||
} | |||||
} | } | ||||
$this->applyFilter($repositoryQuery, $fieldDto, $filteredValue); | $this->applyFilter($repositoryQuery, $fieldDto, $filteredValue); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $this->isFiltered; | |||||
} | } | ||||
$customFilter->applyFilter($repositoryQuery, $fieldDto, $filteredValue['value']); | $customFilter->applyFilter($repositoryQuery, $fieldDto, $filteredValue['value']); | ||||
} else { | } else { | ||||
switch ($this->guessFormType($fieldDto)) { | |||||
switch ($fieldDto->getFormType()) { | |||||
case CheckboxType::class: | case CheckboxType::class: | ||||
$checkboxFilter = new CheckboxFilter(); | $checkboxFilter = new CheckboxFilter(); | ||||
} | } | ||||
} | } | ||||
protected function guessFormType(FieldDto $fieldDto) | |||||
{ | |||||
if ($fieldDto->getCustomOption('filter_type')) { | |||||
return $fieldDto->getCustomOption('filter_type'); | |||||
} else { | |||||
return $fieldDto->getFormType(); | |||||
} | |||||
} | |||||
} | } |
{ | { | ||||
$property = $fieldDto->getProperty(); | $property = $fieldDto->getProperty(); | ||||
//TODO pas forcément utile, à discuter | //TODO pas forcément utile, à discuter | ||||
if ($fieldDto->getCustomOption('filter_on')) { | |||||
$property = $property . '.' . $fieldDto->getCustomOption('filter_on'); | |||||
} | |||||
// if ($fieldDto->getCustomOption('filter_on')) { | |||||
// $property = $property . '.' . $fieldDto->getCustomOption('filter_on'); | |||||
// } | |||||
return $property; | return $property; | ||||
} | } | ||||
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketEmailFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByEmail($filteredValue); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketFirstnameFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByFirstname($filteredValue); | |||||
} | |||||
} | |||||
} |
<?php | |||||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
/** | |||||
* @author La clic ! <contact@laclic.fr> | |||||
*/ | |||||
class TicketLastnameFilter extends AssociationFilter | |||||
{ | |||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||||
{ | |||||
$builder->add( | |||||
$fieldDto->getProperty(), | |||||
TextType::class, | |||||
array( | |||||
'required' => false, | |||||
'attr' => array( | |||||
'class' => ' input-sm', | |||||
'form' => 'filters-form', | |||||
), | |||||
) | |||||
); | |||||
} | |||||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||||
{ | |||||
if ($filteredValue !== null) { | |||||
$repositoryQuery->filterByLastname($filteredValue); | |||||
} | |||||
} | |||||
} |
{ | { | ||||
protected EntityManager $entityManager; | protected EntityManager $entityManager; | ||||
protected TranslatorAdmin $translatorAdmin; | protected TranslatorAdmin $translatorAdmin; | ||||
protected TicketSolver $ticketSolver; | |||||
public function __construct( | public function __construct( | ||||
EntityManager $entityManager, | EntityManager $entityManager, | ||||
TranslatorAdmin $translatorAdmin, | |||||
TicketSolver $ticketSolver | |||||
TranslatorAdmin $translatorAdmin | |||||
) { | ) { | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->translatorAdmin = $translatorAdmin; | $this->translatorAdmin = $translatorAdmin; | ||||
$this->ticketSolver = $ticketSolver; | |||||
} | } | ||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
] | ] | ||||
); | ); | ||||
$builder->add( | |||||
'subject', | |||||
TextType::class | |||||
); | |||||
$builder->add( | $builder->add( | ||||
'type', | 'type', | ||||
ChoiceType::class, | ChoiceType::class, | ||||
[ | [ | ||||
'label' => 'Type', | 'label' => 'Type', | ||||
'choices' => $this->translatorAdmin->transChoices( | 'choices' => $this->translatorAdmin->transChoices( | ||||
$this->ticketSolver->getTypeChoices(), | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | 'Ticket', | ||||
'type' | 'type' | ||||
), | ), | ||||
] | ] | ||||
); | ); | ||||
$builder->add( | |||||
'subject', | |||||
TextType::class | |||||
); | |||||
$builder->add( | $builder->add( | ||||
'ticketMessages', | 'ticketMessages', | ||||
CollectionType::class, | CollectionType::class, | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
} | |||||
} |
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | use Lc\SovBundle\Translation\TranslatorAdmin; | ||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; | |||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | use Symfony\Component\Form\Extension\Core\Type\TextareaType; | ||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
use Symfony\Component\OptionsResolver\OptionsResolver; | use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
class TicketMessageFormType extends AbstractType | |||||
class TicketMessageAdminFormType extends AbstractType | |||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected $translatorAdmin; | protected $translatorAdmin; | ||||
'required' => true | 'required' => true | ||||
] | ] | ||||
); | ); | ||||
$builder->add( | $builder->add( | ||||
'submit', | |||||
SubmitType::class, | |||||
[ | |||||
'label' => $this->translatorAdmin->transAction('send') | |||||
] | |||||
'answerByAdmin', | |||||
HiddenType::class, | |||||
[ | |||||
'data' => 1 | |||||
] | |||||
); | ); | ||||
} | } | ||||
namespace Lc\SovBundle\Form\Ticket; | namespace Lc\SovBundle\Form\Ticket; | ||||
use App\Entity\Address; | |||||
use App\Entity\OrderShop; | |||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\ShopBundle\Model\Ticket; | |||||
use Lc\ShopBundle\Services\UtilsManager; | |||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | ||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||||
use Symfony\Component\Form\Extension\Core\Type\EmailType; | |||||
use Symfony\Component\Form\Extension\Core\Type\FileType; | use Symfony\Component\Form\Extension\Core\Type\FileType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | use Symfony\Component\Form\Extension\Core\Type\TextareaType; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
use Symfony\Component\OptionsResolver\OptionsResolver; | use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
use Symfony\Component\Security\Core\Security; | |||||
use Symfony\Component\Validator\Constraints\File; | use Symfony\Component\Validator\Constraints\File; | ||||
class TicketMessageType extends AbstractType | class TicketMessageType extends AbstractType | ||||
{ | { | ||||
protected EntityManagerInterface $entityManager; | |||||
public function __construct(EntityManagerInterface $entityManager) | |||||
{ | |||||
$this->entityManager = $entityManager; | |||||
} | |||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
{ | { | ||||
'label' => 'entity.TicketMessage.fields.closeTicket', | 'label' => 'entity.TicketMessage.fields.closeTicket', | ||||
'translation_domain' => 'admin', | 'translation_domain' => 'admin', | ||||
'required' => false, | 'required' => false, | ||||
'mapped' => false, | |||||
]); | ]); | ||||
} | } | ||||
public function configureOptions(OptionsResolver $resolver) | public function configureOptions(OptionsResolver $resolver) | ||||
{ | { | ||||
$resolver->setDefaults([ | $resolver->setDefaults([ | ||||
// Configure your form options here | |||||
'data_class' => $this->entityManager->getEntityName(TicketMessageInterface::class), | |||||
]); | ]); | ||||
} | } | ||||
} | } |
{ | { | ||||
use StatusTrait; | use StatusTrait; | ||||
/** | /** | ||||
* @ORM\Column(type="text") | * @ORM\Column(type="text") | ||||
*/ | */ | ||||
public function __toString() | public function __toString() | ||||
{ | { | ||||
return $this->message; | |||||
return ''.$this->message; | |||||
} | } | ||||
public function getMessage(): ?string | public function getMessage(): ?string |
const TICKET_STATUS_OPEN = 'open'; | const TICKET_STATUS_OPEN = 'open'; | ||||
const TICKET_STATUS_BEING_PROCESSED = 'being-processed'; | const TICKET_STATUS_BEING_PROCESSED = 'being-processed'; | ||||
const TICKET_STATUS_PROCESSED = 'processed'; | |||||
const TICKET_STATUS_CLOSED = 'closed'; | const TICKET_STATUS_CLOSED = 'closed'; | ||||
/** | /** | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getStatus(): ?string | public function getStatus(): ?string | ||||
{ | { | ||||
return $this->status; | return $this->status; | ||||
return $this; | return $this; | ||||
} | } | ||||
public function getSubject(): ?string | public function getSubject(): ?string | ||||
{ | { | ||||
return $this->subject; | return $this->subject; |
return $this->birthdate; | return $this->birthdate; | ||||
} | } | ||||
public function setBirthdate(\DateTimeInterface $birthdate): self | |||||
public function setBirthdate(?\DateTimeInterface $birthdate): self | |||||
{ | { | ||||
$this->birthdate = $birthdate; | $this->birthdate = $birthdate; | ||||
public function filterByOldUrl(string $oldUrl): self | public function filterByOldUrl(string $oldUrl): self | ||||
{ | { | ||||
// @TODO : ne fonctionne pas, utilisation de LIKE à la place ? | |||||
//return $this->andWhere(':oldUrl IN (.oldUrls)')->setParameter('oldUrl', $oldUrl); | |||||
return $this->andWhere(':oldUrl LIKE .oldUrls')->setParameter('oldUrl', $oldUrl); | |||||
return $this->andWhere('.oldUrls LIKE :oldUrl')->setParameter('oldUrl', '%'.$oldUrl.'%'); | |||||
} | } | ||||
/* | /* |
class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | ||||
{ | { | ||||
protected $isJoinUser = false; | |||||
public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | ||||
{ | { | ||||
parent::__construct($repository, 'r', $paginator); | parent::__construct($repository, 'r', $paginator); | ||||
->setParameter('user', $user); | ->setParameter('user', $user); | ||||
} | } | ||||
public function joinUser(): self | |||||
{ | |||||
if (!$this->isJoinUser) { | |||||
$this->isJoinUser = true; | |||||
return $this | |||||
->leftJoin('.user', 'user'); | |||||
} | |||||
return $this; | |||||
} | |||||
public function filterByStatus($statusArray): self | public function filterByStatus($statusArray): self | ||||
{ | { | ||||
return $this | return $this | ||||
->setParameter('status', $statusArray); | ->setParameter('status', $statusArray); | ||||
} | } | ||||
public function filterByFirstname(string $firstname) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorFirstname LIKE :firstname OR u.firstname LIKE :firstname') | |||||
->setParameter('firstname', '%'.$firstname.'%'); | |||||
} | |||||
public function filterByLastname(string $lastname) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorLastname LIKE :lastname OR u.lastname LIKE :lastname') | |||||
->setParameter('lastname', '%'.$lastname.'%'); | |||||
} | |||||
public function filterByEmail(string $email) | |||||
{ | |||||
$this->joinUser(); | |||||
return $this | |||||
->andWhere('.visitorEmail LIKE :email OR u.email LIKE :email') | |||||
->setParameter('email', '%'.$email.'%'); | |||||
} | |||||
public function selectCount(): self | public function selectCount(): self | ||||
{ | { | ||||
return $this | return $this |
{ | { | ||||
parent::__construct($repository, 'r', $paginator); | parent::__construct($repository, 'r', $paginator); | ||||
} | } | ||||
protected $isJoinUsers = false; | |||||
public function joinUsers(): self | |||||
{ | |||||
if (!$this->isJoinUsers) { | |||||
$this->isJoinUsers = true; | |||||
return $this | |||||
->innerJoin('.users', 'user'); | |||||
} | |||||
return $this; | |||||
} | |||||
} | } |
public function relationsDefault(RepositoryQueryInterface $query): RepositoryQueryInterface | public function relationsDefault(RepositoryQueryInterface $query): RepositoryQueryInterface | ||||
{ | { | ||||
$query->joinUsers(); | |||||
return $query; | return $query; | ||||
} | } | ||||
} | } |
parent::__construct($repository, 'r', $paginator); | parent::__construct($repository, 'r', $paginator); | ||||
} | } | ||||
protected $isJoinGroupUsers = false; | |||||
public function joinGroupUsers($addSelect = true): self | |||||
{ | |||||
if (!$this->isJoinGroupUsers) { | |||||
$this->isJoinGroupUsers = true; | |||||
$this->innerJoin('.groupUsers', 'groupUser'); | |||||
if($addSelect){ | |||||
$this->addSelect('groupUser'); | |||||
} | |||||
} | |||||
return $this; | |||||
} | |||||
public function filterByNewsletter(Newsletter $newsletter): self | public function filterByNewsletter(Newsletter $newsletter): self | ||||
{ | { | ||||
return $this | return $this |
white-space: normal; | white-space: normal; | ||||
} | } | ||||
} | } | ||||
table.fixedHeader-floating{margin-top: 0px !important;} | |||||
table th.sorting_asc, table th.sorting_desc{border-top:2px solid var(--success);} | |||||
.card-body table th.filtered{border-top:2px solid var(--primary);} | |||||
/*.card-body table.lc-table-list th{border-top:3px solid var(--success);}*/ | |||||
table th.filtered{border-top:2px solid var(--primary);} | |||||
.card-body table th.sorted, table th.sorting_asc, table th.sorting_desc{border-top:2px solid var(--success);} | |||||
.card-body table th.sorted.filtered{border-top:0px; position: relative;} | |||||
.card-body table th.sorted.filtered:after{ content: ''; height: 2px; position: absolute; left: 0; width: 100%; right: 0; top: -1px; background: linear-gradient(to right, var(--success) 0%, var(--success) 50%, var(--primary) 50%, var(--primary) 100%);} |
// Replace '__name__' in the prototype's HTML to | // Replace '__name__' in the prototype's HTML to | ||||
$(li).find('div:last-child').remove(); | $(li).find('div:last-child').remove(); | ||||
$(li).append(newForm); | |||||
$(li).find('td:first').append('<div class="hidden">'+newForm+'</div>'); | |||||
$(li).find('#form_entities_' + index + '_id').val($(li).data('id')); | $(li).find('#form_entities_' + index + '_id').val($(li).data('id')); | ||||
/* if ($('.sov-sortable').data('parent-position') !== '') { | /* if ($('.sov-sortable').data('parent-position') !== '') { | ||||
//Ajout d'un 0 initial pour les nuémros <10 | //Ajout d'un 0 initial pour les nuémros <10 |
account: Mon compte | account: Mon compte | ||||
account_profile: Informations personnelles | account_profile: Informations personnelles | ||||
account_password: Mot de passe | account_password: Mot de passe | ||||
tickets: Tickets | |||||
tickets: Tickets <span class="float-right badge badge-info">%total_ticket_open%</span> | |||||
setting_global: Global | setting_global: Global | ||||
title: | title: | ||||
label: Ticket | label: Ticket | ||||
label_plurial: Tickets | label_plurial: Tickets | ||||
fields: | fields: | ||||
visitorFirstName: Nom | |||||
visitorLastName: Prénom | |||||
visitorFirstname: Nom | |||||
visitorLastname: Prénom | |||||
visitorEmail: E-mail | visitorEmail: E-mail | ||||
subject: Sujet | subject: Sujet | ||||
type: Type | type: Type | ||||
open: Ouvert | open: Ouvert | ||||
being-processed: En attente | being-processed: En attente | ||||
closed: Fermé | closed: Fermé | ||||
ticketMessages: Message | |||||
TicketModel: | TicketModel: | ||||
fields: | fields: | ||||
open: Ouvert | open: Ouvert | ||||
default: | default: | ||||
fields: | fields: | ||||
id: Id | id: Id | ||||
createdAt: Créé à | |||||
createdAt: Créé le | |||||
user: Utilisateur | user: Utilisateur | ||||
firstname: Prénom | firstname: Prénom | ||||
lastname: Nom | lastname: Nom |
<div class="col-12"> | <div class="col-12"> | ||||
{{ form_row(form_add_ticket_message.message) }} | {{ form_row(form_add_ticket_message.message) }} | ||||
</div> | </div> | ||||
<div class="col-12 text-right"> | |||||
<button type="submit" class="btn btn-primary text-right">{{ 'send'|sov_trans_admin_action }}</button> | |||||
</div> | |||||
</div> | </div> | ||||
{{ form_end(form_add_ticket_message) }} | {{ form_end(form_add_ticket_message) }} | ||||
</div> | </div> |
{#{% set ticketMessage = entity.instance.getLastMessage() %}#} | |||||
{#{% if ticketMessage.answerByAdmin != true %}#} | |||||
{# <span class="badge badge-danger">#} | |||||
{# New#} | |||||
{# </span>#} | |||||
{#{% endif %}#} | |||||
{#{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par {{ ticketMessage.createdBy }} {{ ticketMessage.message }}#} | |||||
{% if item is not defined %} | |||||
{% set item = entity.instance %} | |||||
{% endif %} | |||||
{% set ticketMessage = ticket_container.solver.getLastMessage(item) %} | |||||
{% if ticketMessage.answerByAdmin != true %} | |||||
<span class="badge badge-danger"> | |||||
New | |||||
</span> | |||||
{% endif %} | |||||
{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par | |||||
{% if ticketMessage.answerByAdmin %} | |||||
Équipe | |||||
{% else %} | |||||
Client | |||||
{% endif %} | |||||
{# {% set ticket = entity.instance %} #} | |||||
{# {% if ticket.ticketMessages %} #} | |||||
{# {% for message in ticket.ticketMessages %} #} | |||||
{# {% if loop.last %} #} | |||||
{# {% if message.answerByAdmin %} #} | |||||
{# Équipe #} | |||||
{# {% else %} #} | |||||
{# Client #} | |||||
{# {% endif %} #} | |||||
{# {% endif %} #} | |||||
{# {% endfor %} #} | |||||
{# {% endif %} #} | |||||
{{ macro.badge_success(status|sov_trans_admin_choice('status','Ticket')) }} | {{ macro.badge_success(status|sov_trans_admin_choice('status','Ticket')) }} | ||||
{% elseif status == 'being-processed' %} | {% elseif status == 'being-processed' %} | ||||
{{ macro.badge_warning(status|sov_trans_admin_choice('status','Ticket')) }} | {{ macro.badge_warning(status|sov_trans_admin_choice('status','Ticket')) }} | ||||
{% elseif status == 'processed' %} | |||||
{{ macro.badge_info(status|sov_trans_admin_choice('status','Ticket')) }} | |||||
{% elseif status == 'closed' %} | {% elseif status == 'closed' %} | ||||
{{ macro.badge_danger(status|sov_trans_admin_choice('status','Ticket')) }} | {{ macro.badge_danger(status|sov_trans_admin_choice('status','Ticket')) }} | ||||
{% endif %} | {% endif %} |
<th>Sujet</th> | <th>Sujet</th> | ||||
<th>Statut</th> | <th>Statut</th> | ||||
<th>Dernier message</th> | <th>Dernier message</th> | ||||
<th></th> | |||||
<th>Actions</th> | |||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> |
{% if item.icon is not empty %} | {% if item.icon is not empty %} | ||||
<i class="{{ item.icon }} nav-icon"></i> | <i class="{{ item.icon }} nav-icon"></i> | ||||
{% endif %} | {% endif %} | ||||
<p>{{ item.label|sov_trans_admin_menu }}</p> | |||||
<p>{{ item.label|sov_trans_admin_menu(item.translationParameters)|raw }}</p> | |||||
{% if item.hasSubItems %}<i class="right fas fa-angle-left"></i>{% endif %} | {% if item.hasSubItems %}<i class="right fas fa-angle-left"></i>{% endif %} | ||||
</a> | </a> | ||||
{% endif %} | {% endif %} | ||||
</ul> | </ul> | ||||
</nav> | </nav> | ||||
{% block main_menu_after %}{% endblock %} | |||||
{% block main_menu_after %}{% endblock %} |
Pense-bête | Pense-bête | ||||
</a> | </a> | ||||
</li> | </li> | ||||
{# TODO Adapter Pour Caracole #} | |||||
{# <li class="nav-item">#} | |||||
{# <a href="{{ path(sov_homepage_route(), {section: section_slug_current()}) }}" class="btn btn-sm btn-block btn-outline-success" target="_blank"#} | |||||
{# rel="noreferrer">#} | |||||
{# <i class="action-icon fa fa-eye"></i>#} | |||||
{# Afficher le site#} | |||||
{# </a>#} | |||||
{# </li>#} | |||||
<li class="nav-item"> | |||||
<a href="{{ path(sov_homepage_route()) }}" class="btn btn-sm btn-block btn-outline-success" target="_blank" | |||||
rel="noreferrer"> | |||||
<i class="action-icon fa fa-eye"></i> | |||||
Afficher le site | |||||
</a> | |||||
</li> | |||||
</ul> | </ul> | ||||
</nav> | </nav> |
{# @var ea \EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext #} | |||||
{# @var field \EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto #} | |||||
{# @var entity \EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto #} | |||||
{% if 'toMany' == field.customOptions.get('associationType') %} | |||||
<span class="badge badge-secondary">{{ field.formattedValue }}</span> | |||||
{% else %} | |||||
{% if field.customOption('crudControllerFqcn') is not null and field.value is not null%} | |||||
<a href="{{ ea_url_short(field.customOption('crudControllerFqcn'), 'edit', field.value.id) }}">{{ field.formattedValue }}</a> | |||||
{% else %} | |||||
{{ field.formattedValue }} | |||||
{% endif %} | |||||
{% endif %} |
{% set id_toggle = 'toggle-'~item.id~'-'~property_name %} | {% set id_toggle = 'toggle-'~item.id~'-'~property_name %} | ||||
{% block toggle %} | {% block toggle %} | ||||
<div class="custom-control custom-switch custom-switch-on-success custom-switch-off-default" | |||||
<div class="custom-control custom-switch custom-switch-on-success custom-switch-off-default" data-toggle="tooltip" title="{{ field.getCustomOption('toggle_label') ? field.label : field.property|sov_trans_admin_field(entity.instance) }}" | |||||
data-url="{{ ea_url({crudAction: 'edit', entityId: item.id, fieldName: property_name }) }}"> | 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 }}"> | |||||
{% block label %} | |||||
{{ field.getCustomOption('toggle_label') ? field.label : field.property|sov_trans_admin_field(entity.instance) }} | |||||
{% endblock label %} | |||||
<input type="checkbox" class="custom-control-input" id="{{ id_toggle }}" {{ field.value ? 'checked' }}> | |||||
<label class="custom-control-label" for="{{ id_toggle }}" > | |||||
</label> | </label> | ||||
</div> | </div> | ||||
{% endblock toggle %} | {% endblock toggle %} |
{% block class %}{{ loop.first ? 'active' }}{% endblock %} | {% block class %}{{ loop.first ? 'active' }}{% endblock %} | ||||
{% block id %}{{ panel_name }}{% endblock %} | {% block id %}{{ panel_name }}{% endblock %} | ||||
{% block content %} | {% block content %} | ||||
{% if panel_config['prepend_content_path'] is defined %} | |||||
{% include panel_config['prepend_content_path'] %} | |||||
{% endif %} | |||||
{% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and field.vars.ea_crud_form.form_panel == panel_name) %} | {% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and field.vars.ea_crud_form.form_panel == panel_name) %} | ||||
{% if not field.vars.ea_crud_form.form_tab or field.vars.ea_crud_form.form_tab == tab_name %} | {% if not field.vars.ea_crud_form.form_tab or field.vars.ea_crud_form.form_tab == tab_name %} | ||||
{{ form_row(field) }} | {{ form_row(field) }} | ||||
{% endif %} | {% endif %} | ||||
{% endfor %} | {% endfor %} | ||||
{% if panel_config['append_content_path'] is defined %} | |||||
{% include panel_config['append_content_path'] %} | |||||
{% endif %} | |||||
{% endblock %} | {% endblock %} | ||||
{% endembed %} | {% endembed %} | ||||
{% else %} | {% else %} |
<div class="btn-list float-sm-right"> | <div class="btn-list float-sm-right"> | ||||
{% block global_actions %} | |||||
<div class="global-actions"> | |||||
<div class="global-actions"> | |||||
{% block global_actions %} | |||||
{% for action in global_actions %} | {% for action in global_actions %} | ||||
{{ include(action.templatePath, { action: action }, with_context = false) }} | {{ include(action.templatePath, { action: action }, with_context = false) }} | ||||
{% endfor %} | {% endfor %} | ||||
</div> | |||||
{% endblock global_actions %} | |||||
{% endblock global_actions %} | |||||
</div> | |||||
{% block batch_actions %} | {% block batch_actions %} | ||||
{% if has_batch_actions %} | {% if has_batch_actions %} | ||||
<div class="batch-actions" style="display: none"> | <div class="batch-actions" style="display: none"> | ||||
{% endblock %} | {% endblock %} | ||||
{% block card_body_wrapper %} | {% block card_body_wrapper %} | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="table-responsive"> | |||||
<div class=""> | |||||
<table class="table table-bordered table-hover table-striped"> | <table class="table table-bordered table-hover table-striped"> | ||||
<thead> | <thead> | ||||
{% block table_head %} | {% block table_head %} |
{% set is_sorting_field = ea.search.isSortingField(field.property) %} | {% set is_sorting_field = ea.search.isSortingField(field.property) %} | ||||
<th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}" | <th class="{{ is_sorting_field ? 'sorted' }} {{ field.isVirtual ? 'field-virtual' }} {% if field.textAlign %}text-{{ field.textAlign }}{% endif %}" | ||||
dir="{{ ea.i18n.textDirection }}"> | dir="{{ ea.i18n.textDirection }}"> | ||||
<span>{{ field.label ? field.label|raw : field.getProperty|raw }}</span> | |||||
<span> | |||||
{% if field.label is not null %} | |||||
{{ field.label|raw }} | |||||
{% else %} | |||||
{{ field.getProperty|sov_trans_admin_field_index(translation_entity_name) }} | |||||
{% endif %} | |||||
</span> | |||||
</th> | </th> | ||||
{% endif %} | {% endif %} | ||||
{% endfor %} | {% endfor %} |
{% endif %} | {% endif %} | ||||
{% endif %} | {% endif %} | ||||
{% block append_body %}{% endblock %} | {% block append_body %}{% endblock %} | ||||
</body> | </body> |
{{ _self.badge('danger', title) }} | {{ _self.badge('danger', title) }} | ||||
{% endmacro %} | {% endmacro %} | ||||
{% macro badge_info(title) %} | |||||
{{ _self.badge('info', title) }} | |||||
{% endmacro %} | |||||
{% macro badge(status, title) %} | {% macro badge(status, title) %} | ||||
<span class="badge badge-{{ status }}">{{ title }}</span> | <span class="badge badge-{{ status }}">{{ title }}</span> | ||||
{% endmacro %} | |||||
{% endmacro %} |
class TicketSolver | class TicketSolver | ||||
{ | { | ||||
public function getTypeChoices(): array | |||||
public static function getTypeChoices(): array | |||||
{ | { | ||||
return [ | return [ | ||||
TicketModel::TYPE_GENERAL_QUESTION, | TicketModel::TYPE_GENERAL_QUESTION, | ||||
]; | ]; | ||||
} | } | ||||
public function getStatusChoices(): array | |||||
public static function getStatusChoices(): array | |||||
{ | { | ||||
return [ | return [ | ||||
TicketModel::TICKET_STATUS_OPEN, | TicketModel::TICKET_STATUS_OPEN, | ||||
TicketModel::TICKET_STATUS_BEING_PROCESSED, | TicketModel::TICKET_STATUS_BEING_PROCESSED, | ||||
TicketModel::TICKET_STATUS_PROCESSED, | |||||
TicketModel::TICKET_STATUS_CLOSED, | TicketModel::TICKET_STATUS_CLOSED, | ||||
]; | ]; | ||||
} | } |
return $this->trans('action.' . $action); | return $this->trans('action.' . $action); | ||||
} | } | ||||
public function transMenu($menu): string | |||||
public function transMenu($menu, $params = []): string | |||||
{ | { | ||||
return $this->trans('menu.' . $menu); | |||||
return $this->trans('menu.' . $menu, $params); | |||||
} | } | ||||
public function transFlashMessage($type, $name, $entityClass = false, $params = []): string | public function transFlashMessage($type, $name, $entityClass = false, $params = []): string |
public function getReminders($params) | public function getReminders($params) | ||||
{ | { | ||||
//TODO !!!!!! | |||||
// @TODO : à faire | |||||
return array(); | return array(); | ||||
} | } | ||||
return $this->translatorAdmin->transCard($cardName, $entityClass); | return $this->translatorAdmin->transCard($cardName, $entityClass); | ||||
} | } | ||||
public function transAdminMenu($menuName) | |||||
public function transAdminMenu($menuName, $params = []) | |||||
{ | { | ||||
return $this->translatorAdmin->transMenu($menuName);; | |||||
return $this->translatorAdmin->transMenu($menuName, $params);; | |||||
} | } | ||||
public function transAdminAction($actionName) | public function transAdminAction($actionName) |
use Lc\SovBundle\Component\FileComponent; | use Lc\SovBundle\Component\FileComponent; | ||||
use Lc\SovBundle\Component\MetaComponent; | use Lc\SovBundle\Component\MetaComponent; | ||||
use Lc\SovBundle\Component\StringComponent; | use Lc\SovBundle\Component\StringComponent; | ||||
use Lc\SovBundle\Doctrine\EntityInterface; | |||||
use Lc\SovBundle\Form\Newsletter\NewsletterType; | use Lc\SovBundle\Form\Newsletter\NewsletterType; | ||||
use Lc\SovBundle\Model\File\FileInterface; | use Lc\SovBundle\Model\File\FileInterface; | ||||
use Lc\SovBundle\Repository\Reminder\ReminderStore; | use Lc\SovBundle\Repository\Reminder\ReminderStore; | ||||
new TwigFunction('day_by_number', [$this, 'getDayByNumber']), | new TwigFunction('day_by_number', [$this, 'getDayByNumber']), | ||||
new TwigFunction('user_current', [$this, 'getUserCurrent']), | new TwigFunction('user_current', [$this, 'getUserCurrent']), | ||||
new TwigFunction('ea_url_short', [$this, 'generateEaUrl']), | new TwigFunction('ea_url_short', [$this, 'generateEaUrl']), | ||||
new TwigFunction('is_instance_of', [$this, 'isInstanceOf']), | |||||
]; | ]; | ||||
} | } | ||||
]; | ]; | ||||
} | } | ||||
public function isInstanceOf(EntityInterface $entity, string $interfaceName) | |||||
{ | |||||
$reflection = new \ReflectionClass($entity); | |||||
$interfaceNameArray = $reflection->getInterfaceNames(); | |||||
foreach($interfaceNameArray as $interfaceNameEntity) { | |||||
if(strpos($interfaceNameEntity, $interfaceName) !== false) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
public function sovCache($file) | public function sovCache($file) | ||||
{ | { | ||||
$cacheTime = filemtime($this->kernel->getProjectDir() . '/public' . $file); | $cacheTime = filemtime($this->kernel->getProjectDir() . '/public' . $file); |