Просмотр исходного кода

Finalisation tableau de bord + ticket

feature/symfony6.1
Fab 3 лет назад
Родитель
Сommit
69875a62d9
24 измененных файлов: 551 добавлений и 101 удалений
  1. +11
    -1
      Container/Ticket/TicketContainer.php
  2. +9
    -1
      Controller/AbstractAdminController.php
  3. +45
    -42
      Controller/Ticket/TicketAdminController.php
  4. +39
    -8
      Controller/User/UserAdminController.php
  5. +2
    -0
      Definition/ActionDefinition.php
  6. +2
    -2
      Definition/Field/Site/NewsFieldDefinition.php
  7. +106
    -0
      Definition/Field/Ticket/TicketFieldDefinition.php
  8. +1
    -14
      Field/Filter/ChoiceFilter.php
  9. +11
    -12
      Field/Filter/FilterManager.php
  10. +3
    -3
      Field/Filter/FilterTrait.php
  11. +48
    -0
      Field/Filter/Ticket/EmailTicketFilter.php
  12. +48
    -0
      Field/Filter/Ticket/FirstnameTicketFilter.php
  13. +48
    -0
      Field/Filter/Ticket/LastnameTicketFilter.php
  14. +93
    -0
      Form/Ticket/TicketAdminFormType.php
  15. +3
    -6
      Form/Ticket/TicketFormType.php
  16. +45
    -0
      Form/Ticket/TicketMessageAdminType.php
  17. +1
    -0
      Model/Ticket/TicketModel.php
  18. +14
    -0
      Repository/Ticket/TicketRepositoryQuery.php
  19. +1
    -1
      Resources/translations/admin.fr.yaml
  20. +10
    -7
      Resources/views/admin/ticket/field/lastmessage.html.twig
  21. +2
    -0
      Resources/views/admin/ticket/field/status.html.twig
  22. +1
    -1
      Resources/views/admin/ticket/macro.html.twig
  23. +5
    -1
      Resources/views/adminlte/macro/badge.html.twig
  24. +3
    -2
      Solver/Ticket/TicketSolver.php

+ 11
- 1
Container/Ticket/TicketContainer.php Просмотреть файл

@@ -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;
@@ -15,19 +16,22 @@ class TicketContainer
protected TicketRepositoryQuery $repositoryQuery;
protected TicketStore $store;
protected TicketSolver $solver;
protected TicketFieldDefinition $fieldDefinition;

public function __construct(
TicketFactory $factory,
TicketBuilder $builder,
TicketRepositoryQuery $repositoryQuery,
TicketStore $store,
TicketSolver $solver
TicketSolver $solver,
TicketFieldDefinition $fieldDefinition
) {
$this->factory = $factory;
$this->builder = $builder;
$this->repositoryQuery = $repositoryQuery;
$this->store = $store;
$this->solver = $solver;
$this->fieldDefinition = $fieldDefinition;
}

public function getFactory(): TicketFactory
@@ -54,4 +58,10 @@ class TicketContainer
{
return $this->solver;
}


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

+ 9
- 1
Controller/AbstractAdminController.php Просмотреть файл

@@ -62,6 +62,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController
use ControllerTrait;

protected FormInterface $filtersForm;
protected bool $isRepositoryQueryFiltered = false;

abstract public function getRepositoryQuery(): RepositoryQueryInterface;

@@ -332,6 +333,13 @@ abstract class AbstractAdminController extends EaAbstractCrudController
return $this->redirect($url);
}

public function isRepositoryQueryFiltered():bool{
if(($this->filtersForm && $this->filtersForm->isSubmitted()) || $this->isRepositoryQueryFiltered){
return true;
}else{
return false;
}
}
public function createIndexRepositoryQuery(
SearchDto $searchDto,
EntityDto $entityDto,
@@ -370,7 +378,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController

$this->filtersForm->handleRequest($searchDto->getRequest());

$filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto);
$this->isRepositoryQueryFiltered = $filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto);
return $repositoryQuery;
}


+ 45
- 42
Controller/Ticket/TicketAdminController.php Просмотреть файл

