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; | ||||
} | } | ||||
protected TicketBuilder $builder; | protected TicketBuilder $builder; | ||||
protected TicketRepositoryQuery $repositoryQuery; | protected TicketRepositoryQuery $repositoryQuery; | ||||
protected TicketStore $store; | protected TicketStore $store; | ||||
protected TicketFieldDefinition $fieldDefinition; | |||||
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, | ||||
TicketFieldDefinition $fieldDefinition, | |||||
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->fieldDefinition = $fieldDefinition; | |||||
$this->solver = $solver; | $this->solver = $solver; | ||||
$this->fieldDefinition = $fieldDefinition; | |||||
} | } | ||||
public function getFactory(): TicketFactory | public function getFactory(): TicketFactory | ||||
return $this->store; | return $this->store; | ||||
} | } | ||||
public function getFieldDefinition(): TicketFieldDefinition | |||||
public function getSolver(): TicketSolver | |||||
{ | { | ||||
return $this->fieldDefinition; | |||||
return $this->solver; | |||||
} | } | ||||
public function getSolver(): TicketSolver | |||||
public function getFieldDefinition(): TicketFieldDefinition | |||||
{ | { | ||||
return $this->solver; | |||||
return $this->fieldDefinition; | |||||
} | } | ||||
} | } |
use ControllerTrait; | use ControllerTrait; | ||||
protected FormInterface $filtersForm; | protected FormInterface $filtersForm; | ||||
protected bool $isRepositoryQueryFiltered = false; | |||||
abstract public function getRepositoryQuery(): RepositoryQueryInterface; | abstract public function getRepositoryQuery(): RepositoryQueryInterface; | ||||
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, | ||||
$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; | ||||
} | } | ||||
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; | ||||
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 | |||||
{ | |||||
$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 | ||||
{ | { | ||||
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | ||||
} | } | ||||
public function configureAssets(Assets $assets): Assets | public function configureAssets(Assets $assets): Assets | ||||
return $assets; | return $assets; | ||||
} | } | ||||
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( | |||||
SearchDto $searchDto, | |||||
EntityDto $entityDto, | |||||
FieldCollection $fields, | |||||
FilterCollection $filters | |||||
): RepositoryQueryInterface { | |||||
$repositoryQuery = parent::createIndexRepositoryQuery( | |||||
$searchDto, | |||||
$entityDto, | |||||
$fields, | |||||
$filters | |||||
); | |||||
if(!$this->isRepositoryQueryFiltered()){ | |||||
$repositoryQuery->filterByStatus(array( | |||||
TicketModel::TICKET_STATUS_OPEN, | |||||
TicketModel::TICKET_STATUS_BEING_PROCESSED, | |||||
TicketModel::TICKET_STATUS_PROCESSED | |||||
)); | |||||
} | |||||
return $repositoryQuery; | |||||
} | } | ||||
public function detail(AdminContext $context) | public function detail(AdminContext $context) | ||||
{ | { | ||||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | $adminUrlGenerator = $this->get(AdminUrlGenerator::class); | ||||
); | ); | ||||
$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( | ||||
} | } | ||||
public function ticketStatusAction() | |||||
public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager) | |||||
{ | { | ||||
$entityManager = $this->getEntityManager(); | |||||
$request = $this->getRequestStack()->getMainRequest(); | |||||
$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()) { | ||||
$entityManager->persist($ticket); | |||||
$entityManager->update($ticket); | |||||
$entityManager->flush(); | $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_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 SWITCH_USER = 'switchUser'; | ||||
} | } |
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 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\DateField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use Lc\CaracoleBundle\Field\Filter\ProductCategoriesFilter; | |||||
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\Definition\Field\AbstractFieldDefinition; | ||||
use Lc\SovBundle\Field\CollectionField; | use Lc\SovBundle\Field\CollectionField; | ||||
use Lc\SovBundle\Field\Filter\Ticket\EmailFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\FirstnameFilter; | |||||
use Lc\SovBundle\Field\Filter\Ticket\LastnameFilter; | |||||
use Lc\SovBundle\Form\Ticket\TicketMessageType; | use Lc\SovBundle\Form\Ticket\TicketMessageType; | ||||
use Lc\SovBundle\Solver\Ticket\TicketSolver; | |||||
use Lc\SovBundle\Translation\TranslatorAdmin; | use Lc\SovBundle\Translation\TranslatorAdmin; | ||||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||||
class TicketFieldDefinition extends AbstractFieldDefinition | class TicketFieldDefinition extends AbstractFieldDefinition | ||||
{ | { | ||||
protected TicketSolver $ticketSolver; | |||||
public function __construct(TranslatorAdmin $translatorAdmin, TicketSolver $ticketSolver) | |||||
public function __construct(TranslatorAdmin $translatorAdmin) | |||||
{ | { | ||||
parent::__construct($translatorAdmin); | parent::__construct($translatorAdmin); | ||||
$this->ticketSolver = $ticketSolver; | |||||
} | } | ||||
public function configureIndex(): array | public function configureIndex(): array | ||||
return [ | return [ | ||||
'id', | 'id', | ||||
'createdAt', | 'createdAt', | ||||
'lastname', | |||||
'firstname', | |||||
'email', | |||||
'type', | |||||
'visitorFirstname', | |||||
'visitorLastname', | |||||
'visitorEmail', | |||||
'subject', | 'subject', | ||||
'lastMessage', | |||||
'updatedAt', | |||||
'type', | |||||
'status' | 'status' | ||||
]; | ]; | ||||
} | } | ||||
]; | ]; | ||||
} | } | ||||
public function configurePanels(): array | |||||
{ | |||||
return []; | |||||
} | |||||
public function configureFields(): array | public function configureFields(): array | ||||
{ | { | ||||
return [ | return [ | ||||
'createdAt' => DateField::new('createdAt')->setFormat('short'), | |||||
'visitorFirstname' => TextField::new('visitorFirstname'), | |||||
'visitorLastname' => TextField::new('visitorLastname'), | |||||
'visitorEmail' => TextField::new('visitorEmail'), | |||||
'lastname' => TextField::new('lastname') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | |||||
->setCustomOption('filter_fqcn', LastnameFilter::class), | |||||
'firstname' => TextField::new('firstname') | |||||
'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') | ->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | ||||
->setCustomOption('filter_fqcn', FirstnameFilter::class), | |||||
'email' => TextField::new('email') | |||||
->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') | ->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | ||||
->setCustomOption('filter_fqcn', EmailFilter::class), | |||||
'user' => AssociationField::new('user'), | |||||
->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') | 'type' => ChoiceField::new('type') | ||||
->autocomplete() | ->autocomplete() | ||||
->setSortable(true) | |||||
->setChoices( | ->setChoices( | ||||
$this->translatorAdmin->transChoices( | $this->translatorAdmin->transChoices( | ||||
$this->ticketSolver->getTypeChoices(), | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | 'Ticket', | ||||
'type' | 'type' | ||||
) | ) | ||||
), | ), | ||||
'subject' => TextField::new('subject'), | |||||
'lastMessage' => TextField::new('lastMessage') | |||||
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig'), | |||||
'status' => ChoiceField::new('status') | 'status' => ChoiceField::new('status') | ||||
->autocomplete() | ->autocomplete() | ||||
->setSortable(true) | |||||
->setChoices( | ->setChoices( | ||||
$this->translatorAdmin->transChoices( | $this->translatorAdmin->transChoices( | ||||
$this->ticketSolver->getStatusChoices(), | |||||
TicketSolver::getStatusChoices(), | |||||
'Ticket', | 'Ticket', | ||||
'status' | 'status' | ||||
) | ) | ||||
) | ) | ||||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig'), | ->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig'), | ||||
'ticketMessages' => CollectionField::new('ticketMessages') | 'ticketMessages' => CollectionField::new('ticketMessages') | ||||
->setFormTypeOption('entry_type', TicketMessageType::class) | |||||
->setFormTypeOption('entry_type', TicketMessageAdminFormType::class) | |||||
->setFormTypeOption('allow_add', false) | ->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' | |||||
]; | ]; | ||||
} | } | ||||
'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() |
<?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; | |||||
} | |||||
} |
<?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], | |||||
], | |||||
] | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
{ | { | ||||
$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; | ||||
} | } | ||||
/** | /** | ||||
* @author La clic ! <contact@laclic.fr> | * @author La clic ! <contact@laclic.fr> | ||||
*/ | */ | ||||
class EmailFilter extends AssociationFilter | |||||
class TicketEmailFilter extends AssociationFilter | |||||
{ | { | ||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | ||||
{ | { |
/** | /** | ||||
* @author La clic ! <contact@laclic.fr> | * @author La clic ! <contact@laclic.fr> | ||||
*/ | */ | ||||
class FirstnameFilter extends AssociationFilter | |||||
class TicketFirstnameFilter extends AssociationFilter | |||||
{ | { | ||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | ||||
{ | { |
/** | /** | ||||
* @author La clic ! <contact@laclic.fr> | * @author La clic ! <contact@laclic.fr> | ||||
*/ | */ | ||||
class LastnameFilter extends AssociationFilter | |||||
class TicketLastnameFilter extends AssociationFilter | |||||
{ | { | ||||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | ||||
{ | { |
{ | { | ||||
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) | ||||
[ | [ | ||||
'label' => 'Type', | 'label' => 'Type', | ||||
'choices' => $this->translatorAdmin->transChoices( | 'choices' => $this->translatorAdmin->transChoices( | ||||
$this->ticketSolver->getTypeChoices(), | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | 'Ticket', | ||||
'type' | 'type' | ||||
), | ), | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
} | |||||
} |
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 | |||||
] | |||||
); | ); | ||||
} | } | ||||
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'; | ||||
/** | /** |
class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | ||||
{ | { | ||||
protected bool $isJoinUser = false; | |||||
protected $isJoinUser = false; | |||||
public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | public function __construct(TicketRepository $repository, PaginatorInterface $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 | ||||
return $this | return $this | ||||
->select('count(r.id) as count'); | ->select('count(r.id) as count'); | ||||
} | } | ||||
public function joinUser(): self | |||||
{ | |||||
if (!$this->isJoinUser) { | |||||
$this->isJoinUser = true; | |||||
return $this->leftJoin('.user', 'u'); | |||||
} | |||||
return $this; | |||||
} | |||||
} | } |
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: | ||||
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> |
{# @TODO : génère une erreur sur le tableau de bord | |||||
{% set ticket = entity.instance %} | |||||
{% if ticket.ticketMessages %} | |||||
{% for message in ticket.ticketMessages %} | |||||
{% if loop.last %} | |||||
{% if message.answerByAdmin %} | |||||
Équipe | |||||
{% else %} | |||||
Client | |||||
{% endif %} | |||||
{% endif %} | |||||
{% endfor %} | |||||
{% if item is not defined %} | |||||
{% set item = entity.instance %} | |||||
{% endif %} | {% 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 %} |
{{ _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 |
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) |