@@ -3,6 +3,7 @@ | |||
namespace Lc\SovBundle\Container\Ticket; | |||
use Lc\SovBundle\Builder\Ticket\TicketBuilder; | |||
use Lc\SovBundle\Definition\Field\Ticket\TicketFieldDefinition; | |||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | |||
use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery; | |||
use Lc\SovBundle\Repository\Ticket\TicketStore; | |||
@@ -14,6 +15,7 @@ class TicketContainer | |||
protected TicketBuilder $builder; | |||
protected TicketRepositoryQuery $repositoryQuery; | |||
protected TicketStore $store; | |||
protected TicketFieldDefinition $fieldDefinition; | |||
protected TicketSolver $solver; | |||
public function __construct( | |||
@@ -21,12 +23,14 @@ class TicketContainer | |||
TicketBuilder $builder, | |||
TicketRepositoryQuery $repositoryQuery, | |||
TicketStore $store, | |||
TicketFieldDefinition $fieldDefinition, | |||
TicketSolver $solver | |||
) { | |||
$this->factory = $factory; | |||
$this->builder = $builder; | |||
$this->repositoryQuery = $repositoryQuery; | |||
$this->store = $store; | |||
$this->fieldDefinition = $fieldDefinition; | |||
$this->solver = $solver; | |||
} | |||
@@ -50,6 +54,11 @@ class TicketContainer | |||
return $this->store; | |||
} | |||
public function getFieldDefinition(): TicketFieldDefinition | |||
{ | |||
return $this->fieldDefinition; | |||
} | |||
public function getSolver(): TicketSolver | |||
{ | |||
return $this->solver; |
@@ -35,7 +35,7 @@ use Symfony\Component\HttpFoundation\RequestStack; | |||
abstract class TicketAdminController extends AbstractAdminController | |||
{ | |||
public function getRepositoryQuery() :RepositoryQueryInterface | |||
public function getRepositoryQuery(): RepositoryQueryInterface | |||
{ | |||
return $this->getTicketContainer()->getRepositoryQuery(); | |||
} | |||
@@ -45,6 +45,11 @@ abstract class TicketAdminController extends AbstractAdminController | |||
return $this->getTicketContainer()->getFactory()->create(); | |||
} | |||
public function configureFields(string $pageName): iterable | |||
{ | |||
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName); | |||
} | |||
public function configureAssets(Assets $assets): Assets | |||
{ | |||
$assets = parent::configureAssets($assets); | |||
@@ -54,100 +59,31 @@ abstract class TicketAdminController extends AbstractAdminController | |||
return $assets; | |||
} | |||
public function configureFields(string $pageName): iterable | |||
{ | |||
$translatorAdmin = $this->get(TranslatorAdmin::class); | |||
return [ | |||
IntegerField::new('id') | |||
->hideOnForm(), | |||
DateField::new('createdAt')->setFormat('short') | |||
->hideOnForm(), | |||
TextField::new('visitorFirstname') | |||
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | |||
->hideOnForm(), | |||
TextField::new('visitorLastname') | |||
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig') | |||
->hideOnForm(), | |||
TextField::new('visitorEmail') | |||
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | |||
->hideOnForm(), | |||
AssociationField::new('user') | |||
->hideOnIndex(), | |||
TextField::new('subject'), | |||
TextField::new('lastMessage') | |||
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig') | |||
->hideOnForm(), | |||
ChoiceField::new('type') | |||
->autocomplete() | |||
->setChoices( | |||
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getTypeChoices(), 'Ticket', 'type') | |||
), | |||
ChoiceField::new('status') | |||
->autocomplete() | |||
->setChoices( | |||
$translatorAdmin->transChoices($this->get(TicketContainer::class)->getSolver()->getStatusChoices(), 'Ticket', 'status') | |||
) | |||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig') | |||
->hideOnForm(), | |||
]; | |||
} | |||
public function configureActions(Actions $actions): Actions | |||
{ | |||
$actions | |||
->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL) | |||
->remove(Crud::PAGE_INDEX, ActionDefinition::EDIT); | |||
->add(Crud::PAGE_INDEX, ActionDefinition::DETAIL) | |||
->remove(Crud::PAGE_INDEX, ActionDefinition::EDIT); | |||
return parent::configureActions($actions); | |||
} | |||
public function new(AdminContext $context) | |||
{ | |||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | |||
$ticket = $this->createEntity($context->getEntity()->getFqcn()); | |||
$form = $this->createForm(TicketFormType::class, $ticket); | |||
$form->handleRequest($context->getRequest()); | |||
if ($form->isSubmitted() && $form->isValid()) { | |||
$ticket = $form->getData(); | |||
$this->get(EntityManagerInterface::class)->create($ticket); | |||
$this->get(EntityManagerInterface::class)->flush(); | |||
$url = $adminUrlGenerator | |||
->setAction('index') | |||
->generateUrl(); | |||
return $this->redirect($url); | |||
} | |||
return $this->render( | |||
'@LcSov/admin/ticket/new.html.twig', | |||
[ | |||
'form' => $form->createView(), | |||
] | |||
); | |||
} | |||
public function detail(AdminContext $context) | |||
{ | |||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | |||
$ticket = $context->getEntity()->getInstance(); | |||
$url = $adminUrlGenerator | |||
->setAction('ticketStatusAction') | |||
->generateUrl(); | |||
->setAction('ticketStatusAction') | |||
->generateUrl(); | |||
$formTicketStatus = $this->createForm( | |||
TicketStatusType::class, | |||
$ticket, | |||
[ | |||
'action' => $url, | |||
'method' => 'POST', | |||
] | |||
TicketStatusType::class, | |||
$ticket, | |||
[ | |||
'action' => $url, | |||
'method' => 'POST', | |||
] | |||
); | |||
$ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); | |||
@@ -163,19 +99,20 @@ abstract class TicketAdminController extends AbstractAdminController | |||
} | |||
return $this->render( | |||
'@LcSov/admin/ticket/detail.html.twig', | |||
[ | |||
'form_ticket_status' => $formTicketStatus->createView(), | |||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||
'ticket' => $ticket, | |||
] | |||
'@LcSov/admin/ticket/detail.html.twig', | |||
[ | |||
'form_ticket_status' => $formTicketStatus->createView(), | |||
'form_add_ticket_message' => $formAddTicketMessage->createView(), | |||
'ticket' => $ticket, | |||
] | |||
); | |||
} | |||
public function ticketStatusAction() | |||
{ | |||
$request = $this->get('request')->getMasterRequest(); | |||
$entityManager = $this->getEntityManager(); | |||
$request = $this->getRequestStack()->getMainRequest(); | |||
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance(); | |||
$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); | |||
@@ -183,8 +120,8 @@ abstract class TicketAdminController extends AbstractAdminController | |||
$success = false; | |||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | |||
$this->get('em')->persist($ticket); | |||
$this->get('em')->flush(); | |||
$entityManager->persist($ticket); | |||
$entityManager->flush(); | |||
$success = true; | |||
} | |||
@@ -9,6 +9,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | |||
use Lc\SovBundle\Field\BooleanField; | |||
use Lc\SovBundle\Field\CKEditorField; | |||
use Lc\SovBundle\Field\ImageManagerField; | |||
class NewsFieldDefinition extends AbstractFieldDefinition | |||
@@ -50,7 +51,7 @@ class NewsFieldDefinition extends AbstractFieldDefinition | |||
'newsletter' => AssociationField::new('newsletter')->setSortable(true), | |||
'image' => ImageManagerField::new('image'), | |||
'position' => NumberField::new('position'), | |||
'description' => TextEditorField::new('description'), | |||
'description' => CKEditorField::new('description'), | |||
'isSent' => BooleanField::new('isSent')->setSortable(true), | |||
]; | |||
} |
@@ -0,0 +1,101 @@ | |||
<?php | |||
namespace Lc\SovBundle\Definition\Field\Ticket; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||
use Lc\CaracoleBundle\Field\Filter\ProductCategoriesFilter; | |||
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition; | |||
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\Solver\Ticket\TicketSolver; | |||
use Lc\SovBundle\Translation\TranslatorAdmin; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
class TicketFieldDefinition extends AbstractFieldDefinition | |||
{ | |||
protected TicketSolver $ticketSolver; | |||
public function __construct(TranslatorAdmin $translatorAdmin, TicketSolver $ticketSolver) | |||
{ | |||
parent::__construct($translatorAdmin); | |||
$this->ticketSolver = $ticketSolver; | |||
} | |||
public function configureIndex(): array | |||
{ | |||
return [ | |||
'id', | |||
'createdAt', | |||
'lastname', | |||
'firstname', | |||
'email', | |||
'type', | |||
'subject', | |||
'lastMessage', | |||
'status' | |||
]; | |||
} | |||
public function configureForm(): array | |||
{ | |||
return [ | |||
'user', | |||
'type', | |||
'subject', | |||
'ticketMessages' | |||
]; | |||
} | |||
public function configureFields(): array | |||
{ | |||
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') | |||
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig') | |||
->setCustomOption('filter_fqcn', FirstnameFilter::class), | |||
'email' => TextField::new('email') | |||
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig') | |||
->setCustomOption('filter_fqcn', EmailFilter::class), | |||
'user' => AssociationField::new('user'), | |||
'type' => ChoiceField::new('type') | |||
->autocomplete() | |||
->setChoices( | |||
$this->translatorAdmin->transChoices( | |||
$this->ticketSolver->getTypeChoices(), | |||
'Ticket', | |||
'type' | |||
) | |||
), | |||
'subject' => TextField::new('subject'), | |||
'lastMessage' => TextField::new('lastMessage') | |||
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig'), | |||
'status' => ChoiceField::new('status') | |||
->autocomplete() | |||
->setChoices( | |||
$this->translatorAdmin->transChoices( | |||
$this->ticketSolver->getStatusChoices(), | |||
'Ticket', | |||
'status' | |||
) | |||
) | |||
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig'), | |||
'ticketMessages' => CollectionField::new('ticketMessages') | |||
->setFormTypeOption('entry_type', TicketMessageType::class) | |||
->setFormTypeOption('allow_add', false) | |||
]; | |||
} | |||
} |
@@ -35,29 +35,12 @@ class SiteSettingDefinition extends AbstractSettingDefinition implements SiteSet | |||
'name' => self::SETTING_MAINTENANCE_IP_AUTHORIZED, | |||
] | |||
); | |||
$this->addSettingText( | |||
[ | |||
'category' => self::CATEGORY_EMAIL, | |||
'name' => self::SETTING_EMAIL_FROM, | |||
] | |||
); | |||
$this->addSettingText( | |||
[ | |||
'category' => self::CATEGORY_EMAIL, | |||
'name' => self::SETTING_EMAIL_FROM_NAME, | |||
] | |||
); | |||
} | |||
public function getCategories() | |||
{ | |||
return [ | |||
self::CATEGORY_GENERAL, | |||
self::CATEGORY_EMAIL | |||
]; | |||
} | |||
@@ -105,5 +105,4 @@ class SiteSettingEventSubscriber implements EventSubscriberInterface | |||
{ | |||
return $this->siteStore->getOneByDevAlias('default'); | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
<?php | |||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
/** | |||
* @author La clic ! <contact@laclic.fr> | |||
*/ | |||
class EmailFilter extends AssociationFilter | |||
{ | |||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||
{ | |||
$builder->add( | |||
$fieldDto->getProperty(), | |||
TextType::class, | |||
array( | |||
'required' => false, | |||
'attr' => array( | |||
'class' => ' input-sm', | |||
'form' => 'filters-form', | |||
), | |||
) | |||
); | |||
} | |||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||
{ | |||
if ($filteredValue !== null) { | |||
$repositoryQuery->filterByEmail($filteredValue); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
<?php | |||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
/** | |||
* @author La clic ! <contact@laclic.fr> | |||
*/ | |||
class FirstnameFilter extends AssociationFilter | |||
{ | |||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||
{ | |||
$builder->add( | |||
$fieldDto->getProperty(), | |||
TextType::class, | |||
array( | |||
'required' => false, | |||
'attr' => array( | |||
'class' => ' input-sm', | |||
'form' => 'filters-form', | |||
), | |||
) | |||
); | |||
} | |||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||
{ | |||
if ($filteredValue !== null) { | |||
$repositoryQuery->filterByFirstname($filteredValue); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
<?php | |||
namespace Lc\SovBundle\Field\Filter\Ticket; | |||
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; | |||
use Lc\SovBundle\Field\Filter\AssociationFilter; | |||
use Lc\SovBundle\Repository\RepositoryQueryInterface; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
/** | |||
* @author La clic ! <contact@laclic.fr> | |||
*/ | |||
class LastnameFilter extends AssociationFilter | |||
{ | |||
public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array()) | |||
{ | |||
$builder->add( | |||
$fieldDto->getProperty(), | |||
TextType::class, | |||
array( | |||
'required' => false, | |||
'attr' => array( | |||
'class' => ' input-sm', | |||
'form' => 'filters-form', | |||
), | |||
) | |||
); | |||
} | |||
public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null) | |||
{ | |||
if ($filteredValue !== null) { | |||
$repositoryQuery->filterByLastname($filteredValue); | |||
} | |||
} | |||
} |
@@ -45,11 +45,6 @@ class TicketFormType extends AbstractType | |||
] | |||
); | |||
$builder->add( | |||
'subject', | |||
TextType::class | |||
); | |||
$builder->add( | |||
'type', | |||
ChoiceType::class, | |||
@@ -63,6 +58,11 @@ class TicketFormType extends AbstractType | |||
] | |||
); | |||
$builder->add( | |||
'subject', | |||
TextType::class | |||
); | |||
$builder->add( | |||
'ticketMessages', | |||
CollectionType::class, |
@@ -2,26 +2,24 @@ | |||
namespace Lc\SovBundle\Form\Ticket; | |||
use App\Entity\Address; | |||
use App\Entity\OrderShop; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\ShopBundle\Model\Ticket; | |||
use Lc\ShopBundle\Services\UtilsManager; | |||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
use Symfony\Component\Form\Extension\Core\Type\EmailType; | |||
use Symfony\Component\Form\Extension\Core\Type\FileType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
use Symfony\Component\Security\Core\Security; | |||
use Symfony\Component\Validator\Constraints\File; | |||
class TicketMessageType extends AbstractType | |||
{ | |||
protected EntityManagerInterface $entityManager; | |||
public function __construct(EntityManagerInterface $entityManager) | |||
{ | |||
$this->entityManager = $entityManager; | |||
} | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
@@ -51,13 +49,14 @@ class TicketMessageType extends AbstractType | |||
'label' => 'entity.TicketMessage.fields.closeTicket', | |||
'translation_domain' => 'admin', | |||
'required' => false, | |||
'mapped' => false, | |||
]); | |||
} | |||
public function configureOptions(OptionsResolver $resolver) | |||
{ | |||
$resolver->setDefaults([ | |||
// Configure your form options here | |||
'data_class' => $this->entityManager->getEntityName(TicketMessageInterface::class), | |||
]); | |||
} | |||
} |
@@ -17,7 +17,6 @@ abstract class TicketMessageModel extends AbstractLightEntity implements TicketM | |||
{ | |||
use StatusTrait; | |||
/** | |||
* @ORM\Column(type="text") | |||
*/ | |||
@@ -41,7 +40,7 @@ abstract class TicketMessageModel extends AbstractLightEntity implements TicketM | |||
public function __toString() | |||
{ | |||
return $this->message; | |||
return ''.$this->message; | |||
} | |||
public function getMessage(): ?string |
@@ -92,7 +92,6 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
return $this; | |||
} | |||
public function getStatus(): ?string | |||
{ | |||
return $this->status; | |||
@@ -105,7 +104,6 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
return $this; | |||
} | |||
public function getSubject(): ?string | |||
{ | |||
return $this->subject; |
@@ -8,6 +8,8 @@ use Lc\SovBundle\Repository\AbstractRepositoryQuery; | |||
class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | |||
{ | |||
protected bool $isJoinUser = false; | |||
public function __construct(TicketRepository $repository, PaginatorInterface $paginator) | |||
{ | |||
parent::__construct($repository, 'r', $paginator); | |||
@@ -27,9 +29,46 @@ class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRep | |||
->setParameter('status', $statusArray); | |||
} | |||
public function filterByFirstname(string $firstname) | |||
{ | |||
$this->joinUser(); | |||
return $this | |||
->andWhere('.visitorFirstname LIKE :firstname OR u.firstname LIKE :firstname') | |||
->setParameter('firstname', '%'.$firstname.'%'); | |||
} | |||
public function filterByLastname(string $lastname) | |||
{ | |||
$this->joinUser(); | |||
return $this | |||
->andWhere('.visitorLastname LIKE :lastname OR u.lastname LIKE :lastname') | |||
->setParameter('lastname', '%'.$lastname.'%'); | |||
} | |||
public function filterByEmail(string $email) | |||
{ | |||
$this->joinUser(); | |||
return $this | |||
->andWhere('.visitorEmail LIKE :email OR u.email LIKE :email') | |||
->setParameter('email', '%'.$email.'%'); | |||
} | |||
public function selectCount(): self | |||
{ | |||
return $this | |||
->select('count(r.id) as count'); | |||
} | |||
public function joinUser(): self | |||
{ | |||
if (!$this->isJoinUser) { | |||
$this->isJoinUser = true; | |||
return $this->leftJoin('.user', 'u'); | |||
} | |||
return $this; | |||
} | |||
} |
@@ -76,8 +76,8 @@ entity: | |||
label: Ticket | |||
label_plurial: Tickets | |||
fields: | |||
visitorFirstName: Nom | |||
visitorLastName: Prénom | |||
visitorFirstname: Nom | |||
visitorLastname: Prénom | |||
visitorEmail: E-mail | |||
subject: Sujet | |||
type: Type | |||
@@ -91,6 +91,7 @@ entity: | |||
open: Ouvert | |||
being-processed: En attente | |||
closed: Fermé | |||
ticketMessages: Message | |||
TicketModel: | |||
fields: | |||
open: Ouvert |
@@ -1,7 +1,12 @@ | |||
{#{% set ticketMessage = entity.instance.getLastMessage() %}#} | |||
{#{% if ticketMessage.answerByAdmin != true %}#} | |||
{# <span class="badge badge-danger">#} | |||
{# New#} | |||
{# </span>#} | |||
{#{% endif %}#} | |||
{#{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par {{ ticketMessage.createdBy }} {{ ticketMessage.message }}#} | |||
{% 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 %} |