Browse Source

Merge branch 'develop' of https://forge.laclic.fr/Laclic/SovBundle into develop

ideas
Guillaume 3 years ago
parent
commit
528b114b98
13 changed files with 250 additions and 139 deletions
  1. +94
    -38
      Controller/Ticket/TicketAdminController.php
  2. +1
    -1
      Factory/Ticket/TicketFactory.php
  3. +8
    -0
      Factory/Ticket/TicketFactoryInterface.php
  4. +1
    -12
      Form/Ticket/TicketFormType.php
  5. +52
    -0
      Form/Ticket/TicketMessageFormType.php
  6. +10
    -11
      Form/Ticket/TicketStatusType.php
  7. +0
    -59
      Form/Ticket/TicketTypeType.php
  8. +18
    -1
      Model/Ticket/TicketModel.php
  9. +1
    -0
      Resources/assets/app/adminlte/ticket/app.ticket.js
  10. +17
    -0
      Resources/assets/app/adminlte/ticket/ticket.js
  11. +8
    -0
      Resources/translations/admin.fr.yaml
  12. +19
    -6
      Resources/views/admin/ticket/detail.html.twig
  13. +21
    -11
      Translation/TranslatorAdmin.php

+ 94
- 38
Controller/Ticket/TicketAdminController.php View File

@@ -2,44 +2,42 @@

namespace Lc\SovBundle\Controller\Ticket;

use App\Entity\Ticket\Ticket;
use App\Entity\Ticket\TicketMessage;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException;
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException;
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
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\Router\AdminUrlGenerator;
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission;
use Lc\SovBundle\Factory\Ticket\TicketFactory;
use Lc\SovBundle\Field\StatusField;
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface;
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory;
use Lc\SovBundle\Form\Ticket\TicketFormType;
use Lc\SovBundle\Form\Ticket\TicketMessageFormType;
use Lc\SovBundle\Form\Ticket\TicketStatusType;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Controller\AbstractAdminController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Lc\SovBundle\Model\Ticket\TicketModel;
use Symfony\Component\HttpFoundation\JsonResponse;

class TicketAdminController extends AbstractAdminController
{
protected $ticketFactory;
protected $ticketMessageFactory;
protected $adminUrlGenerator;
protected $em;

public function __construct(TicketFactory $ticketFactory)
{
public function __construct(
TicketFactoryInterface $ticketFactory,
TicketMessageFactory $ticketMessageFactory,
AdminUrlGenerator $adminUrlGenerator
) {
$this->ticketFactory = $ticketFactory;
$this->ticketMessageFactory = $ticketMessageFactory;
$this->adminUrlGenerator = $adminUrlGenerator;
}

public static function getEntityFqcn(): string
@@ -47,6 +45,15 @@ class TicketAdminController extends AbstractAdminController
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
{
return [
@@ -69,38 +76,24 @@ class TicketAdminController extends AbstractAdminController
ChoiceField::new('type')
->autocomplete()
->setChoices(
[
'entity.Ticket.fields.typeOptions.' . Ticket::TYPE_GENERAL_QUESTION => Ticket::TYPE_GENERAL_QUESTION,
'entity.Ticket.fields.typeOptions.' . Ticket::TYPE_TECHNICAL_PROBLEM => Ticket::TYPE_TECHNICAL_PROBLEM,
]
TicketModel::getChoicesType()
),
ChoiceField::new('status')
->autocomplete()
->setChoices(
[
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_OPEN => Ticket::TICKET_STATUS_OPEN,
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_BEING_PROCESSED => Ticket::TICKET_STATUS_BEING_PROCESSED,
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_CLOSED => Ticket::TICKET_STATUS_CLOSED,
]
TicketModel::getChoicesStatus()
)
->setTemplatePath('@LcSov/admin/ticket/index_status.html.twig')
->hideOnForm(),
];
}

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
{
$actions
->add(Crud::PAGE_INDEX, Action::DETAIL)
->remove(Crud::PAGE_INDEX, Action::EDIT);

return parent::configureActions($actions);
}

@@ -113,14 +106,18 @@ class TicketAdminController extends AbstractAdminController
if ($form->isSubmitted() && $form->isValid()) {
$ticket = $form->getData();

foreach($ticket->getTicketMessages() as $ticketMessage){
foreach ($ticket->getTicketMessages() as $ticketMessage) {
$this->get('em')->persist($ticketMessage);
}

$this->get('em')->persist($ticket);
$this->get('em')->flush();

return $this->redirectToRoute('admin_dashboard');
$url = $this->adminUrlGenerator
->setAction('index')
->generateUrl();

return $this->redirect($url);
}

return $this->render(
@@ -130,4 +127,63 @@ class TicketAdminController extends AbstractAdminController
]
);
}

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

$ticketMessage = $this->ticketMessageFactory->create();
$formAddTicketMessage = $this->createForm(TicketMessageFormType::class, $ticketMessage);
$formAddTicketMessage->handleRequest($this->get('request')->getMainRequest());

if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) {
$ticketMessage = $formAddTicketMessage->getData();
$ticketMessage->setTicket($ticket);
$ticketMessage->setAnswerByAdmin(true);
$this->get('em')->persist($ticketMessage);
$this->get('em')->flush();
}