@@ -3,14 +3,19 @@
namespace Lc\SovBundle\Controller\Ticket;

use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
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\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
@@ -21,6 +26,7 @@ use Lc\SovBundle\Factory\Ticket\TicketFactory;
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface;
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory;
use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface;
use Lc\SovBundle\Form\Ticket\TicketAdminFormType;
use Lc\SovBundle\Form\Ticket\TicketFormType;
use Lc\SovBundle\Form\Ticket\TicketMessageFormType;
use Lc\SovBundle\Form\Ticket\TicketStatusType;
@@ -45,6 +51,13 @@ abstract class TicketAdminController extends AbstractAdminController
return $this->getTicketContainer()->getFactory()->create();
}

public function configureCrud(Crud $crud): Crud
{
$crud = parent::configureCrud($crud); // TODO: Change the autogenerated stub
$crud->setDefaultSort(array('updatedAt'=> 'DESC'));
return $crud;
}

public function configureAssets(Assets $assets): Assets
{
$assets = parent::configureAssets($assets);
@@ -56,41 +69,7 @@ abstract class TicketAdminController extends AbstractAdminController

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(),
];
return $this->getTicketContainer()->getFieldDefinition()->getFields($pageName);
}

public function configureActions(Actions $actions): Actions
@@ -102,13 +81,37 @@ abstract class TicketAdminController extends AbstractAdminController
return parent::configureActions($actions);
}

public function createIndexRepositoryQuery(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters
): RepositoryQueryInterface {
$repositoryQuery = parent::createIndexRepositoryQuery(
$searchDto,
$entityDto,
$fields,
$filters
);

if(!$this->isRepositoryQueryFiltered()){

$repositoryQuery->filterByStatus(array(
TicketModel::TICKET_STATUS_OPEN,
TicketModel::TICKET_STATUS_BEING_PROCESSED
));
}

return $repositoryQuery;
}

public function new(AdminContext $context)
{
$adminUrlGenerator = $this->get(AdminUrlGenerator::class);

$ticket = $this->createEntity($context->getEntity()->getFqcn());

$form = $this->createForm(TicketFormType::class, $ticket);
$form = $this->createForm(TicketAdminFormType::class, $ticket);

$form->handleRequest($context->getRequest());
if ($form->isSubmitted() && $form->isValid()) {
@@ -173,18 +176,18 @@ abstract class TicketAdminController extends AbstractAdminController
}


public function ticketStatusAction()
public function ticketStatusAction(AdminContext $context, EntityManagerInterface $entityManager)
{
$request = $this->get('request')->getMasterRequest();
$ticket = $request->attributes->get('easyadmin_context')->getEntity()->getInstance();
$ticket = $context->getEntity()->getInstance();

$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket);
$formTicketStatusForm->handleRequest($request);
$formTicketStatusForm->handleRequest($context->getRequest());

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


+ 39
- 8
Controller/User/UserAdminController.php Просмотреть файл

@@ -2,11 +2,16 @@

namespace Lc\SovBundle\Controller\User;

use EasyCorp\Bundle\EasyAdminBundle\Collection\EntityCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Container\User\UserContainer;
use Lc\SovBundle\Controller\AbstractAdminController;
use Lc\SovBundle\Definition\ActionDefinition;
use Lc\SovBundle\Definition\RolesDefinition;
use Lc\SovBundle\Definition\RolesDefinitionInterface;
use Lc\SovBundle\Doctrine\EntityManager;
@@ -19,14 +24,40 @@ abstract class UserAdminController extends AbstractAdminController
{
protected RolesDefinitionInterface $rolesDefinition;

public function __construct(
SessionInterface $session,
RequestStack $request,
EntityManager $em,
TranslatorAdmin $translatorAdmin,
RolesDefinitionInterface $rolesDefinition
) {
$this->rolesDefinition = $rolesDefinition;

public function buildIndexActions(Actions $actions): void
{
parent::buildIndexActions($actions); // TODO: Change the autogenerated stub

$actions->add(Crud::PAGE_INDEX, $this->getSwitchUserAction());
}

public function getSwitchUserAction(): Action
{
$switchAction = Action::new(
ActionDefinition::SWITCH_USER,
$this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SWITCH_USER),
'fa fa-fw fa-user-secret'
)
->linkToCrudAction(ActionDefinition::SWITCH_USER)
->setLabel($this->get(TranslatorAdmin::class)->transAction(ActionDefinition::SWITCH_USER))
->setCssClass('in-dropdown text-info action-confirm action_switch');

return $switchAction;
}

public function overrideEntitiesActions(?EntityCollection $entities): void
{
parent::overrideEntitiesActions($entities); // TODO: Change the autogenerated stub
foreach ($entities as $entity) {
foreach ($entity->getActions() as $action){
if($action->getName() == ActionDefinition::SWITCH_USER){
$url = $this->generateUrl($this->getParameter('lc_sov.homepage_route'), array('_switch_user' => $entity->getInstance()->getEmail()));
$action->setLinkUrl($url);
}
}

}
}

public function configureFields(string $pageName): iterable

+ 2
- 0
Definition/ActionDefinition.php Просмотреть файл

@@ -15,4 +15,6 @@ class ActionDefinition {
public const SAVE_AND_ADD_ANOTHER = 'saveAndAddAnother';
public const SAVE_AND_CONTINUE = 'saveAndContinue';
public const SAVE_AND_RETURN = 'saveAndReturn';
public const SWITCH_USER = 'switchUser';

}

+ 2
- 2
Definition/Field/Site/NewsFieldDefinition.php Просмотреть файл

@@ -5,10 +5,10 @@ namespace Lc\SovBundle\Definition\Field\Site;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
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 +50,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),
];
}

