Sfoglia il codice sorgente

Finalisation app ticket

feature/symfony6.1
Fab 2 anni fa
parent
commit
f7adba5e15
31 ha cambiato i file con 477 aggiunte e 501 eliminazioni
  1. +15
    -57
      Builder/Ticket/TicketBuilder.php
  2. +10
    -18
      Builder/Ticket/TicketMessageBuilder.php
  3. +0
    -1
      Container/Ticket/TicketContainer.php
  4. +46
    -73
      Controller/Ticket/TicketAdminController.php
  5. +24
    -12
      Definition/Field/Ticket/TicketFieldDefinition.php
  6. +12
    -1
      Definition/Field/User/UserFieldDefinition.php
  7. +0
    -17
      Definition/SiteSettingDefinition.php
  8. +30
    -0
      Event/Ticket/TicketEvent.php
  9. +0
    -1
      EventSubscriber/SiteSettingEventSubscriber.php
  10. +138
    -0
      EventSubscriber/Ticket/SendNotificationTicketEventSubscriber.php
  11. +0
    -48
      Field/Filter/Ticket/EmailTicketFilter.php
  12. +0
    -48
      Field/Filter/Ticket/FirstnameTicketFilter.php
  13. +0
    -48
      Field/Filter/Ticket/LastnameTicketFilter.php
  14. +38
    -0
      Field/Filter/Ticket/TicketEmailFilter.php
  15. +38
    -0
      Field/Filter/Ticket/TicketFirstnameFilter.php
  16. +38
    -0
      Field/Filter/Ticket/TicketLastnameFilter.php
  17. +0
    -93
      Form/Ticket/TicketAdminFormType.php
  18. +5
    -5
      Form/Ticket/TicketFormType.php
  19. +7
    -7
      Form/Ticket/TicketMessageAdminFormType.php
  20. +0
    -45
      Form/Ticket/TicketMessageAdminType.php
  21. +9
    -10
      Form/Ticket/TicketMessageType.php
  22. +1
    -2
      Model/Ticket/TicketMessageModel.php
  23. +0
    -2
      Model/Ticket/TicketModel.php
  24. +28
    -1
      Repository/Ticket/TicketRepositoryQuery.php
  25. +4
    -3
      Resources/translations/admin.fr.yaml
  26. +3
    -0
      Resources/views/admin/ticket/detail.html.twig
  27. +23
    -1
      Resources/views/admin/ticket/field/lastmessage.html.twig
  28. +4
    -2
      Resources/views/adminlte/block/menu.html.twig
  29. +0
    -2
      Resources/views/adminlte/layout.html.twig
  30. +2
    -2
      Translation/TranslatorAdmin.php
  31. +2
    -2
      Twig/TranslatorTwigExtension.php

+ 15
- 57
Builder/Ticket/TicketBuilder.php Vedi File

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']);

+ 10
- 18
Builder/Ticket/TicketMessageBuilder.php Vedi File

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;
} }



+ 0
- 1
Container/Ticket/TicketContainer.php Vedi File

return $this->solver; return $this->solver;
} }



public function getFieldDefinition(): TicketFieldDefinition public function getFieldDefinition(): TicketFieldDefinition
{ {
return $this->fieldDefinition; return $this->fieldDefinition;

+ 46
- 73
Controller/Ticket/TicketAdminController.php Vedi File

use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection; use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
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\Dto\EntityDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
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\TicketAdminFormType;
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 persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
parent::persistEntity($entityManager, $entityInstance);
$this->getEventDispatcher()->dispatch(new TicketEvent($entityInstance), TicketEvent::NEW_TICKET_EVENT);
} }


public function configureCrud(Crud $crud): Crud public function configureCrud(Crud $crud): Crud
{ {
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub
$crud->setDefaultSort(array('updatedAt'=> 'DESC'));
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub
$crud->setDefaultSort(array('updatedAt' => 'DESC'));
return $crud; return $crud;
} }



public function configureFields(string $pageName): iterable
{
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName);

}

public function configureAssets(Assets $assets): Assets public function configureAssets(Assets $assets): Assets
{ {
$assets = parent::configureAssets($assets); $assets = parent::configureAssets($assets);
return $assets; return $assets;
} }


public function configureFields(string $pageName): iterable
{
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName);
}


public function configureActions(Actions $actions): Actions public function configureActions(Actions $actions): Actions
{ {
$actions
->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL)
->remove(Crud::PAGE_INDEX, ActionDefinition::EDIT);
$actions->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL);
$actions = parent::configureActions($actions);
$actions->disable( ActionDefinition::EDIT, ActionDefinition::DUPLICATE);
return $actions;


return parent::configureActions($actions);
} }