return $this->render(
'@LcSov/admin/ticket/detail.html.twig',
[
'form_ticket_status' => $formTicketStatus->createView(),
'form_add_ticket_message' => $formAddTicketMessage->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]);
}

}

+ 1
- 1
Factory/Ticket/TicketFactory.php View File

@@ -7,7 +7,7 @@ use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Factory\AbstractFactory;
use Lc\SovBundle\Model\Ticket\TicketInterface;

class TicketFactory extends AbstractFactory
class TicketFactory extends AbstractFactory implements TicketFactoryInterface
{
protected $ticketMessageFactory;


+ 8
- 0
Factory/Ticket/TicketFactoryInterface.php View File

@@ -0,0 +1,8 @@
<?php

namespace Lc\SovBundle\Factory\Ticket;

interface TicketFactoryInterface
{

}

+ 1
- 12
Form/Ticket/TicketFormType.php View File

@@ -2,7 +2,6 @@

namespace Lc\SovBundle\Form\Ticket;

use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Model\Ticket\TicketModel;
@@ -19,7 +18,6 @@ use Symfony\Component\OptionsResolver\OptionsResolver;

class TicketFormType extends AbstractType
{

protected $em;
protected $translatorAdmin;

@@ -51,16 +49,7 @@ class TicketFormType extends AbstractType
ChoiceType::class,
[
'label' => 'Type',
'choices' => [
$this->translatorAdmin->transField(
'typeOptions.' . TicketModel::TYPE_TECHNICAL_PROBLEM,
$entityName
) => TicketModel::TYPE_TECHNICAL_PROBLEM,
$this->translatorAdmin->transField(
'typeOptions.' . TicketModel::TYPE_GENERAL_QUESTION,
$entityName
) => TicketModel::TYPE_TECHNICAL_PROBLEM,
],
'choices' => $this->translatorAdmin->transChoices($entityName::getChoicesType(),TicketInterface::class),
]
);


+ 52
- 0
Form/Ticket/TicketMessageFormType.php View File

@@ -0,0 +1,52 @@
<?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 TicketMessageFormType 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
]
);

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

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

+ 10
- 11
Form/Ticket/TicketStatusType.php View File

@@ -3,6 +3,7 @@
namespace Lc\SovBundle\Form\Ticket;

use Doctrine\ORM\EntityManagerInterface;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
@@ -13,11 +14,13 @@ use Lc\SovBundle\Model\Ticket\TicketModel;
class TicketStatusType extends AbstractType
{
protected $em;
protected $translatorAdmin;


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

public function buildForm(FormBuilderInterface $builder, array $options)
@@ -25,15 +28,12 @@ class TicketStatusType extends AbstractType
$builder->add(
'status',
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,
'expanded' => true
)
'expanded' => true,
'label' => false,
]
);
}

@@ -41,8 +41,7 @@ class TicketStatusType extends AbstractType
{
$resolver->setDefaults(
[
'data_class' => $this->em->getClassMetadata(TicketInterface::class)->getName(),
'translation_domain' => 'lcshop'
'data_class' => $this->em->getEntityName(TicketInterface::class),
]
);
}

+ 0
- 59
Form/Ticket/TicketTypeType.php View File

@@ -1,59 +0,0 @@
<?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'
]
);
}
}

+ 18
- 1
Model/Ticket/TicketModel.php View File