+ 106
- 0
Definition/Field/Ticket/TicketFieldDefinition.php Просмотреть файл

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

namespace Lc\SovBundle\Definition\Field\Ticket;


use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use Lc\SovBundle\Definition\Field\AbstractFieldDefinition;
use Lc\SovBundle\Field\Filter\Ticket\EmailTicketFilter;
use Lc\SovBundle\Field\Filter\Ticket\FirstnameTicketFilter;
use Lc\SovBundle\Field\Filter\Ticket\LastnameTicketFilter;
use Lc\SovBundle\Solver\Ticket\TicketSolver;

class TicketFieldDefinition extends AbstractFieldDefinition
{

public function configureIndex(): array
{
return [
'id',
'createdAt',
'visitorFirstname',
'visitorLastname',
'visitorEmail',
'subject',
'updatedAt',
'type',
'status'
];
}

public function configureForm(): array
{
return [
'user',
'subject'
];
}

public function configurePanels(): array
{
return [];
}

public function configureFields(): array
{
return [
'id' => IdField::new('id')
->setSortable(true)
->hideOnForm(),
'createdAt' => DateTimeField::new('createdAt')
->setSortable(true)
->hideOnForm(),
'visitorFirstname' => TextField::new('visitorFirstname')
->setTemplatePath('@LcSov/admin/ticket/field/firstname.html.twig')
->setCustomOption('filter_fqcn', FirstnameTicketFilter::class)
->setSortable(true)
->hideOnForm(),
'visitorLastname' => TextField::new('visitorLastname')
->setTemplatePath('@LcSov/admin/ticket/field/lastname.html.twig')
->setCustomOption('filter_fqcn', LastnameTicketFilter::class)
->setSortable(true)
->hideOnForm(),
'visitorEmail' => TextField::new('visitorEmail')
->setTemplatePath('@LcSov/admin/ticket/field/email.html.twig')
->setCustomOption('filter_fqcn', EmailTicketFilter::class)
->setSortable(true)
->hideOnForm(),
'user' => AssociationField::new('user')
->hideOnIndex(),
'subject' => TextField::new('subject')
->setSortable(true),
'updatedAt' => DateTimeField::new('updatedAt')
->setTemplatePath('@LcSov/admin/ticket/field/lastmessage.html.twig')
->setSortable(true)
->hideOnForm(),
'type' => ChoiceField::new('type')
->autocomplete()
->setSortable(true)
->setChoices(
$this->translatorAdmin->transChoices(
TicketSolver::getTypeChoices(),
'Ticket',
'type'
)
),
'status' => ChoiceField::new('status')
->autocomplete()
->setSortable(true)
->setChoices(
$this->translatorAdmin->transChoices(
TicketSolver::getStatusChoices(),
'Ticket',
'status'
)

)
->setTemplatePath('@LcSov/admin/ticket/field/status.html.twig')
->hideOnForm(),
];
}

}

