Browse Source

Admin : correctifs divers

develop
Guillaume 2 years ago
parent
commit
3194064292
16 changed files with 321 additions and 136 deletions
  1. +9
    -0
      Container/Ticket/TicketContainer.php
  2. +26
    -89
      Controller/Ticket/TicketAdminController.php
  3. +2
    -1
      Definition/Field/Site/NewsFieldDefinition.php
  4. +101
    -0
      Definition/Field/Ticket/TicketFieldDefinition.php
  5. +0
    -17
      Definition/SiteSettingDefinition.php
  6. +0
    -1
      EventSubscriber/SiteSettingEventSubscriber.php
  7. +38
    -0
      Field/Filter/Ticket/EmailFilter.php
  8. +38
    -0
      Field/Filter/Ticket/FirstnameFilter.php
  9. +38
    -0
      Field/Filter/Ticket/LastnameFilter.php
  10. +5
    -5
      Form/Ticket/TicketFormType.php
  11. +9
    -10
      Form/Ticket/TicketMessageType.php
  12. +1
    -2
      Model/Ticket/TicketMessageModel.php
  13. +0
    -2
      Model/Ticket/TicketModel.php
  14. +39
    -0
      Repository/Ticket/TicketRepositoryQuery.php
  15. +3
    -2
      Resources/translations/admin.fr.yaml
  16. +12
    -7
      Resources/views/admin/ticket/field/lastmessage.html.twig

+ 9
- 0
Container/Ticket/TicketContainer.php View File

namespace Lc\SovBundle\Container\Ticket; namespace Lc\SovBundle\Container\Ticket;


use Lc\SovBundle\Builder\Ticket\TicketBuilder; use Lc\SovBundle\Builder\Ticket\TicketBuilder;
use Lc\SovBundle\Definition\Field\Ticket\TicketFieldDefinition;
use Lc\SovBundle\Factory\Ticket\TicketFactory; use Lc\SovBundle\Factory\Ticket\TicketFactory;
use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery; use Lc\SovBundle\Repository\Ticket\TicketRepositoryQuery;
use Lc\SovBundle\Repository\Ticket\TicketStore; use Lc\SovBundle\Repository\Ticket\TicketStore;
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;


public function __construct( public function __construct(
TicketBuilder $builder, TicketBuilder $builder,
TicketRepositoryQuery $repositoryQuery, TicketRepositoryQuery $repositoryQuery,
TicketStore $store, TicketStore $store,
TicketFieldDefinition $fieldDefinition,
TicketSolver $solver TicketSolver $solver
) { ) {
$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;
} }


return $this->store; return $this->store;
} }


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

public function getSolver(): TicketSolver public function getSolver(): TicketSolver
{ {
return $this->solver; return $this->solver;

+ 26
- 89
Controller/Ticket/TicketAdminController.php View File

abstract class TicketAdminController extends AbstractAdminController abstract class TicketAdminController extends AbstractAdminController
{ {


public function getRepositoryQuery() :RepositoryQueryInterface
public function getRepositoryQuery(): RepositoryQueryInterface
{ {
return $this->getTicketContainer()->getRepositoryQuery(); return $this->getTicketContainer()->getRepositoryQuery();
} }
return $this->getTicketContainer()->getFactory()->create(); return $this->getTicketContainer()->getFactory()->create();
} }


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

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


public function configureFields(string $pageName): iterable
{
$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 public function configureActions(Actions $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); 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) public function detail(AdminContext $context)
{ {
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); $adminUrlGenerator = $this->get(AdminUrlGenerator::class);
$ticket = $context->getEntity()->getInstance(); $ticket = $context->getEntity()->getInstance();


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


$formTicketStatus = $this->createForm( $formTicketStatus = $this->createForm(
TicketStatusType::class,
$ticket,
[
'action' => $url,
'method' => 'POST',
]
TicketStatusType::class,
$ticket,
[
'action' => $url,
'method' => 'POST',
]
); );


$ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket); $ticketMessage = $this->get(TicketMessageContainer::class)->getFactory()->create($ticket);
} }


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




public function ticketStatusAction() public function ticketStatusAction()
{ {
$request = $this->get('request')->getMasterRequest();
$entityManager = $this->getEntityManager();
$request = $this->getRequestStack()->getMainRequest();
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance(); $ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance();


$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); $formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket);


$success = false; $success = false;
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) {
$this->get('em')->persist($ticket);
$this->get('em')->flush();
$entityManager->persist($ticket);
$entityManager->flush();
$success = true; $success = true;
} }



+ 2
- 1
Definition/Field/Site/NewsFieldDefinition.php View File

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 Lc\SovBundle\Field\CKEditorField;
use Lc\SovBundle\Field\ImageManagerField; use Lc\SovBundle\Field\ImageManagerField;


class NewsFieldDefinition extends AbstractFieldDefinition class NewsFieldDefinition extends AbstractFieldDefinition
'newsletter' => AssociationField::new('newsletter')->setSortable(true), 'newsletter' => AssociationField::new('newsletter')->setSortable(true),
'image' => ImageManagerField::new('image'), 'image' => ImageManagerField::new('image'),
'position' => NumberField::new('position'), 'position' => NumberField::new('position'),
'description' => TextEditorField::new('description'),
'description' => CKEditorField::new('description'),
'isSent' => BooleanField::new('isSent')->setSortable(true), 'isSent' => BooleanField::new('isSent')->setSortable(true),
]; ];
} }