public function createIndexRepositoryQuery( public function createIndexRepositoryQuery(


$repositoryQuery->filterByStatus(array( $repositoryQuery->filterByStatus(array(
TicketModel::TICKET_STATUS_OPEN, TicketModel::TICKET_STATUS_OPEN,
TicketModel::TICKET_STATUS_BEING_PROCESSED
TicketModel::TICKET_STATUS_BEING_PROCESSED,
TicketModel::TICKET_STATUS_PROCESSED
)); ));
} }


return $repositoryQuery; return $repositoryQuery;
} }


public function new(AdminContext $context)
{
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);

$ticket = $this->createEntity($context->getEntity()->getFqcn());

$form = $this->createForm(TicketAdminFormType::class, $ticket);

$form->handleRequest($context->getRequest());
if ($form->isSubmitted() && $form->isValid()) {
$ticket = $form->getData();

$this->get(EntityManagerInterface::class)->create($ticket);
$this->get(EntityManagerInterface::class)->flush();

$url = $adminUrlGenerator
->setAction('index')
->generateUrl();

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(AdminContext $context, EntityManagerInterface $entityManager) public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager)
{ {




$success = false; $success = false;
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) {

$entityManager->update($ticket); $entityManager->update($ticket);
$entityManager->flush(); $entityManager->flush();
$success = true; $success = true;

+ 24
- 12
Definition/Field/Ticket/TicketFieldDefinition.php Vedi File



namespace Lc\SovBundle\Definition\Field\Ticket; namespace Lc\SovBundle\Definition\Field\Ticket;



use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition;
use Lc\SovBundle\Field\Filter\Ticket\EmailTicketFilter;
use Lc\SovBundle\Field\Filter\Ticket\FirstnameTicketFilter;
use Lc\SovBundle\Field\Filter\Ticket\LastnameTicketFilter;
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\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 class TicketFieldDefinition extends AbstractFieldDefinition
{ {
public function __construct(TranslatorAdmin $translatorAdmin)
{
parent::__construct($translatorAdmin);
}


public function configureIndex(): array public function configureIndex(): array
{ {
{ {
return [ return [
'user', 'user',
'subject'
'type',
'subject',
'ticketMessages'
]; ];
} }


->hideOnForm(), ->hideOnForm(),
'visitorFirstname' => TextField::new('visitorFirstname') 'visitorFirstname' => TextField::new('visitorFirstname')
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') ->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig')
->setCustomOption('filter_fqcn', FirstnameTicketFilter::class)
->setCustomOption('filter_fqcn', TicketFirstnameFilter::class)
->setSortable(true) ->setSortable(true)
->hideOnForm(), ->hideOnForm(),
'visitorLastname' => TextField::new('visitorLastname') 'visitorLastname' => TextField::new('visitorLastname')
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') ->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig')
->setCustomOption('filter_fqcn', LastnameTicketFilter::class)
->setCustomOption('filter_fqcn', TicketLastnameFilter::class)
->setSortable(true) ->setSortable(true)
->hideOnForm(), ->hideOnForm(),
'visitorEmail' => TextField::new('visitorEmail') 'visitorEmail' => TextField::new('visitorEmail')
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') ->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig')
->setCustomOption('filter_fqcn', EmailTicketFilter::class)
->setCustomOption('filter_fqcn', TicketEmailFilter::class)
->setSortable(true) ->setSortable(true)
->hideOnForm(), ->hideOnForm(),
'user' => AssociationField::new('user') 'user' => AssociationField::new('user')
'Ticket', 'Ticket',
'status' 'status'
) )

) )
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig')
->hideOnForm(),
->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)
]; ];
} }



+ 12
- 1
Definition/Field/User/UserFieldDefinition.php Vedi File

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'
]; ];
} }


'phone' => TextField::new('phone')->setSortable(true), 'phone' => TextField::new('phone')->setSortable(true),
'birthdate' => DateField::new('birthdate')->setSortable(true), 'birthdate' => DateField::new('birthdate')->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()

+ 0
- 17
Definition/SiteSettingDefinition.php Vedi File

'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, 'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED,
] ]
); );


// email
$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
]; ];
} }



+ 30
- 0
Event/Ticket/TicketEvent.php Vedi File

<?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;
}
}

+ 0
- 1
EventSubscriber/SiteSettingEventSubscriber.php Vedi File

{ {
return $this->siteStore->getOneByDevAlias('default'); return $this->siteStore->getOneByDevAlias('default');
} }

} }

+ 138
- 0
EventSubscriber/Ticket/SendNotificationTicketEventSubscriber.php Vedi File

<?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],
],
]
);
}
}
}


}

+ 0
- 48
Field/Filter/Ticket/EmailTicketFilter.php Vedi File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class EmailTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.email LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 0
- 48
Field/Filter/Ticket/FirstnameTicketFilter.php Vedi File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class FirstnameTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.firstname LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 0
- 48
Field/Filter/Ticket/LastnameTicketFilter.php Vedi File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class LastnameTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.lastname LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 38
- 0
Field/Filter/Ticket/TicketEmailFilter.php Vedi File