+ 1
- 14
Field/Filter/ChoiceFilter.php Просмотреть файл

@@ -53,23 +53,10 @@ class ChoiceFilter
{
$fieldProperty = $this->getFieldProperty($fieldDto);
if ($filteredValue !== null) {
// if ($this->isRelationField($fieldProperty)) {
// $aliasRelation = $this->getFieldPropertyRelationAlias($fieldProperty);
// if (array_search($aliasRelation, $repositoryQuery->getAllAliases()) === false) {
// $repositoryQuery->innerJoin('entity.'.$aliasRelation, $aliasRelation);
// }
// $repositoryQuery->andWhere(
// $fieldProperty.' LIKE :'.$this->getFieldPropertySnake($fieldProperty).''
// );
// $repositoryQuery->setParameter(
// $this->getFieldPropertySnake($fieldProperty),
// '%'.$filteredValue.'%'
// );
// } else {
$repositoryQuery->andWhere(
'.'.$fieldProperty.' LIKE :'.$fieldProperty.''
);
$repositoryQuery->setParameter($fieldProperty, '%'.$filteredValue.'%');
$repositoryQuery->setParameter($fieldProperty, $filteredValue);

}
}

+ 11
- 12
Field/Filter/FilterManager.php Просмотреть файл

@@ -29,6 +29,7 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
class FilterManager
{
protected $em;
protected bool $isFiltered = false;

use FilterTrait;

@@ -39,7 +40,7 @@ class FilterManager
}


public function handleFiltersForm(RepositoryQueryInterface $repositoryQuery, Form $filtersForm, $fields, EntityDto $entityDto)
public function handleFiltersForm(RepositoryQueryInterface $repositoryQuery, Form $filtersForm, $fields, EntityDto $entityDto):bool
{

foreach ($fields as $field) {
@@ -65,17 +66,25 @@ class FilterManager
$fieldDto->getProperty(),
'dateEnd'
);
if($filteredValue['dateStart'] || $filteredValue['dateEnd']){
$this->isFiltered = true;
}
} else {
$filteredValue['value'] = $this->getFilteredValue(
$filtersForm,
$entityDto->getFqcn(),
$fieldDto->getProperty()
);
if($filteredValue['value'] ){
$this->isFiltered = true;
}
}

$this->applyFilter($repositoryQuery, $fieldDto, $filteredValue);
}
}
}
return $this->isFiltered;
}


@@ -88,7 +97,7 @@ class FilterManager
$customFilter->applyFilter($repositoryQuery, $fieldDto, $filteredValue['value']);
} else {

switch ($this->guessFormType($fieldDto)) {
switch ($fieldDto->getFormType()) {

case CheckboxType::class:
$checkboxFilter = new CheckboxFilter();
@@ -183,14 +192,4 @@ class FilterManager
}
}


protected function guessFormType(FieldDto $fieldDto)
{
if ($fieldDto->getCustomOption('filter_type')) {
return $fieldDto->getCustomOption('filter_type');
} else {
return $fieldDto->getFormType();
}

}
}

+ 3
- 3
Field/Filter/FilterTrait.php Просмотреть файл

@@ -41,9 +41,9 @@ trait FilterTrait
{
$property = $fieldDto->getProperty();
//TODO pas forcément utile, à discuter
if ($fieldDto->getCustomOption('filter_on')) {
$property = $property . '.' . $fieldDto->getCustomOption('filter_on');
}
// if ($fieldDto->getCustomOption('filter_on')) {
// $property = $property . '.' . $fieldDto->getCustomOption('filter_on');
// }
return $property;
}


