use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | 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\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters; | use EasyCorp\Bundle\EasyAdminBundle\Config\Filters; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore; | use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | use Lc\SovBundle\Factory\Ticket\TicketFactory; | ||||
use Lc\SovBundle\Field\StatusField; | use Lc\SovBundle\Field\StatusField; | ||||
use Lc\SovBundle\Form\Ticket\TicketFormType; | use Lc\SovBundle\Form\Ticket\TicketFormType; | ||||
use Lc\SovBundle\Form\Ticket\TicketStatusType; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | use Lc\SovBundle\Model\Ticket\TicketInterface; | ||||
use Lc\SovBundle\Controller\AbstractAdminController; | use Lc\SovBundle\Controller\AbstractAdminController; | ||||
use Symfony\Component\HttpFoundation\JsonResponse; | |||||
use Symfony\Component\HttpFoundation\Request; | use Symfony\Component\HttpFoundation\Request; | ||||
use Symfony\Component\HttpFoundation\Response; | use Symfony\Component\HttpFoundation\Response; | ||||
use Symfony\Component\Translation\TranslatableMessage; | |||||
class TicketAdminController extends AbstractAdminController | class TicketAdminController extends AbstractAdminController | ||||
{ | { | ||||
protected $ticketFactory; | protected $ticketFactory; | ||||
protected $adminUrlGenerator; | |||||
public function __construct(TicketFactory $ticketFactory) | |||||
public function __construct(TicketFactory $ticketFactory, AdminUrlGenerator $adminUrlGenerator) | |||||
{ | { | ||||
$this->ticketFactory = $ticketFactory; | $this->ticketFactory = $ticketFactory; | ||||
$this->adminUrlGenerator = $adminUrlGenerator; | |||||
} | } | ||||
public static function getEntityFqcn(): string | public static function getEntityFqcn(): string | ||||
return TicketInterface::class; | return TicketInterface::class; | ||||
} | } | ||||
public function configureAssets(Assets $assets): Assets | |||||
{ | |||||
$assets = parent::configureAssets($assets); | |||||
$assets->addWebpackEncoreEntry('adminlte-ticket'); | |||||
return $assets; | |||||
} | |||||
public function configureFields(string $pageName): iterable | public function configureFields(string $pageName): iterable | ||||
{ | { | ||||
return [ | return [ | ||||
]; | ]; | ||||
} | } | ||||
public function configureCrud(Crud $crud): Crud | |||||
{ | |||||
$crud | |||||
->overrideTemplate('crud/detail', '@LcSov/admin/ticket/detail.html.twig'); | |||||
return parent::configureCrud($crud); | |||||
} | |||||
public function configureActions(Actions $actions): Actions | public function configureActions(Actions $actions): Actions | ||||
{ | { | ||||
$actions | $actions | ||||
if ($form->isSubmitted() && $form->isValid()) { | if ($form->isSubmitted() && $form->isValid()) { | ||||
$ticket = $form->getData(); | $ticket = $form->getData(); | ||||
foreach($ticket->getTicketMessages() as $ticketMessage){ | |||||
foreach ($ticket->getTicketMessages() as $ticketMessage) { | |||||
$this->get('em')->persist($ticketMessage); | $this->get('em')->persist($ticketMessage); | ||||
} | } | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
public function detail(AdminContext $context) | |||||
{ | |||||
$ticket = $context->getEntity()->getInstance(); | |||||
$url = $this->adminUrlGenerator | |||||
->setAction('ticketStatusAction') | |||||
->generateUrl(); | |||||
$formTicketStatus = $this->createForm( | |||||
TicketStatusType::class, | |||||
$ticket, | |||||
[ | |||||
'action' => $url, | |||||
'method' => 'POST', | |||||
] | |||||
); | |||||
return $this->render( | |||||
'@LcSov/admin/ticket/detail.html.twig', | |||||
[ | |||||
'form_ticket_status' => $formTicketStatus->createView(), | |||||
'ticket' => $ticket, | |||||
] | |||||
); | |||||
} | |||||
public function ticketStatusAction() | |||||
{ | |||||
$request = $this->get('request')->getMainRequest(); | |||||
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance(); | |||||
$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); | |||||
$formTicketStatusForm->handleRequest($request); | |||||
$success = false; | |||||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | |||||
$this->get('em')->persist($ticket); | |||||
$this->get('em')->flush(); | |||||
$success = true; | |||||
} | |||||
return new JsonResponse(['success' => $success]); | |||||
} | |||||
} | } |
namespace Lc\SovBundle\Form\Ticket; | namespace Lc\SovBundle\Form\Ticket; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||||
use Lc\SovBundle\Doctrine\EntityManager; | use Lc\SovBundle\Doctrine\EntityManager; | ||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | use Lc\SovBundle\Model\Ticket\TicketInterface; | ||||
use Lc\SovBundle\Model\Ticket\TicketModel; | use Lc\SovBundle\Model\Ticket\TicketModel; | ||||
class TicketFormType extends AbstractType | class TicketFormType extends AbstractType | ||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected $translatorAdmin; | protected $translatorAdmin; | ||||
namespace Lc\SovBundle\Form\Ticket; | namespace Lc\SovBundle\Form\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | use Doctrine\ORM\EntityManagerInterface; | ||||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||||
use Symfony\Component\Form\AbstractType; | use Symfony\Component\Form\AbstractType; | ||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | ||||
use Symfony\Component\Form\FormBuilderInterface; | use Symfony\Component\Form\FormBuilderInterface; | ||||
class TicketStatusType extends AbstractType | class TicketStatusType extends AbstractType | ||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected $translatorAdmin; | |||||
public function __construct(EntityManagerInterface $em) | |||||
public function __construct(EntityManagerInterface $em, TranslatorAdmin $translatorAdmin) | |||||
{ | { | ||||
$this->em = $em; | $this->em = $em; | ||||
$this->translatorAdmin = $translatorAdmin; | |||||
} | } | ||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
$builder->add( | $builder->add( | ||||
'status', | 'status', | ||||
ChoiceType::class, | ChoiceType::class, | ||||
array( | |||||
'choices' => array( | |||||
'field.Ticket.statusOptions.' . TicketModel::TICKET_STATUS_OPEN => TicketModel::TICKET_STATUS_OPEN, | |||||
'field.Ticket.statusOptions.' . TicketModel::TICKET_STATUS_BEING_PROCESSED => TicketModel::TICKET_STATUS_BEING_PROCESSED, | |||||
'field.Ticket.statusOptions.' . TicketModel::TICKET_STATUS_CLOSED => TicketModel::TICKET_STATUS_CLOSED, | |||||
), | |||||
[ | |||||
'choices' => $this->translatorAdmin->transChoices(TicketModel::getChoicesStatus(),TicketModel::class), | |||||
'required' => true, | 'required' => true, | ||||
'expanded' => true | |||||
) | |||||
'expanded' => true, | |||||
'label' => false, | |||||
] | |||||
); | ); | ||||
} | } | ||||
{ | { | ||||
$resolver->setDefaults( | $resolver->setDefaults( | ||||
[ | [ | ||||
'data_class' => $this->em->getClassMetadata(TicketInterface::class)->getName(), | |||||
'translation_domain' => 'lcshop' | |||||
'data_class' => $this->em->getEntityName(TicketInterface::class), | |||||
] | ] | ||||
); | ); | ||||
} | } |
<?php | |||||
namespace Lc\SovBundle\Form\Ticket; | |||||
use Doctrine\ORM\EntityManagerInterface; | |||||
use Symfony\Component\Form\AbstractType; | |||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||||
use Symfony\Component\Form\FormBuilderInterface; | |||||
use Symfony\Component\Form\FormEvent; | |||||
use Symfony\Component\Form\FormEvents; | |||||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||||
use Lc\SovBundle\Model\Ticket\TicketModel; | |||||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||||
class TicketTypeType extends AbstractType | |||||
{ | |||||
protected $em; | |||||
public function __construct(EntityManagerInterface $em) | |||||
{ | |||||
$this->em = $em; | |||||
} | |||||
public function buildForm(FormBuilderInterface $builder, array $options) | |||||
{ | |||||
$builder->addEventListener( | |||||
FormEvents::PRE_SET_DATA, | |||||
function (FormEvent $event) { | |||||
$builder = $event->getForm()->getParent(); | |||||
$builder->add( | |||||
'type', | |||||
ChoiceType::class, | |||||
[ | |||||
'label' => 'field.Ticket.type', | |||||
'multiple' => false, | |||||
'expanded' => false, | |||||
'choices' => [ | |||||
'field.Ticket.typeOptions.' . TicketModel::TYPE_GENERAL_QUESTION => TicketModel::TYPE_GENERAL_QUESTION, | |||||
'field.Ticket.typeOptions.' . TicketModel::TYPE_TECHNICAL_PROBLEM => TicketModel::TYPE_TECHNICAL_PROBLEM, | |||||
], | |||||
'translation_domain' => 'lcshop', | |||||
] | |||||
); | |||||
} | |||||
); | |||||
} | |||||
public function configureOptions(OptionsResolver $resolver) | |||||
{ | |||||
$resolver->setDefaults( | |||||
[ | |||||
'data_class' => $this->em->getClassMetadata(TicketInterface::class)->getName(), | |||||
'translation_domain' => 'lcshop' | |||||
] | |||||
); | |||||
} | |||||
} |
public function getStatusLabel(): string | public function getStatusLabel(): string | ||||
{ | { | ||||
return 'field.Ticket.statusOptions.' . $this->getStatus(); | |||||
return 'entity.Ticket.statusOptions.' . $this->getStatus(); | |||||
} | |||||
public function getChoicesStatus(): array | |||||
{ | |||||
return [ | |||||
'entity.Ticket.fields.statusOptions.' . TicketModel::TICKET_STATUS_OPEN => TicketModel::TICKET_STATUS_OPEN, | |||||
'entity.Ticket.fields.statusOptions.' . TicketModel::TICKET_STATUS_BEING_PROCESSED => TicketModel::TICKET_STATUS_BEING_PROCESSED, | |||||
'entity.Ticket.fields.statusOptions.' . TicketModel::TICKET_STATUS_CLOSED => TicketModel::TICKET_STATUS_CLOSED, | |||||
]; | |||||
} | } | ||||
public function getSubject(): ?string | public function getSubject(): ?string |
import './ticket.js' |
jQuery(document).ready(function () { | |||||
$('.ticket-status').on("change", function () { | |||||
$.ajax({ | |||||
url: $('#ticketStatusForm').prop('action'), | |||||
method: "POST", | |||||
data: $('#ticketStatusForm').serialize(), | |||||
dataType: "json", | |||||
success: function (data) { | |||||
if (data.success) { | |||||
Notification.add('success', 'Le status a bien été mise à jour.'); | |||||
} else { | |||||
Notification.add('danger', 'Une erreur est survenue.'); | |||||
} | |||||
} | |||||
}); | |||||
}); | |||||
}); |
open: Ouvert | open: Ouvert | ||||
being-processed: En attente | being-processed: En attente | ||||
closed: Fermé | closed: Fermé | ||||
TicketModel: | |||||
fields: | |||||
open: Ouvert | |||||
being-processed: En attente | |||||
closed: Fermé | |||||
TicketMessage: | TicketMessage: | ||||
fields: | fields: | ||||
message: Votre réponse | message: Votre réponse |
{% endblock %} | {% endblock %} | ||||
{% block main %} | {% block main %} | ||||
{{ dump() }} | |||||
<div class="row"> | <div class="row"> | ||||
<div class="col-4"> | <div class="col-4"> | ||||
{% embed '@LcSov/adminlte/embed/infobox.html.twig' %} | {% embed '@LcSov/adminlte/embed/infobox.html.twig' %} | ||||
{% block icon %}fa fa-toggle-on{% endblock %} | {% block icon %}fa fa-toggle-on{% endblock %} | ||||
{% block title %}Status{% endblock %} | {% block title %}Status{% endblock %} | ||||
{% block content %} | {% block content %} | ||||
{{ entity.instance.status }} | |||||
{% form_theme form_ticket_status '@LcSov/adminlte/crud/form_theme.html.twig' %} | |||||
{{ form_start(form_ticket_status,{'attr' : {'id' : 'ticketStatusForm'}}) }} | |||||
{% for field in form_ticket_status.status %} | |||||
{{ form_widget(field, {'attr': {"class" : 'ticket-status'}}) }} | |||||
{% endfor %} | |||||
{{ form_end(form_ticket_status) }} | |||||
{% endblock %} | {% endblock %} | ||||
{% endembed %} | {% endembed %} | ||||
{% block icon %}fa fa-user{% endblock %} | {% block icon %}fa fa-user{% endblock %} | ||||
{% block title %}Utilisateur{% endblock %} | {% block title %}Utilisateur{% endblock %} | ||||
{% block content %} | {% block content %} | ||||
{{ entity.instance.getUserInfosTicket() }} | |||||
{{ ticket.getUserInfosTicket() }} | |||||
{% endblock %} | {% endblock %} | ||||
{% endembed %} | {% endembed %} | ||||
{{ macro.infobox('Date',entity.instance.createdAt|date('d/m/Y'), "yellow", "fa fa-calendar") }} | |||||
{{ macro.infobox('Catégorie',entity.instance.getTypeLabel()|trans({},'admin'), "green", "fa fa-archive") }} | |||||
{{ macro.infobox('Date',ticket.createdAt|date('d/m/Y'), "yellow", "fa fa-calendar") }} | |||||
{{ macro.infobox('Catégorie',ticket.getTypeLabel()|trans({},'admin'), "green", "fa fa-archive") }} | |||||
</div> | </div> | ||||
<div class="col-8"> | <div class="col-8"> | ||||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | {% embed '@LcSov/adminlte/embed/card.html.twig' %} | ||||
{% block body_wrapper %} | {% block body_wrapper %} | ||||
<div class="card-body row"> | <div class="card-body row"> | ||||
<div class="col-12 direct-chat-primary"> | <div class="col-12 direct-chat-primary"> | ||||
{% for message in entity.instance.ticketMessages %} | |||||
{% for message in ticket.ticketMessages %} | |||||
<div class="direct-chat-msg {{ message.answerByAdmin ? 'right' }}"> | <div class="direct-chat-msg {{ message.answerByAdmin ? 'right' }}"> | ||||
<div class="direct-chat-infos clearfix"> | <div class="direct-chat-infos clearfix"> | ||||
<div class="direct-chat-name {{ message.answerByAdmin ? 'float-right' : 'float-left' }}"> | <div class="direct-chat-name {{ message.answerByAdmin ? 'float-right' : 'float-left' }}"> |
public function transField($fieldName, $entityClass): string | public function transField($fieldName, $entityClass): string | ||||
{ | { | ||||
return $this->transEntityThenDefault( | return $this->transEntityThenDefault( | ||||
$this->buildTransIdField($fieldName, $entityClass), | |||||
$this->buildTransIdField($fieldName, $entityClass, true) | |||||
$this->buildTransIdField($fieldName, $entityClass), | |||||
$this->buildTransIdField($fieldName, $entityClass, true) | |||||
); | ); | ||||
} | } | ||||
public function transChoices($choices, $entityClass): array | |||||
{ | |||||
$newChoices = []; | |||||
foreach ($choices as $key => $choice) { | |||||
$newChoices[$this->trans($key)] = $choice; | |||||
} | |||||
return $newChoices; | |||||
} | |||||
public function transHelp($fieldName, $entityClass): string | public function transHelp($fieldName, $entityClass): string | ||||
{ | { | ||||
$fieldName = $fieldName . '_help'; | $fieldName = $fieldName . '_help'; | ||||
return $this->transEntityThenDefault( | return $this->transEntityThenDefault( | ||||
$this->buildTransIdField($fieldName, $entityClass), | |||||
$this->buildTransIdField($fieldName, $entityClass, true), | |||||
true | |||||
$this->buildTransIdField($fieldName, $entityClass), | |||||
$this->buildTransIdField($fieldName, $entityClass, true), | |||||
true | |||||
); | ); | ||||
} | } | ||||
public function transPanel($panelName, $entityClass): string | public function transPanel($panelName, $entityClass): string | ||||
{ | { | ||||
return $this->transEntityThenDefault( | return $this->transEntityThenDefault( | ||||
$this->buildTransIdPanel($panelName, $entityClass), | |||||
$this->buildTransIdPanel($panelName, $entityClass, true) | |||||
$this->buildTransIdPanel($panelName, $entityClass), | |||||
$this->buildTransIdPanel($panelName, $entityClass, true) | |||||
); | ); | ||||
} | } | ||||
if ($entityName) { | if ($entityName) { | ||||
$baseIdEntityLabel = 'entity.' . $entityName; | $baseIdEntityLabel = 'entity.' . $entityName; | ||||
$paramsTranslation = [ | $paramsTranslation = [ | ||||
'%label%' => $this->trans($baseIdEntityLabel . '.label'), | |||||
'%label_plurial%' => $this->trans($baseIdEntityLabel . '.label_plurial'), | |||||
'%label%' => $this->trans($baseIdEntityLabel . '.label'), | |||||
'%label_plurial%' => $this->trans($baseIdEntityLabel . '.label_plurial'), | |||||
]; | ]; | ||||
} | } | ||||
} | } | ||||
return $this->trans( | return $this->trans( | ||||
'title.' . $pageName, | |||||
$paramsTranslation | |||||
'title.' . $pageName, | |||||
$paramsTranslation | |||||
); | ); | ||||
} | } | ||||