@@ -50,22 +50,14 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface; | |||
abstract class AbstractAdminController extends EaAbstractCrudController | |||
{ | |||
protected $session; | |||
protected $request; | |||
protected $em; | |||
protected $translatorAdmin; | |||
public function __construct( | |||
SessionInterface $session, | |||
RequestStack $request, | |||
EntityManagerInterface $em, | |||
TranslatorAdmin $translatorAdmin | |||
) | |||
public static function getSubscribedServices() | |||
{ | |||
$this->session = $session; | |||
$this->request = $request; | |||
$this->em = $em; | |||
$this->translatorAdmin = $translatorAdmin; | |||
return array_merge(parent::getSubscribedServices(), [ | |||
'session' => SessionInterface::class, | |||
'request' => RequestStack::class, | |||
'em' => EntityManagerInterface::class, | |||
'translator_admin' => TranslatorAdmin::class, | |||
]); | |||
} | |||
public function configureActions(Actions $actions): Actions | |||
@@ -87,7 +79,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$actionsArray[Crud::PAGE_INDEX] = [ | |||
Action::NEW => [ | |||
'icon' => 'plus', | |||
'label' => $this->translatorAdmin->transAction('create'), | |||
'label' => $this->get('translator_admin')->transAction('create'), | |||
'add_class' => 'btn-sm' | |||
], | |||
Action::EDIT => [ | |||
@@ -96,43 +88,51 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
'label' => false, | |||
'html_attributes' => array( | |||
'data-toggle' => 'tooltip', | |||
'title' => $this->translatorAdmin->transAction('edit') | |||
'title' => $this->get('translator_admin')->transAction('edit') | |||
) | |||
], | |||
Action::DETAIL => [ | |||
'icon' => 'eye', | |||
'add_class' => 'btn btn-sm btn-success', | |||
'label' => false, | |||
'html_attributes' => array( | |||
'data-toggle' => 'tooltip', | |||
'title' => $this->get('translator_admin')->transAction('detail') | |||
) | |||
], | |||
Action::DELETE => [ | |||
'icon' => 'trash', | |||
'dropdown' => true, | |||
'label' => $this->translatorAdmin->transAction('delete') | |||
'label' => $this->get('translator_admin')->transAction('delete') | |||
], | |||
Action::BATCH_DELETE => [ | |||
'class' => 'btn btn-sm btn-danger', | |||
'icon' => 'trash', | |||
'label' => $this->translatorAdmin->transAction('delete') | |||
'label' => $this->get('translator_admin')->transAction('delete') | |||
], | |||
]; | |||
/* Boutons des actions dans l'édition */ | |||
$actionSaveAndReturn = [ | |||
'add_class' => 'float-right', | |||
'icon' => 'check', | |||
'label' => $this->translatorAdmin->transAction('save_and_return') | |||
'label' => $this->get('translator_admin')->transAction('save_and_return') | |||
]; | |||
$actionIndex = [ | |||
'icon' => 'chevron-left', | |||
'class' => 'btn btn-link', | |||
'label' => $this->translatorAdmin->transAction('back_index') | |||
'label' => $this->get('translator_admin')->transAction('back_index') | |||
]; | |||
$actionsArray[Crud::PAGE_EDIT] = [ | |||
Action::SAVE_AND_CONTINUE => [ | |||
'class' => 'btn btn-info float-right', | |||
'label' => $this->translatorAdmin->transAction('save_and_continue') | |||
'label' => $this->get('translator_admin')->transAction('save_and_continue') | |||
], | |||
Action::DELETE => [ | |||
'icon' => 'trash', | |||
'class' => 'btn btn-outline-danger action-delete', | |||
'label' => $this->translatorAdmin->transAction('delete') | |||
'label' => $this->get('translator_admin')->transAction('delete') | |||
], | |||
Action::SAVE_AND_RETURN => $actionSaveAndReturn, | |||
Action::INDEX => $actionIndex, | |||
@@ -141,7 +141,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$actionsArray[Crud::PAGE_NEW] = [ | |||
Action::SAVE_AND_ADD_ANOTHER => [ | |||
'class' => 'btn btn-info float-right', | |||
'label' => $this->translatorAdmin->transAction('save_and_add_another') | |||
'label' => $this->get('translator_admin')->transAction('save_and_add_another') | |||
], | |||
Action::SAVE_AND_RETURN => $actionSaveAndReturn, | |||
Action::INDEX => $actionIndex, | |||
@@ -152,7 +152,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$actions->add(Crud::PAGE_NEW, Action::INDEX); | |||
if ($this->isInstanceOf(SortableInterface::class)) { | |||
$sortAction = Action::new('sort', $this->translatorAdmin->transAction('sort'), 'fa fa-sort') | |||
$sortAction = Action::new('sort', $this->get('translator_admin')->transAction('sort'), 'fa fa-sort') | |||
->linkToCrudAction('sort') | |||
->setCssClass('btn btn-sm btn-success') | |||
->createAsGlobalAction(); | |||
@@ -164,7 +164,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
if ($this->isInstanceOf(TreeInterface::class)) { | |||
$indexChildAction = Action::new( | |||
'index_children', | |||
$this->translatorAdmin->transAction('index_children'), | |||
$this->get('translator_admin')->transAction('index_children'), | |||
'fa fa-list' | |||
) | |||
->linkToCrudAction(Action::INDEX) | |||
@@ -175,7 +175,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$backParentAction = Action::new( | |||
'index_parent', | |||
$this->translatorAdmin->transAction('index_parent'), | |||
$this->get('translator_admin')->transAction('index_parent'), | |||
'fa fa-chevron-left' | |||
) | |||
->linkToCrudAction(Action::INDEX) | |||
@@ -192,37 +192,40 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
foreach ($actionsArray as $crudActionName => $actionsStyle) { | |||
foreach ($actionsStyle as $actionName => $button) { | |||
$actions->update( | |||
$crudActionName, | |||
$actionName, | |||
function (Action $action) use ($button) { | |||
if (isset($button['add_class'])) { | |||
$action->addCssClass($button['add_class']); | |||
} | |||
if (isset($button['class'])) { | |||
$action->setCssClass($button['class']); | |||
} | |||
if (isset($button['icon'])) { | |||
$action->setIcon('fa fa-' . $button['icon']); | |||
// si l'action existe | |||
if ($actions->getAsDto('actions')->getAction($crudActionName, $actionName)) { | |||
$actions->update( | |||
$crudActionName, | |||
$actionName, | |||
function (Action $action) use ($button) { | |||
if (isset($button['add_class'])) { | |||
$action->addCssClass($button['add_class']); | |||
} | |||
if (isset($button['class'])) { | |||
$action->setCssClass($button['class']); | |||
} | |||
if (isset($button['icon'])) { | |||
$action->setIcon('fa fa-' . $button['icon']); | |||
} | |||
if (isset($button['label'])) { | |||
$action->setLabel($button['label']); | |||
} | |||
if (isset($button['dropdown']) && $button['dropdown']) { | |||
$action->addCssClass('in-dropdown'); | |||
} | |||
if (isset($button['html_attributes']) && $button['html_attributes']) { | |||
$action->setHtmlAttributes($button['html_attributes']); | |||
} | |||
return $action; | |||
} | |||
if (isset($button['label'])) { | |||
$action->setLabel($button['label']); | |||
} | |||
if (isset($button['dropdown']) && $button['dropdown']) { | |||
$action->addCssClass('in-dropdown'); | |||
} | |||
if (isset($button['html_attributes']) && $button['html_attributes']) { | |||
$action->setHtmlAttributes($button['html_attributes']); | |||
} | |||
return $action; | |||
} | |||
); | |||
); | |||
} | |||
} | |||
} | |||
@@ -254,12 +257,12 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
$entityClass = $this->getEntityFqcn(); | |||
$paramListMaxResults = 'listMaxResults'; | |||
$paramSessionListMaxResults = $entityClass . '-' . $paramListMaxResults; | |||
$requestListMaxResults = $this->request->getCurrentRequest()->get($paramListMaxResults); | |||
$requestListMaxResults = $this->get('request')->getCurrentRequest()->get($paramListMaxResults); | |||
if ($requestListMaxResults) { | |||
$this->session->set($paramSessionListMaxResults, $requestListMaxResults); | |||
$this->get('session')->set($paramSessionListMaxResults, $requestListMaxResults); | |||
} | |||
$maxResults = $this->session->get($paramSessionListMaxResults) ? $this->session->get( | |||
$maxResults = $this->get('session')->get($paramSessionListMaxResults) ? $this->get('session')->get( | |||
$paramSessionListMaxResults | |||
) : 30; | |||
@@ -390,16 +393,16 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
} | |||
public function createIndexQueryBuilder( | |||
SearchDto $searchDto, | |||
EntityDto $entityDto, | |||
FieldCollection $fields, | |||
FilterCollection $filters | |||
SearchDto $searchDto, | |||
EntityDto $entityDto, | |||
FieldCollection $fields, | |||
FilterCollection $filters | |||
): QueryBuilder { | |||
$queryBuilder = parent::createIndexQueryBuilder( | |||
$searchDto, | |||
$entityDto, | |||
$fields, | |||
$filters | |||
$searchDto, | |||
$entityDto, | |||
$fields, | |||
$filters | |||
); | |||
if ($this->isInstanceOf(TreeInterface::class)) { | |||
@@ -417,13 +420,12 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
} | |||
public function createSortQueryBuilder( | |||
SearchDto $searchDto, | |||
EntityDto $entityDto, | |||
FieldCollection $fields, | |||
FilterCollection $filters | |||
SearchDto $searchDto, | |||
EntityDto $entityDto, | |||
FieldCollection $fields, | |||
FilterCollection $filters | |||
): QueryBuilder { | |||
$queryBuilder = $this->createIndexQueryBuilder($searchDto,$entityDto,$fields,$filters); | |||
$queryBuilder = $this->createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters); | |||
return $queryBuilder; | |||
} | |||
@@ -434,7 +436,7 @@ abstract class AbstractAdminController extends EaAbstractCrudController | |||
// on vide le flash bag si édition en ajax (notification déjà affichée en Javascript) | |||
if ($context->getRequest()->isXmlHttpRequest()) { | |||
$this->session->getFlashBag()->clear(); | |||
$this->get('session')->getFlashBag()->clear(); | |||
} | |||
return $response; |
@@ -3,17 +3,44 @@ | |||
namespace Lc\SovBundle\Controller\Ticket; | |||
use App\Entity\Ticket\Ticket; | |||
use App\Entity\Ticket\TicketMessage; | |||
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Action; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters; | |||
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore; | |||
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent; | |||
use EasyCorp\Bundle\EasyAdminBundle\Exception\ForbiddenActionException; | |||
use EasyCorp\Bundle\EasyAdminBundle\Exception\InsufficientEntityPermissionException; | |||
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; | |||
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; | |||
use EasyCorp\Bundle\EasyAdminBundle\Security\Permission; | |||
use Lc\SovBundle\Factory\Ticket\TicketFactory; | |||
use Lc\SovBundle\Field\StatusField; | |||
use Lc\SovBundle\Form\Ticket\TicketFormType; | |||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||
use Lc\SovBundle\Controller\AbstractAdminController; | |||
use Symfony\Component\HttpFoundation\Request; | |||
use Symfony\Component\HttpFoundation\Response; | |||
abstract class TicketAdminController extends AbstractAdminController | |||
class TicketAdminController extends AbstractAdminController | |||
{ | |||
protected $ticketFactory; | |||
public function __construct(TicketFactory $ticketFactory) | |||
{ | |||
$this->ticketFactory = $ticketFactory; | |||
} | |||
public static function getEntityFqcn(): string | |||
{ | |||
@@ -22,16 +49,23 @@ abstract class TicketAdminController extends AbstractAdminController | |||
public function configureFields(string $pageName): iterable | |||
{ | |||
return [ | |||
TextField::new('id')->hideOnForm(), | |||
DateField::new('createdAt')->setFormat('short')->hideOnForm(), | |||
TextField::new('visitorFirstName')->hideOnForm(), | |||
TextField::new('visitorLastName')->hideOnForm(), | |||
TextField::new('visitorEmail')->hideOnForm(), | |||
IntegerField::new('id') | |||
->hideOnForm(), | |||
DateField::new('createdAt')->setFormat('short') | |||
->hideOnForm(), | |||
TextField::new('visitorFirstName') | |||
->setTemplatePath('@LcSov/admin/ticket/index_username.html.twig') | |||
->hideOnForm(), | |||
TextField::new('visitorEmail') | |||
->setTemplatePath('@LcSov/admin/ticket/index_email.html.twig') | |||
->hideOnForm(), | |||
AssociationField::new('user') | |||
->hideOnIndex(), | |||
TextField::new('subject'), | |||
TextField::new('lastMessage') | |||
->setTemplatePath('@LcSov/admin/ticket/index_lastmessage.html.twig') | |||
->hideOnForm(), | |||
ChoiceField::new('type') | |||
->autocomplete() | |||
->setChoices( | |||
@@ -40,7 +74,60 @@ abstract class TicketAdminController extends AbstractAdminController | |||
'entity.Ticket.fields.typeOptions.' . Ticket::TYPE_TECHNICAL_PROBLEM => Ticket::TYPE_TECHNICAL_PROBLEM, | |||
] | |||
), | |||
StatusField::new('status')->setRequired(false)->hideOnForm(), | |||
ChoiceField::new('status') | |||
->autocomplete() | |||
->setChoices( | |||
[ | |||
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_OPEN => Ticket::TICKET_STATUS_OPEN, | |||
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_BEING_PROCESSED => Ticket::TICKET_STATUS_BEING_PROCESSED, | |||
'entity.Ticket.fields.statusOptions.' . Ticket::TICKET_STATUS_CLOSED => Ticket::TICKET_STATUS_CLOSED, | |||
] | |||
) | |||
->setTemplatePath('@LcSov/admin/ticket/index_status.html.twig') | |||
->hideOnForm(), | |||
]; | |||
} | |||
public function configureCrud(Crud $crud): Crud | |||
{ | |||
$crud | |||
->overrideTemplate('crud/detail', '@LcSov/admin/ticket/detail.html.twig'); | |||
return parent::configureCrud($crud); | |||
} | |||
public function configureActions(Actions $actions): Actions | |||
{ | |||
$actions | |||
->add(Crud::PAGE_INDEX, Action::DETAIL) | |||
->remove(Crud::PAGE_INDEX, Action::EDIT); | |||
return parent::configureActions($actions); | |||
} | |||
public function new(AdminContext $context) | |||
{ | |||
$ticket = $this->ticketFactory->create(); | |||
$form = $this->createForm(TicketFormType::class, $ticket); | |||
$form->handleRequest($context->getRequest()); | |||
if ($form->isSubmitted() && $form->isValid()) { | |||
$ticket = $form->getData(); | |||
foreach($ticket->getTicketMessages() as $ticketMessage){ | |||
$this->get('em')->persist($ticketMessage); | |||
} | |||
$this->get('em')->persist($ticket); | |||
$this->get('em')->flush(); | |||
return $this->redirectToRoute('admin_dashboard'); | |||
} | |||
return $this->render( | |||
'@LcSov/admin/ticket/new.html.twig', | |||
[ | |||
'form' => $form->createView(), | |||
] | |||
); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
<?php | |||
namespace Lc\SovBundle\Factory\Ticket; | |||
use App\Entity\Ticket\Ticket; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
use Lc\SovBundle\Model\Ticket\TicketInterface; | |||
class TicketFactory extends AbstractFactory | |||
{ | |||
protected $ticketMessageFactory; | |||
public function __construct(EntityManagerInterface $em, TicketMessageFactory $ticketMessageFactory) | |||
{ | |||
$this->ticketMessageFactory = $ticketMessageFactory; | |||
parent::__construct($em); | |||
} | |||
public function getEntityClass() | |||
{ | |||
return TicketInterface::class; | |||
} | |||
public function create($params = array()) | |||
{ | |||
if (!isset($params['status'])) { | |||
$params['status'] = Ticket::TICKET_STATUS_OPEN; | |||
} | |||
$ticket = parent::create($params); | |||
if (!isset($params['ticketMessages'])) { | |||
$ticket->addTicketMessage($this->ticketMessageFactory->create()); | |||
} | |||
return $ticket; | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
<?php | |||
namespace Lc\SovBundle\Factory\Ticket; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||
class TicketMessageFactory extends AbstractFactory | |||
{ | |||
public function getEntityClass() | |||
{ | |||
return TicketMessageInterface::class; | |||
} | |||
public function create($params = array()) | |||
{ | |||
if (!isset($params['status'])) { | |||
$params['status'] = 1; | |||
} | |||
return parent::create($params); | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
<?php | |||
namespace Lc\SovBundle\Form\Ticket; | |||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField; | |||
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\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 TicketFormType 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) | |||
{ | |||
$entityName = $this->em->getEntityName(TicketInterface::class); | |||
$builder->add( | |||
'user', | |||
EntityType::class, | |||
[ | |||
'class' => $this->em->getEntityName(UserInterface::class), | |||
] | |||
); | |||
$builder->add( | |||
'subject', | |||
TextType::class | |||
); | |||
$builder->add( | |||
'type', | |||
ChoiceType::class, | |||
[ | |||
'label' => 'Type', | |||
'choices' => [ | |||
$this->translatorAdmin->transField( | |||
'typeOptions.' . TicketModel::TYPE_TECHNICAL_PROBLEM, | |||
$entityName | |||
) => TicketModel::TYPE_TECHNICAL_PROBLEM, | |||
$this->translatorAdmin->transField( | |||
'typeOptions.' . TicketModel::TYPE_GENERAL_QUESTION, | |||
$entityName | |||
) => TicketModel::TYPE_TECHNICAL_PROBLEM, | |||
], | |||
] | |||
); | |||
$builder->add( | |||
'ticketMessages', | |||
CollectionType::class, | |||
[ | |||
'entry_type' => TicketMessageType::class, | |||
'allow_add' => false, | |||
] | |||
); | |||
$builder->add( | |||
'submit', | |||
SubmitType::class, | |||
[ | |||
'label' => $this->translatorAdmin->transAction('save') | |||
] | |||
); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function configureOptions(OptionsResolver $resolver) | |||
{ | |||
$resolver->setDefaults( | |||
[ | |||
'data_class' => $this->em->getEntityName(TicketInterface::class), | |||
] | |||
); | |||
} | |||
} |
@@ -2,10 +2,9 @@ | |||
namespace Lc\SovBundle\Form\Ticket; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\SovBundle\Doctrine\EntityManager; | |||
use Lc\SovBundle\Model\Ticket\TicketMessageInterface; | |||
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; | |||
@@ -14,7 +13,7 @@ class TicketMessageType extends AbstractType | |||
{ | |||
protected $em; | |||
public function __construct(EntityManagerInterface $em) | |||
public function __construct(EntityManager $em) | |||
{ | |||
$this->em = $em; | |||
} | |||
@@ -24,28 +23,17 @@ class TicketMessageType extends AbstractType | |||
$builder->add( | |||
'message', | |||
TextareaType::class, | |||
array( | |||
[ | |||
'required' => true | |||
) | |||
) | |||
->add( | |||
'add', | |||
SubmitType::class, | |||
array( | |||
'label' => 'action.send', | |||
'attr' => array( | |||
'class' => 'btn btn-primary float-right' | |||
) | |||
) | |||
); | |||
] | |||
); | |||
} | |||
public function configureOptions(OptionsResolver $resolver) | |||
{ | |||
$resolver->setDefaults( | |||
[ | |||
'data_class' => $this->em->getClassMetadata(TicketMessageInterface::class)->getName(), | |||
'translation_domain' => 'lcshop' | |||
'data_class' => $this->em->getEntityName(TicketMessageInterface::class), | |||
] | |||
); | |||
} |
@@ -77,7 +77,7 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
protected $visitorToken; | |||
/** | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketMessageInterface", mappedBy="ticket", orphanRemoval=true) | |||
* @ORM\OneToMany(targetEntity="Lc\SovBundle\Model\Ticket\TicketMessageInterface", mappedBy="ticket", orphanRemoval=true, cascade={"persist", "remove"}) | |||
* @ORM\OrderBy({"id" = "ASC"}) | |||
*/ | |||
protected $ticketMessages; | |||
@@ -101,12 +101,37 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
} | |||
} | |||
public function getUserInfosTicket() | |||
{ | |||
$user = $this->getUser(); | |||
if ($user) { | |||
return '#' . $user->getId() . ' ' . $user->getName() . ' ' . $user->getEmail(); | |||
} else { | |||
return strtoupper($this->getVisitorLastname()) . ' ' . $this->getVisitorFirstname( | |||
) . ' ' . $this->getVisitorEmail(); | |||
} | |||
} | |||
public function getEmail() | |||
{ | |||
if ($this->getUser()) { | |||
return $this->getUser()->getEmail(); | |||
} else { | |||
return $this->getVisitorEmail(); | |||
} | |||
} | |||
public function getVisitorInfos() | |||
{ | |||
return strtoupper($this->getVisitorLastname()) . ' ' . $this->getVisitorFirstname( | |||
) . ' (' . $this->getVisitorEmail() . ')'; | |||
} | |||
public function getLastMessage() | |||
{ | |||
return $this->getTicketMessages()->last(); | |||
} | |||
public function getType(): ?string | |||
{ | |||
return $this->type; | |||
@@ -121,7 +146,7 @@ abstract class TicketModel extends AbstractLightEntity implements TicketInterfac | |||
public function getTypeLabel(): string | |||
{ | |||
return 'field.Ticket.typeOptions.' . $this->getType(); | |||
return 'entity.Ticket.fields.typeOptions.' . $this->getType(); | |||
} | |||
public function getStatus(): ?string |
@@ -1,6 +1,8 @@ | |||
table.table { | |||
.dropdown-actions { | |||
display: inline-block ; | |||
} | |||
.actions { | |||
white-space: nowrap; | |||
} | |||
} |
@@ -26,3 +26,7 @@ sov_admin_setting_global: | |||
path: /admin/setting/global | |||
controller: Lc\SovBundle\Controller\Setting\SettingAdminController::manageGlobal | |||
sov_admin_create_ticket: | |||
path: /admin/ticket/create | |||
controller: Lc\SovBundle\Controller\Ticket\TicketAdminController::create | |||
@@ -27,6 +27,7 @@ action: | |||
sort: Ordonner | |||
delete: Supprimer | |||
change: Changer | |||
detail: Voir | |||
index_children: Afficher les enfants | |||
index_parent: Retour au parent | |||
back_index: Retour à la liste | |||
@@ -51,6 +52,8 @@ entity: | |||
label: Page | |||
label_plurial: Pages | |||
Ticket: | |||
label: Ticket | |||
label_plurial: Tickets | |||
fields: | |||
visitorFirstName: Nom | |||
visitorLastName: Prénom | |||
@@ -60,11 +63,16 @@ entity: | |||
typeOptions: | |||
general-question: Questions générales | |||
technical-problem: Problème technique | |||
lastMessage: Dernier message | |||
statusOptions: | |||
open: Ouvert | |||
being-processed: En attente | |||
closed: Fermé | |||
default: | |||
fields: | |||
id: Id | |||
createdAt: Created at | |||
createdAt: Créé à | |||
user: Utilisateur | |||
firstname: Prénom | |||
lastname: Nom | |||
@@ -73,7 +81,7 @@ entity: | |||
position: Position | |||
description: Description | |||
file: Fichier | |||
status: Statut | |||
status: Status | |||
email: Email | |||
value: Valeur | |||
metaTitle: Meta title |
@@ -0,0 +1,83 @@ | |||
{% extends '@LcSov/adminlte/layout.html.twig' %} | |||
{% import '@LcSov/adminlte/macro/infobox.html.twig' as macro %} | |||
{% block content_title %} | |||
{{ 'detail'|lc_trans_admin_title(ea.getEntity().getFqcn(), {id: ea.getEntity().getInstance().getId()}) }} | |||
{% endblock %} | |||
{% block main %} | |||
{{ dump() }} | |||
<div class="row"> | |||
<div class="col-4"> | |||
{% embed '@LcSov/adminlte/embed/infobox.html.twig' %} | |||
{% block color %}blue{% endblock %} | |||
{% block icon %}fa fa-toggle-on{% endblock %} | |||
{% block title %}Status{% endblock %} | |||
{% block content %} | |||
{{ entity.instance.status }} | |||
{% endblock %} | |||
{% endembed %} | |||
{% embed '@LcSov/adminlte/embed/infobox.html.twig' %} | |||
{% block color %}blue{% endblock %} | |||
{% block icon %}fa fa-user{% endblock %} | |||
{% block title %}Utilisateur{% endblock %} | |||
{% block content %} | |||
{{ entity.instance.getUserInfosTicket() }} | |||
{% endblock %} | |||
{% endembed %} | |||
{{ macro.infobox('Date',entity.instance.createdAt|date('d/m/Y'), "yellow", "fa fa-calendar") }} | |||
{{ macro.infobox('Catégorie',entity.instance.getTypeLabel()|trans({},'admin'), "green", "fa fa-archive") }} | |||
</div> | |||
<div class="col-8"> | |||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||
{% block css %}card-primary{% endblock %} | |||
{% block header %} | |||
<h3 class="card-title"> | |||
Liste des messages | |||
</h3> | |||
{% endblock header %} | |||
{% block body_wrapper %} | |||
<div class="card-body row"> | |||
<div class="col-12 direct-chat-primary"> | |||
{% for message in entity.instance.ticketMessages %} | |||
<div class="direct-chat-msg {{ message.answerByAdmin ? 'right' }}"> | |||
<div class="direct-chat-infos clearfix"> | |||
<div class="direct-chat-name {{ message.answerByAdmin ? 'float-right' : 'float-left' }}"> | |||
{{ message.createdBy }} | |||
</div> | |||
<div class="direct-chat-timestamp {{ message.answerByAdmin ? 'float-left' : 'float-right' }}"> | |||
{{ message.createdAt|date('d/m/Y H:i') }} | |||
</div> | |||
</div> | |||
{% if message.answerByAdmin %} | |||
<div class="direct-chat-img align-items-center"> | |||
<i class="fa fa-user-circle" style="font-size: 2rem; color: red"></i> | |||
</div> | |||
{% else %} | |||
<div class="direct-chat-img align-items-center"> | |||
<i class="fa fa-user-circle" style="font-size: 2rem"></i> | |||
</div> | |||
{% endif %} | |||
<div class="direct-chat-text"> | |||
<p>{{ message.message|nl2br }}</p> | |||
{% if message.imageFilename is not null %} | |||
<i>Photo jointe au message : </i> <br/> | |||
<a href="{{ lc_liip(message.imageFilename, 'big') }}" | |||
data-toggle="lightbox"> | |||
<img src="{{ lc_liip(message.imageFilename, 'thumb') }}" | |||
alt="Illustration ticket"/> | |||
</a> | |||
{% endif %} | |||
</div> | |||
</div> | |||
{% endfor %} | |||
</div> | |||
</div> | |||
{% endblock %} | |||
{% endembed %} | |||
</div> | |||
</div> | |||
{% endblock %} |
@@ -0,0 +1 @@ | |||
{{ entity.instance.getEmail() }} |
@@ -0,0 +1,7 @@ | |||
{% 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 }} |
@@ -0,0 +1,10 @@ | |||
{% import "@LcSov/adminlte/macro/badge.html.twig" as macro %} | |||
{% set status = entity.instance.status %} | |||
{% if status == 'open' %} | |||
{{ macro.badge_success(('entity.Ticket.fields.statusOptions.'~entity.instance.status)|trans({},'admin')) }} | |||
{% elseif status == 'being-processed' %} | |||
{{ macro.badge_warning(('entity.Ticket.fields.statusOptions.'~entity.instance.status)|trans({},'admin')) }} | |||
{% elseif status == 'closed' %} | |||
{{ macro.badge_danger(('entity.Ticket.fields.statusOptions.'~entity.instance.status)|trans({},'admin')) }} | |||
{% endif %} |
@@ -0,0 +1 @@ | |||
{{ entity.instance.getUsername() }} |
@@ -0,0 +1,19 @@ | |||
{% extends '@LcSov/adminlte/layout.html.twig' %} | |||
{% block content_title %} | |||
{# {{ 'ticket.profile'|lc_trans_admin_title }}#} | |||
Créer un ticket | |||
{% endblock %} | |||
{% block main %} | |||
<div class="col-8"> | |||
{% embed '@LcSov/adminlte/embed/card.html.twig' %} | |||
{% block header_wrapper %}{% endblock %} | |||
{% block body %} | |||
{% form_theme form '@LcSov/adminlte/crud/form_theme.html.twig' %} | |||
{{ form(form) }} | |||
{% endblock %} | |||
{% block footer_wrapper %}{% endblock %} | |||
{% endembed %} | |||
</div> | |||
{% endblock main %} |
@@ -0,0 +1,8 @@ | |||
<div class="info-box"> | |||
<!-- Apply any bg-* class to to the icon to color it --> | |||
<span class="info-box-icon bg-{% block color %}{% endblock %}"><i class="{% block icon %}{% endblock %}"></i></span> | |||
<div class="info-box-content"> | |||
<span class="info-box-text">{% block title %}{% endblock %}</span> | |||
<span class="info-box-number">{% block content %}{% endblock %}</span> | |||
</div> | |||
</div> |
@@ -0,0 +1,15 @@ | |||
{% macro badge_success(title) %} | |||
{{ _self.badge('success', title) }} | |||
{% endmacro %} | |||
{% macro badge_warning(title) %} | |||
{{ _self.badge('warning', title) }} | |||
{% endmacro %} | |||
{% macro badge_danger(title) %} | |||
{{ _self.badge('danger', title) }} | |||
{% endmacro %} | |||
{% macro badge(status, title) %} | |||
<span class="badge badge-{{ status }}">{{ title }}</span> | |||
{% endmacro %} |
@@ -1,10 +1,10 @@ | |||
{% macro infobox(title, number, color, icon) %} | |||
{% macro infobox(title, content, color, icon) %} | |||
<div class="info-box"> | |||
<!-- Apply any bg-* class to to the icon to color it --> | |||
<span class="info-box-icon bg-{{ color }}"><i class="{{ icon }}"></i></span> | |||
<div class="info-box-content"> | |||
<span class="info-box-text">{{ title }}</span> | |||
<span class="info-box-number">{{ number }}</span> | |||
<span class="info-box-number">{{ content }}</span> | |||
</div> | |||
<!-- /.info-box-content --> | |||
</div> |