+ 48
- 0
Field/Filter/Ticket/EmailTicketFilter.php Просмотреть файл

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

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class EmailTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.email LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 48
- 0
Field/Filter/Ticket/FirstnameTicketFilter.php Просмотреть файл

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

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class FirstnameTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.firstname LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 48
- 0
Field/Filter/Ticket/LastnameTicketFilter.php Просмотреть файл

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

namespace Lc\SovBundle\Field\Filter\Ticket;

use Doctrine\ORM\EntityRepository;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use Lc\SovBundle\Field\Filter\FilterTrait;
use Lc\SovBundle\Repository\RepositoryQueryInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
* @author La clic ! <contact@laclic.fr>
*/
class LastnameTicketFilter
{
use FilterTrait;

public function buildProperty(FormBuilderInterface $builder, FieldDto $fieldDto, $options = array())
{
$builder->add(
str_replace('.', '_', $fieldDto->getProperty()),
TextType::class,
array(
'required' => false,
'attr' => array(
'class' => ' input-sm',
'form' => 'filters-form',
),
)
);
}

public function applyFilter(RepositoryQueryInterface $repositoryQuery, FieldDto $fieldDto, $filteredValue = null)
{
$fieldProperty = $this->getFieldProperty($fieldDto);

if ($filteredValue !== null) {
$repositoryQuery->joinUser();
$repositoryQuery->andWhere(
'.' . $fieldProperty . ' LIKE :' . $fieldProperty . ' OR user.lastname LIKE :' . $fieldProperty
);
$repositoryQuery->setParameter($fieldProperty, '%' . $filteredValue . '%');
}
}

}

+ 93
- 0
Form/Ticket/TicketAdminFormType.php Просмотреть файл

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

namespace Lc\SovBundle\Form\Ticket;

use Lc\SovBundle\Doctrine\EntityManager;
use Lc\SovBundle\Model\Ticket\TicketInterface;
use Lc\SovBundle\Model\Ticket\TicketModel;
use Lc\SovBundle\Model\User\UserInterface;
use Lc\SovBundle\Solver\Ticket\TicketSolver;
use Lc\SovBundle\Translation\TranslatorAdmin;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class TicketAdminFormType extends AbstractType
{
protected EntityManager $entityManager;
protected TranslatorAdmin $translatorAdmin;

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

public function buildForm(FormBuilderInterface $builder, array $options)
{
$entityName = $this->entityManager->getEntityName(TicketInterface::class);

$builder->add(
'user',
EntityType::class,
[
'class' => $this->entityManager->getEntityName(UserInterface::class),
]
);

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

$builder->add(
'type',
ChoiceType::class,
[
'label' => 'Type',
'choices' => $this->translatorAdmin->transChoices(
TicketSolver::getTypeChoices(),
'Ticket',
'type'
),
]
);

$builder->add(
'ticketMessages',
CollectionType::class,
[
'entry_type' => TicketMessageAdminType::class,
'allow_add' => false,
'label_attr' => ['class' => 'label-ticket'],
]
);

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

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => $this->entityManager->getEntityName(TicketInterface::class),
]
);
}
}

+ 3
- 6
Form/Ticket/TicketFormType.php Просмотреть файл

@@ -21,16 +21,13 @@ class TicketFormType extends AbstractType
{
protected EntityManager $entityManager;
protected TranslatorAdmin $translatorAdmin;
protected TicketSolver $ticketSolver;

public function __construct(
EntityManager $entityManager,
TranslatorAdmin $translatorAdmin,
TicketSolver $ticketSolver
TranslatorAdmin $translatorAdmin
) {
$this->entityManager = $entityManager;
$this->translatorAdmin = $translatorAdmin;
$this->ticketSolver = $ticketSolver;
}

public function buildForm(FormBuilderInterface $builder, array $options)
@@ -56,7 +53,7 @@ class TicketFormType extends AbstractType
[
'label' => 'Type',
'choices' => $this->translatorAdmin->transChoices(
$this->ticketSolver->getTypeChoices(),
TicketSolver::getTypeChoices(),
'Ticket',
'type'
),
@@ -93,4 +90,4 @@ class TicketFormType extends AbstractType
]
);
}
}
}

+ 45
- 0
Form/Ticket/TicketMessageAdminType.php Просмотреть файл

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

}

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

