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 TicketRepositoryQuery $repositoryQuery; | protected TicketRepositoryQuery $repositoryQuery; | ||||
protected TicketStore $store; | protected TicketStore $store; | ||||
protected TicketSolver $solver; | protected TicketSolver $solver; | ||||
protected TicketFieldDefinition $fieldDefinition; | |||||
public function __construct( | public function __construct( | ||||
TicketFactory $factory, | TicketFactory $factory, | ||||
TicketBuilder $builder, | TicketBuilder $builder, | ||||
TicketRepositoryQuery $repositoryQuery, | TicketRepositoryQuery $repositoryQuery, | ||||
TicketStore $store, | TicketStore $store, | ||||
TicketSolver $solver | |||||
TicketSolver $solver, | |||||
TicketFieldDefinition $fieldDefinition | |||||
) { | ) { | ||||
$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->solver = $solver; | $this->solver = $solver; | ||||
$this->fieldDefinition = $fieldDefinition; | |||||
} | } | ||||
public function getFactory(): TicketFactory | public function getFactory(): TicketFactory | ||||
{ | { | ||||
return $this->solver; | return $this->solver; | ||||
} | } | ||||
public function getFieldDefinition(): TicketFieldDefinition | |||||
{ | |||||
return $this->fieldDefinition; | |||||
} | |||||
} | } |
use ControllerTrait; | use ControllerTrait; | ||||
protected FormInterface $filtersForm; | protected FormInterface $filtersForm; | ||||
protected bool $isRepositoryQueryFiltered = false; | |||||
abstract public function getRepositoryQuery(): RepositoryQueryInterface; | abstract public function getRepositoryQuery(): RepositoryQueryInterface; | ||||
return $this->redirect($url); | return $this->redirect($url); | ||||
} | } | ||||
public function isRepositoryQueryFiltered():bool{ | |||||
if(($this->filtersForm && $this->filtersForm->isSubmitted()) || $this->isRepositoryQueryFiltered){ | |||||
return true; | |||||
}else{ | |||||
return false; | |||||
} | |||||
} | |||||
public function createIndexRepositoryQuery( | public function createIndexRepositoryQuery( | ||||
SearchDto $searchDto, | SearchDto $searchDto, | ||||
EntityDto $entityDto, | EntityDto $entityDto, | ||||
$this->filtersForm->handleRequest($searchDto->getRequest()); | $this->filtersForm->handleRequest($searchDto->getRequest()); | ||||
$filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto); | |||||
$this->isRepositoryQueryFiltered = $filterManager->handleFiltersForm($repositoryQuery, $this->filtersForm, $fields, $entityDto); | |||||
return $repositoryQuery; | return $repositoryQuery; | ||||
} | } | ||||
namespace Lc\SovBundle\Controller\Ticket; | namespace Lc\SovBundle\Controller\Ticket; | ||||
use Doctrine\ORM\EntityManagerInterface; | 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\Action; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | use EasyCorp\Bundle\EasyAdminBundle\Config\Assets; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | 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\AssociationField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField; | |||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | ||||
use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface; | use Lc\SovBundle\Factory\Ticket\TicketFactoryInterface; | ||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactory; | use Lc\SovBundle\Factory\Ticket\TicketMessageFactory; | ||||
use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface; | use Lc\SovBundle\Factory\Ticket\TicketMessageFactoryInterface; | ||||
use Lc\SovBundle\Form\Ticket\TicketAdminFormType; | |||||
use Lc\SovBundle\Form\Ticket\TicketFormType; | use Lc\SovBundle\Form\Ticket\TicketFormType; | ||||
use Lc\SovBundle\Form\Ticket\TicketMessageFormType; | use Lc\SovBundle\Form\Ticket\TicketMessageFormType; | ||||
use Lc\SovBundle\Form\Ticket\TicketStatusType; | use Lc\SovBundle\Form\Ticket\TicketStatusType; | ||||
return $this->getTicketContainer()->getFactory()->create(); | 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 | public function configureAssets(Assets $assets): Assets | ||||
{ | { | ||||
$assets = parent::configureAssets($assets); | $assets = parent::configureAssets($assets); | ||||
public function configureFields(string $pageName): iterable | 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 | public function configureActions(Actions $actions): Actions | ||||
return parent::configureActions($actions); | 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) | public function new(AdminContext $context) | ||||
{ | { | ||||
$adminUrlGenerator = $this->get(AdminUrlGenerator::class); | $adminUrlGenerator = $this->get(AdminUrlGenerator::class); | ||||
$ticket = $this->createEntity($context->getEntity()->getFqcn()); | $ticket = $this->createEntity($context->getEntity()->getFqcn()); | ||||
$form = $this->createForm(TicketFormType::class, $ticket); | |||||
$form = $this->createForm(TicketAdminFormType::class, $ticket); | |||||
$form->handleRequest($context->getRequest()); | $form->handleRequest($context->getRequest()); | ||||
if ($form->isSubmitted() && $form->isValid()) { | if ($form->isSubmitted() && $form->isValid()) { | ||||
} | } | ||||
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 = $this->createForm(TicketStatusType::class, $ticket); | ||||
$formTicketStatusForm->handleRequest($request); | |||||
$formTicketStatusForm->handleRequest($context->getRequest()); | |||||
$success = false; | $success = false; | ||||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | ||||
$this->get('em')->persist($ticket); | |||||
$this->get('em')->flush(); | |||||
$entityManager->update($ticket); | |||||
$entityManager->flush(); | |||||
$success = true; | $success = true; | ||||
} | } | ||||
namespace Lc\SovBundle\Controller\User; | 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\ChoiceField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; | use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | ||||
use Lc\SovBundle\Container\User\UserContainer; | use Lc\SovBundle\Container\User\UserContainer; | ||||
use Lc\SovBundle\Controller\AbstractAdminController; | use Lc\SovBundle\Controller\AbstractAdminController; | ||||
use Lc\SovBundle\Definition\ActionDefinition; | |||||
use Lc\SovBundle\Definition\RolesDefinition; | use Lc\SovBundle\Definition\RolesDefinition; | ||||
use Lc\SovBundle\Definition\RolesDefinitionInterface; | use Lc\SovBundle\Definition\RolesDefinitionInterface; | ||||
use Lc\SovBundle\Doctrine\EntityManager; | use Lc\SovBundle\Doctrine\EntityManager; | ||||
{ | { | ||||
protected RolesDefinitionInterface $rolesDefinition; | 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 | public function configureFields(string $pageName): iterable |
public const SAVE_AND_ADD_ANOTHER = 'saveAndAddAnother'; | public const SAVE_AND_ADD_ANOTHER = 'saveAndAddAnother'; | ||||
public const SAVE_AND_CONTINUE = 'saveAndContinue'; | public const SAVE_AND_CONTINUE = 'saveAndContinue'; | ||||
public const SAVE_AND_RETURN = 'saveAndReturn'; | public const SAVE_AND_RETURN = 'saveAndReturn'; | ||||
public const SWITCH_USER = 'switchUser'; | |||||
} | } |
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField; | use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField; | ||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; | |||||
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), | ||||
]; | ]; | ||||
} | } |
<?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(), | |||||
]; | |||||
} | |||||
} |
{ | { | ||||
$fieldProperty = $this->getFieldProperty($fieldDto); | $fieldProperty = $this->getFieldProperty($fieldDto); | ||||
if ($filteredValue !== null) { | 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( | $repositoryQuery->andWhere( | ||||
'.'.$fieldProperty.' LIKE :'.$fieldProperty.'' | '.'.$fieldProperty.' LIKE :'.$fieldProperty.'' | ||||
); | ); | ||||
$repositoryQuery->setParameter($fieldProperty, '%'.$filteredValue.'%'); | |||||
$repositoryQuery->setParameter($fieldProperty, $filteredValue); | |||||
} | } | ||||
} | } |
class FilterManager | class FilterManager | ||||
{ | { | ||||
protected $em; | protected $em; | ||||
protected bool $isFiltered = false; | |||||
use FilterTrait; | use FilterTrait; | ||||
} | } | ||||
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) { | foreach ($fields as $field) { | ||||
$fieldDto->getProperty(), | $fieldDto->getProperty(), | ||||
'dateEnd' | 'dateEnd' | ||||
); | ); | ||||
if($filteredValue['dateStart'] || $filteredValue['dateEnd']){ | |||||
$this->isFiltered = true; | |||||
} | |||||
} else { | } else { | ||||
$filteredValue['value'] = $this->getFilteredValue( | $filteredValue['value'] = $this->getFilteredValue( | ||||
$filtersForm, | $filtersForm, | ||||
$entityDto->getFqcn(), | $entityDto->getFqcn(), | ||||
$fieldDto->getProperty() | $fieldDto->getProperty() | ||||
); | ); | ||||
if($filteredValue['value'] ){ | |||||
$this->isFiltered = true; | |||||
} | |||||
} | } | ||||
$this->applyFilter($repositoryQuery, $fieldDto, $filteredValue); | $this->applyFilter($repositoryQuery, $fieldDto, $filteredValue); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $this->isFiltered; | |||||
} | } | ||||
$customFilter->applyFilter($repositoryQuery, $fieldDto, $filteredValue['value']); | $customFilter->applyFilter($repositoryQuery, $fieldDto, $filteredValue['value']); | ||||
} else { | } else { | ||||
switch ($this->guessFormType($fieldDto)) { | |||||
switch ($fieldDto->getFormType()) { | |||||
case CheckboxType::class: | case CheckboxType::class: | ||||
$checkboxFilter = new CheckboxFilter(); | $checkboxFilter = new CheckboxFilter(); | ||||
} | } | ||||
} | } | ||||
protected function guessFormType(FieldDto $fieldDto) | |||||
{ | |||||
if ($fieldDto->getCustomOption('filter_type')) { | |||||
return $fieldDto->getCustomOption('filter_type'); | |||||
} else { | |||||
return $fieldDto->getFormType(); | |||||
} | |||||
} | |||||
} | } |
{ | { | ||||
$property = $fieldDto->getProperty(); | $property = $fieldDto->getProperty(); | ||||
//TODO pas forcément utile, à discuter | //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; | return $property; | ||||
} | } | ||||
<?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 . '%'); | |||||
} | |||||
} | |||||
} |
<?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 . '%'); | |||||
} | |||||
} | |||||
} |
<?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 . '%'); | |||||
} | |||||
} | |||||
} |
<?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), | |||||
] | |||||
); | |||||
} | |||||
} |
{ | { | ||||
protected EntityManager $entityManager; | protected EntityManager $entityManager; | ||||
protected TranslatorAdmin $translatorAdmin; | protected TranslatorAdmin $translatorAdmin; | ||||
protected TicketSolver $ticketSolver; | |||||
public function __construct( | public function __construct( | ||||
EntityManager $entityManager, | EntityManager $entityManager, | ||||
TranslatorAdmin $translatorAdmin, | |||||
TicketSolver $ticketSolver | |||||
TranslatorAdmin $translatorAdmin | |||||
) { | ) { | ||||
$this->entityManager = $entityManager; | $this->entityManager = $entityManager; | ||||
$this->translatorAdmin = $translatorAdmin; | $this->translatorAdmin = $translatorAdmin; | ||||
$this->ticketSolver = $ticketSolver; | |||||
} | } | ||||
public function buildForm(FormBuilderInterface $builder, array $options) | public function buildForm(FormBuilderInterface $builder, array $options) | ||||
[ | [ | ||||
'label' => 'Type', | 'label' => 'Type', | ||||
'choices' => $this->translatorAdmin->transChoices( | 'choices' => $this->translatorAdmin->transChoices( | ||||
$this->ticketSolver->getTypeChoices(), | |||||
TicketSolver::getTypeChoices(), | |||||
'Ticket', | 'Ticket', | ||||
'type' | 'type' | ||||
), | ), | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
} | |||||
} |
<?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), | |||||
] | |||||
); | |||||
} | |||||
} |
const TICKET_STATUS_OPEN = 'open'; | const TICKET_STATUS_OPEN = 'open'; | ||||
const TICKET_STATUS_BEING_PROCESSED = 'being-processed'; | const TICKET_STATUS_BEING_PROCESSED = 'being-processed'; | ||||
const TICKET_STATUS_PROCESSED = 'processed'; | |||||
const TICKET_STATUS_CLOSED = 'closed'; | const TICKET_STATUS_CLOSED = 'closed'; | ||||
/** | /** |
class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | class TicketRepositoryQuery extends AbstractRepositoryQuery implements TicketRepositoryQueryInterface | ||||
{ | { | ||||
protected $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('user', $user); | ->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 | public function filterByStatus($statusArray): self | ||||
{ | { | ||||
return $this | return $this |
default: | default: | ||||
fields: | fields: | ||||
id: Id | id: Id | ||||
createdAt: Créé à | |||||
createdAt: Créé le | |||||
user: Utilisateur | user: Utilisateur | ||||
firstname: Prénom | firstname: Prénom | ||||
lastname: Nom | lastname: Nom |
{#{% 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 }} |
{{ macro.badge_success(status|sov_trans_admin_choice('status','Ticket')) }} | {{ macro.badge_success(status|sov_trans_admin_choice('status','Ticket')) }} | ||||
{% elseif status == 'being-processed' %} | {% elseif status == 'being-processed' %} | ||||
{{ macro.badge_warning(status|sov_trans_admin_choice('status','Ticket')) }} | {{ 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' %} | {% elseif status == 'closed' %} | ||||
{{ macro.badge_danger(status|sov_trans_admin_choice('status','Ticket')) }} | {{ macro.badge_danger(status|sov_trans_admin_choice('status','Ticket')) }} | ||||
{% endif %} | {% endif %} |
<th>Sujet</th> | <th>Sujet</th> | ||||
<th>Statut</th> | <th>Statut</th> | ||||
<th>Dernier message</th> | <th>Dernier message</th> | ||||
<th></th> | |||||
<th>Actions</th> | |||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> |
{{ _self.badge('danger', title) }} | {{ _self.badge('danger', title) }} | ||||
{% endmacro %} | {% endmacro %} | ||||
{% macro badge_info(title) %} | |||||
{{ _self.badge('info', title) }} | |||||
{% endmacro %} | |||||
{% macro badge(status, title) %} | {% macro badge(status, title) %} | ||||
<span class="badge badge-{{ status }}">{{ title }}</span> | <span class="badge badge-{{ status }}">{{ title }}</span> | ||||
{% endmacro %} | |||||
{% endmacro %} |
class TicketSolver | class TicketSolver | ||||
{ | { | ||||
public function getTypeChoices(): array | |||||
public static function getTypeChoices(): array | |||||
{ | { | ||||
return [ | return [ | ||||
TicketModel::TYPE_GENERAL_QUESTION, | TicketModel::TYPE_GENERAL_QUESTION, | ||||
]; | ]; | ||||
} | } | ||||
public function getStatusChoices(): array | |||||
public static function getStatusChoices(): array | |||||
{ | { | ||||
return [ | return [ | ||||
TicketModel::TICKET_STATUS_OPEN, | TicketModel::TICKET_STATUS_OPEN, | ||||
TicketModel::TICKET_STATUS_BEING_PROCESSED, | TicketModel::TICKET_STATUS_BEING_PROCESSED, | ||||
TicketModel::TICKET_STATUS_PROCESSED, | |||||
TicketModel::TICKET_STATUS_CLOSED, | TicketModel::TICKET_STATUS_CLOSED, | ||||
]; | ]; | ||||
} | } |