<?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);
}
}

}

+ 38
- 0
Field/Filter/Ticket/TicketFirstnameFilter.php Vedi File

<?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);
}
}

}

+ 38
- 0
Field/Filter/Ticket/TicketLastnameFilter.php Vedi File

<?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);
}
}

}

+ 0
- 93
Form/Ticket/TicketAdminFormType.php Vedi File

<?php

namespace Lc\SovBundle\Form\Ticket;

use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Model\Ticket\TicketModel;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Solver\Ticket\TicketSolver;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class TicketAdminFormType extends AbstractType
{
protected EntityManager $entityManager;
protected TranslatorAdmin $translatorAdmin;

public function __construct(
EntityManager $entityManager,
TranslatorAdmin $translatorAdmin
) {
$this->entityManager = $entityManager;
$this->translatorAdmin = $translatorAdmin;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
$entityName = $this->entityManager->getEntityName(TicketInterface::class);

$builder->add(
'user',
EntityType::class,
[
'class' => $this->entityManager->getEntityName(UserInterface::class),
]
);

$builder->add(
'subject',
TextType::class
);

$builder->add(
'type',
ChoiceType::class,
[
'label' => 'Type',
'choices' => $this->translatorAdmin->transChoices(
TicketSolver::getTypeChoices(),
'Ticket',
'type'
),
]
);

$builder->add(
'ticketMessages',
CollectionType::class,
[
'entry_type' => TicketMessageAdminType::class,
'allow_add' => false,
'label_attr' => ['class' => 'label-ticket'],
]
);

$builder->add(
'submit',
SubmitType::class,
[
'label' => $this->translatorAdmin->transAction('save')
]
);
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => $this->entityManager->getEntityName(TicketInterface::class),
]
);
}
}

+ 5
- 5
Form/Ticket/TicketFormType.php Vedi File

] ]
); );


$builder->add(
'subject',
TextType::class
);

$builder->add( $builder->add(
'type', 'type',
ChoiceType::class, ChoiceType::class,
] ]
); );


$builder->add(
'subject',
TextType::class
);

$builder->add( $builder->add(
'ticketMessages', 'ticketMessages',
CollectionType::class, CollectionType::class,

Form/Ticket/TicketMessageFormType.php → Form/Ticket/TicketMessageAdminFormType.php Vedi File

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
]
); );
} }



+ 0
- 45
Form/Ticket/TicketMessageAdminType.php Vedi File

<?php

namespace Lc\SovBundle\Form\Ticket;

use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Model\Ticket\TicketMessageInterface;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class TicketMessageAdminType extends AbstractType
{
protected $em;
protected $translatorAdmin;

public function __construct(EntityManager $em, TranslatorAdmin $translatorAdmin)
{
$this->em = $em;
$this->translatorAdmin = $translatorAdmin;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'message',
TextareaType::class,
[
'required' => true
]
);

}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => $this->em->getEntityName(TicketMessageInterface::class),
]
);
}
}

+ 9
- 10
Form/Ticket/TicketMessageType.php Vedi File



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),
]); ]);
} }
} }

+ 1
- 2
Model/Ticket/TicketMessageModel.php Vedi File

{ {
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

+ 0
- 2
Model/Ticket/TicketModel.php Vedi File

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;

+ 28
- 1
Repository/Ticket/TicketRepositoryQuery.php Vedi File



class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface
{ {
protected $isJoinUser = false;


protected $isJoinUser = false;


public function __construct(TicketRepository $repository, PaginatorInterface $paginator) public function __construct(TicketRepository $repository, PaginatorInterface $paginator)
{ {
->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

+ 4
- 3
Resources/translations/admin.fr.yaml Vedi File

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

+ 3
- 0
Resources/views/admin/ticket/detail.html.twig Vedi File

<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>

+ 23
- 1
Resources/views/admin/ticket/field/lastmessage.html.twig Vedi File

New New
</span> </span>
{% endif %} {% endif %}
{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par {{ ticketMessage.createdBy }}

{{ 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 %} #}


+ 4
- 2
Resources/views/adminlte/block/menu.html.twig Vedi File

{% 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 %}

+ 0
- 2
Resources/views/adminlte/layout.html.twig Vedi File

{% endif %} {% endif %}
{% endif %} {% endif %}




{% block append_body %}{% endblock %} {% block append_body %}{% endblock %}


</body> </body>

+ 2
- 2
Translation/TranslatorAdmin.php Vedi File

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

+ 2
- 2
Twig/TranslatorTwigExtension.php Vedi File

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)

Loading…
Annulla
Salva