+ 1
- 0
Model/Ticket/TicketModel.php Просмотреть файл

@@ -22,6 +22,7 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac

const TICKET_STATUS_OPEN = 'open';
const TICKET_STATUS_BEING_PROCESSED = 'being-processed';
const TICKET_STATUS_PROCESSED = 'processed';
const TICKET_STATUS_CLOSED = 'closed';

/**

+ 14
- 0
Repository/Ticket/TicketRepositoryQuery.php Просмотреть файл

@@ -8,6 +8,9 @@ use Lc\SovBundle\Repository\AbstractRepositoryQuery;

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


public function __construct(TicketRepository $repository, PaginatorInterface $paginator)
{
parent::__construct($repository, 'r', $paginator);
@@ -20,6 +23,17 @@ class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRep
->setParameter('user', $user);
}

public function joinUser(): self
{
if (!$this->isJoinUser) {
$this->isJoinUser = true;

return $this
->leftJoin('.user', 'user');
}
return $this;
}

public function filterByStatus($statusArray): self
{
return $this

+ 1
- 1
Resources/translations/admin.fr.yaml Просмотреть файл

@@ -106,7 +106,7 @@ entity:
default:
fields:
id: Id
createdAt: Créé à
createdAt: Créé le
user: Utilisateur
firstname: Prénom
lastname: Nom

+ 10
- 7
Resources/views/admin/ticket/field/lastmessage.html.twig Просмотреть файл

@@ -1,7 +1,10 @@
{#{% 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 }}#}
{% if item is not defined %}
{% set item = entity.instance %}
{% endif %}
{% set ticketMessage = ticket_container.solver.getLastMessage(item) %}
{% if ticketMessage.answerByAdmin != true %}
<span class="badge badge-danger">
New
</span>
{% endif %}
{{ ticketMessage.createdAt|date('d/m/Y H:i') }} par {{ ticketMessage.createdBy }}

+ 2
- 0
Resources/views/admin/ticket/field/status.html.twig Просмотреть файл

@@ -6,6 +6,8 @@
{{ macro.badge_success(status|sov_trans_admin_choice('status','Ticket')) }}
{% elseif status == 'being-processed' %}
{{ macro.badge_warning(status|sov_trans_admin_choice('status','Ticket')) }}
{% elseif status == 'processed' %}
{{ macro.badge_info(status|sov_trans_admin_choice('status','Ticket')) }}
{% elseif status == 'closed' %}
{{ macro.badge_danger(status|sov_trans_admin_choice('status','Ticket')) }}
{% endif %}

+ 1
- 1
Resources/views/admin/ticket/macro.html.twig Просмотреть файл

@@ -5,7 +5,7 @@
<th>Sujet</th>
<th>Statut</th>
<th>Dernier message</th>
<th></th>
<th>Actions</th>
</tr>
</thead>
<tbody>

+ 5
- 1
Resources/views/adminlte/macro/badge.html.twig Просмотреть файл

@@ -10,6 +10,10 @@
{{ _self.badge('danger', title) }}
{% endmacro %}

{% macro badge_info(title) %}
{{ _self.badge('info', title) }}
{% endmacro %}

{% macro badge(status, title) %}
<span class="badge badge-{{ status }}">{{ title }}</span>
{% endmacro %}
{% endmacro %}

+ 3
- 2
Solver/Ticket/TicketSolver.php Просмотреть файл

@@ -7,7 +7,7 @@ use Lc\SovBundle\Model\Ticket\TicketModel;

class TicketSolver
{
public function getTypeChoices(): array
public static function getTypeChoices(): array
{
return [
TicketModel::TYPE_GENERAL_QUESTION,
@@ -15,11 +15,12 @@ class TicketSolver
];
}

public function getStatusChoices(): array
public static function getStatusChoices(): array
{
return [
TicketModel::TICKET_STATUS_OPEN,
TicketModel::TICKET_STATUS_BEING_PROCESSED,
TicketModel::TICKET_STATUS_PROCESSED,
TicketModel::TICKET_STATUS_CLOSED,
];
}

Загрузка…
Отмена
Сохранить