+ 101
- 0
Definition/Field/Ticket/TicketFieldDefinition.php View File

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

}

+ 0
- 17
Definition/SiteSettingDefinition.php View File

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


// email
$this->addSettingText(
[
'category' => self::CATEGORY_EMAIL,
'name' => self::SETTING_EMAIL_FROM,
]
);

$this->addSettingText(
[
'category' => self::CATEGORY_EMAIL,
'name' => self::SETTING_EMAIL_FROM_NAME,
]
);
} }


public function getCategories() public function getCategories()
{ {
return [ return [
self::CATEGORY_GENERAL, self::CATEGORY_GENERAL,
self::CATEGORY_EMAIL
]; ];
} }



+ 0
- 1
EventSubscriber/SiteSettingEventSubscriber.php View File

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

} }

+ 38
- 0
Field/Filter/Ticket/EmailFilter.php View File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\AssociationFilter;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class 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);
}
}

}

+ 38
- 0
Field/Filter/Ticket/FirstnameFilter.php View File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\AssociationFilter;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class 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);
}
}

}

+ 38
- 0
Field/Filter/Ticket/LastnameFilter.php View File

<?php

namespace Lc\SovBundle\Field\Filter\Ticket;

use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\AssociationFilter;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class 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);
}
}

}

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

] ]
); );


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

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


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

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

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



namespace Lc\SovBundle\Form\Ticket; namespace Lc\SovBundle\Form\Ticket;


use App\Entity\Address;
use App\Entity\OrderShop;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Lc\ShopBundle\Model\Ticket;
use Lc\ShopBundle\Services\UtilsManager;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Lc\SovBundle\Model\Ticket\TicketMessageInterface;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\File;


class TicketMessageType extends AbstractType class TicketMessageType extends AbstractType
{ {
protected EntityManagerInterface $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}


public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
'label' => 'entity.TicketMessage.fields.closeTicket', 'label' => 'entity.TicketMessage.fields.closeTicket',
'translation_domain' => 'admin', 'translation_domain' => 'admin',
'required' => false, 'required' => false,
'mapped' => false,
]); ]);
} }


public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)
{ {
$resolver->setDefaults([ $resolver->setDefaults([
// Configure your form options here
'data_class' => $this->entityManager->getEntityName(TicketMessageInterface::class),
]); ]);
} }
} }

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

{ {
use StatusTrait; use StatusTrait;



/** /**
* @ORM\Column(type="text") * @ORM\Column(type="text")
*/ */


public function __toString() public function __toString()
{ {
return $this->message;
return ''.$this->message;
} }


public function getMessage(): ?string public function getMessage(): ?string

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

return $this; return $this;
} }



public function getStatus(): ?string public function getStatus(): ?string
{ {
return $this->status; return $this->status;
return $this; return $this;
} }



public function getSubject(): ?string public function getSubject(): ?string
{ {
return $this->subject; return $this->subject;

+ 39
- 0
Repository/Ticket/TicketRepositoryQuery.php View File



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

public function __construct(TicketRepository $repository, PaginatorInterface $paginator) public function __construct(TicketRepository $repository, PaginatorInterface $paginator)
{ {
parent::__construct($repository, 'r', $paginator); parent::__construct($repository, 'r', $paginator);
->setParameter('status', $statusArray); ->setParameter('status', $statusArray);
} }


public function filterByFirstname(string $firstname)
{
$this->joinUser();

return $this
->andWhere('.visitorFirstname LIKE :firstname OR u.firstname LIKE :firstname')
->setParameter('firstname', '%'.$firstname.'%');
}

public function filterByLastname(string $lastname)
{
$this->joinUser();

return $this
->andWhere('.visitorLastname LIKE :lastname OR u.lastname LIKE :lastname')
->setParameter('lastname', '%'.$lastname.'%');
}

public function filterByEmail(string $email)
{
$this->joinUser();

return $this
->andWhere('.visitorEmail LIKE :email OR u.email LIKE :email')
->setParameter('email', '%'.$email.'%');
}

public function selectCount(): self public function selectCount(): self
{ {
return $this return $this
->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;
}
} }

+ 3
- 2
Resources/translations/admin.fr.yaml View File

label: Ticket label: Ticket
label_plurial: Tickets label_plurial: Tickets
fields: fields:
visitorFirstName: Nom
visitorLastName: Prénom
visitorFirstname: Nom
visitorLastname: Prénom
visitorEmail: E-mail visitorEmail: E-mail
subject: Sujet subject: Sujet
type: Type type: Type
open: Ouvert open: Ouvert
being-processed: En attente being-processed: En attente
closed: Fermé closed: Fermé
ticketMessages: Message
TicketModel: TicketModel:
fields: fields:
open: Ouvert open: Ouvert

+ 12
- 7
Resources/views/admin/ticket/field/lastmessage.html.twig View File

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

Loading…
Cancel
Save