Sfoglia il codice sorgente

Admin : correctifs divers

develop
Guillaume 3 anni fa
parent
commit
3194064292
16 ha cambiato i file con 321 aggiunte e 136 eliminazioni
  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 Vedi File

@@ -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;

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

@@ -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;
}


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

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

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

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

}

+ 0
- 17
Definition/SiteSettingDefinition.php Vedi File

@@ -35,29 +35,12 @@ class SiteSettingDefinition extends AbstractSettingDefinition implements SiteSet
'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()
{
return [
self::CATEGORY_GENERAL,
self::CATEGORY_EMAIL
];
}


+ 0
- 1
EventSubscriber/SiteSettingEventSubscriber.php Vedi File

@@ -105,5 +105,4 @@ class SiteSettingEventSubscriber implements EventSubscriberInterface
{
return $this->siteStore->getOneByDevAlias('default');
}

}

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

@@ -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);
}
}

}

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

@@ -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);
}
}

}

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

@@ -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);
}
}

}

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

@@ -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,

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

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

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

@@ -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

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

@@ -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;

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

@@ -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;
}
}

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

@@ -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

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

@@ -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 %}

Loading…
Annulla
Salva