@@ -149,6 +149,14 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac
return 'entity.Ticket.fields.typeOptions.' . $this->getType();
}

public function getChoicesType(): array
{
return [
'entity.Ticket.fields.typeOptions.' . TicketModel::TYPE_GENERAL_QUESTION => TicketModel::TYPE_GENERAL_QUESTION,
'entity.Ticket.fields.typeOptions.' . TicketModel::TYPE_TECHNICAL_PROBLEM => TicketModel::TYPE_TECHNICAL_PROBLEM,
];
}

public function getStatus(): ?string
{
return $this->status;
@@ -163,7 +171,16 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac

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

+ 1
- 0
Resources/assets/app/adminlte/ticket/app.ticket.js View File

@@ -0,0 +1 @@
import './ticket.js'

+ 17
- 0
Resources/assets/app/adminlte/ticket/ticket.js View File

@@ -0,0 +1,17 @@
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.');
}
}
});
});
});

+ 8
- 0
Resources/translations/admin.fr.yaml View File

@@ -31,6 +31,7 @@ action:
delete: Supprimer
change: Changer
detail: Voir
send: Envoyer
index_children: Afficher les enfants
index_parent: Retour au parent
back_index: Retour à la liste
@@ -78,11 +79,18 @@ entity:
typeOptions:
general-question: Questions générales
technical-problem: Problème technique
product-unavailable: Produit manquant
product-error: Erreur sur un produit
lastMessage: Dernier message
statusOptions:
open: Ouvert
being-processed: En attente
closed: Fermé
TicketModel:
fields:
open: Ouvert
being-processed: En attente
closed: Fermé
TicketMessage:
fields:
message: Votre réponse

+ 19
- 6
Resources/views/admin/ticket/detail.html.twig View File

@@ -6,7 +6,6 @@
{% endblock %}

{% block main %}
{{ dump() }}
<div class="row">
<div class="col-4">
{% embed '@LcSov/adminlte/embed/infobox.html.twig' %}
@@ -14,7 +13,12 @@
{% block icon %}fa fa-toggle-on{% endblock %}
{% block title %}Status{% endblock %}
{% 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 %}
{% endembed %}

@@ -23,12 +27,12 @@
{% block icon %}fa fa-user{% endblock %}
{% block title %}Utilisateur{% endblock %}
{% block content %}
{{ entity.instance.getUserInfosTicket() }}
{{ ticket.getUserInfosTicket() }}
{% endblock %}
{% 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 class="col-8">
{% embed '@LcSov/adminlte/embed/card.html.twig' %}
@@ -42,7 +46,7 @@
{% block body_wrapper %}
<div class="card-body row">
<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-infos clearfix">
<div class="direct-chat-name {{ message.answerByAdmin ? 'float-right' : 'float-left' }}">
@@ -75,6 +79,15 @@
</div>
{% endfor %}
</div>
<hr />
{{ form_start(form_add_ticket_message, {"attr" : {"class" : 'col-12', 'id' : 'addTicketMessageForm'}}) }}
{% form_theme form_add_ticket_message '@LcSov/adminlte/crud/form_theme.html.twig' %}
<div class="row">
<div class="col-12">
{{ form_row(form_add_ticket_message.message) }}
</div>
</div>
{{ form_end(form_add_ticket_message) }}
</div>
{% endblock %}
{% endembed %}

+ 21
- 11
Translation/TranslatorAdmin.php View File

@@ -34,27 +34,37 @@ class TranslatorAdmin
public function transField($fieldName, $entityClass): string
{
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
{
$fieldName = $fieldName . '_help';

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
{
return $this->transEntityThenDefault(
$this->buildTransIdPanel($panelName, $entityClass),
$this->buildTransIdPanel($panelName, $entityClass, true)
$this->buildTransIdPanel($panelName, $entityClass),
$this->buildTransIdPanel($panelName, $entityClass, true)
);
}

@@ -67,8 +77,8 @@ class TranslatorAdmin
if ($entityName) {
$baseIdEntityLabel = 'entity.' . $entityName;
$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'),
];
}

@@ -77,8 +87,8 @@ class TranslatorAdmin
}

return $this->trans(
'title.' . $pageName,
$paramsTranslation
'title.' . $pageName,
$paramsTranslation
);
}


Loading…
Cancel
Save