@@ -17,6 +17,7 @@ use Lc\ShopBundle\Context\StatusInterface; | |||
use Lc\ShopBundle\Context\TreeInterface; | |||
use Lc\ShopBundle\Form\Backend\Common\AbstractEditPositionType; | |||
use Lc\ShopBundle\Services\Utils; | |||
use Lc\ShopBundle\Services\UtilsManager; | |||
use Mailjet\MailjetSwiftMailer\SwiftMailer\MailjetTransport; | |||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
@@ -39,16 +40,16 @@ class AdminController extends EasyAdminController | |||
protected $orderUtils; | |||
protected $translator; | |||
public function __construct(Security $security, UserManagerInterface $userManager, EntityManagerInterface $em, Utils $utils, | |||
MerchantUtilsInterface $merchantUtils, MailjetTransport $mailjetTransport, OrderUtilsInterface $orderUtils, TranslatorInterface $translator) | |||
public function __construct(Security $security, UserManagerInterface $userManager, EntityManagerInterface $em, | |||
MailjetTransport $mailjetTransport,UtilsManager $utilsManager, TranslatorInterface $translator) | |||
{ | |||
$this->security = $security; | |||
$this->userManager = $userManager; | |||
$this->em = $em; | |||
$this->utils = $utils; | |||
$this->merchantUtils = $merchantUtils; | |||
$this->mailjetTransport = $mailjetTransport; | |||
$this->orderUtils = $orderUtils; | |||
$this->utils = $utilsManager->getUtils(); | |||
$this->merchantUtils = $utilsManager->getMerchantUtils(); | |||
$this->orderUtils = $utilsManager->getOrderUtils() ;; | |||
$this->translator = $translator; | |||
} | |||
@@ -70,7 +71,7 @@ class AdminController extends EasyAdminController | |||
/** | |||
* Réécriture de show action pr rediriger vers l'édition | |||
*/ | |||
public function showAction() | |||
/* public function showAction() | |||
{ | |||
$id = $this->request->query->get('id'); | |||
$entity = $this->request->query->get('entity'); | |||
@@ -80,7 +81,7 @@ class AdminController extends EasyAdminController | |||
'entity' => $entity, | |||
'id' => $id | |||
]); | |||
} | |||
}*/ | |||
/** |
@@ -43,11 +43,11 @@ class ReminderController extends AdminController | |||
public function setReminderDoneAction(){ | |||
$id = $this->request->query->get('id'); | |||
$done = $this->request->query->get('done'); | |||
dump($done); | |||
$easyadmin = $this->request->attributes->get('easyadmin'); | |||
$reminder = $easyadmin['item']; | |||
$reminder->setDone(true); | |||
$reminder->setDone($done); | |||
$this->em->persist($reminder); | |||
$this->em->flush(); | |||
return $this->redirectToReferrer(); |
@@ -0,0 +1,86 @@ | |||
<?php | |||
namespace Lc\ShopBundle\Controller\Backend; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use FOS\UserBundle\Model\UserManagerInterface; | |||
use Lc\ShopBundle\Form\Backend\Ticket\TicketMessageType; | |||
use Lc\ShopBundle\Form\Backend\Ticket\TicketStatusType; | |||
use Lc\ShopBundle\Services\UtilsManager; | |||
use Mailjet\MailjetSwiftMailer\SwiftMailer\MailjetTransport; | |||
use Symfony\Component\HttpFoundation\Response; | |||
use Symfony\Component\Security\Core\Security; | |||
use Symfony\Contracts\Translation\TranslatorInterface; | |||
class TicketController extends AdminController | |||
{ | |||
protected $ticketUtils; | |||
public function __construct(Security $security, UserManagerInterface $userManager, EntityManagerInterface $em, MailjetTransport $mailjetTransport, UtilsManager $utilsManager, TranslatorInterface $translator) | |||
{ | |||
$this->ticketUtils = $utilsManager->getTicketUtils(); | |||
parent::__construct($security, $userManager, $em, $mailjetTransport, $utilsManager, $translator); | |||
} | |||
/** | |||
* The method that is executed when the user performs a 'show' action on an entity. | |||
* | |||
* @return Response | |||
*/ | |||
public function renderTicketTemplate($actionName, $templatePath, array $parameters = []) | |||
{ | |||
if ($actionName == 'show') { | |||
$parameters['form_add_ticket_message'] = $this->createCustomForm(TicketMessageType::class, 'newMessageTicket', $parameters, false)->createView(); | |||
$parameters['form_ticket_status'] = $this->createCustomForm(TicketStatusType::class, 'ticketStatus', $parameters)->createView(); | |||
} | |||
return parent::renderTemplate($actionName, $templatePath, $parameters); | |||
} | |||
public function ticketStatusAction(){ | |||
$easyadmin = $this->request->attributes->get('easyadmin'); | |||
$ticket = $easyadmin['item']; | |||
$formTicketStatusForm = $this->createForm(TicketStatusType::class, $ticket); | |||
$formTicketStatusForm->handleRequest($this->request); | |||
if ($formTicketStatusForm->isSubmitted() && $formTicketStatusForm->isValid()) { | |||
$this->em->persist($ticket); | |||
$this->em->flush(); | |||
$this->utils->addFlash('success', 'success.ticket.statusChange'); | |||
} else { | |||
$this->utils->addFlash('error', $formTicketStatusForm->getErrors()); | |||
} | |||
$response['flashMessages'] = $this->utils->getFlashMessages(); | |||
return new Response(json_encode($response)); | |||
} | |||
public function newMessageTicketAction(){ | |||
$easyadmin = $this->request->attributes->get('easyadmin'); | |||
$ticket = $easyadmin['item']; | |||
$formAddTicketMessage = $this->createForm(TicketMessageType::class); | |||
$formAddTicketMessage->handleRequest($this->request); | |||
if ($formAddTicketMessage->isSubmitted() && $formAddTicketMessage->isValid()) { | |||
$this->ticketUtils->createTicketMessage(array( | |||
'ticket'=>$ticket, | |||
'message'=> $formAddTicketMessage->get('message')->getData(), | |||
'answerByAdmin'=>true | |||
)); | |||
$this->utils->addFlash('success', 'success.ticket.addMessage'); | |||
} else { | |||
$this->utils->addFlash('error', $formAddTicketMessage->getErrors()); | |||
} | |||
return $this->redirectToRoute('easyadmin', [ | |||
'action' => 'show', | |||
'entity' => 'Ticket', | |||
'id' => $ticket->getId() | |||
]); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
namespace Lc\ShopBundle\Form\Backend\Ticket; | |||
use App\Entity\Product; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\ShopBundle\Context\CreditHistoryInterface; | |||
use Lc\ShopBundle\Context\OrderProductInterface; | |||
use Lc\ShopBundle\Context\OrderReductionCartInterface; | |||
use Lc\ShopBundle\Context\OrderShopInterface; | |||
use Lc\ShopBundle\Context\OrderUtilsInterface; | |||
use Lc\ShopBundle\Context\ProductInterface; | |||
use Lc\ShopBundle\Context\ReductionCartInterface; | |||
use Lc\ShopBundle\Context\ReductionCreditInterface; | |||
use Lc\ShopBundle\Context\TicketMessageInterface; | |||
use Lc\ShopBundle\Form\DataTransformer\ProductToIdTransformer; | |||
use Lc\ShopBundle\Model\CreditHistory; | |||
use Lc\ShopBundle\Services\Utils; | |||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\Extension\Core\Type\ButtonType; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
use Symfony\Component\Form\Extension\Core\Type\DateType; | |||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; | |||
use Symfony\Component\Form\Extension\Core\Type\MoneyType; | |||
use Symfony\Component\Form\Extension\Core\Type\NumberType; | |||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
class TicketMessageType extends AbstractType | |||
{ | |||
protected $em; | |||
public function __construct(EntityManagerInterface $em) | |||
{ | |||
$this->em = $em; | |||
} | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
$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' | |||
]); | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
<?php | |||
namespace Lc\ShopBundle\Form\Backend\Ticket; | |||
use App\Entity\Product; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\ShopBundle\Context\CreditHistoryInterface; | |||
use Lc\ShopBundle\Context\OrderProductInterface; | |||
use Lc\ShopBundle\Context\OrderReductionCartInterface; | |||
use Lc\ShopBundle\Context\OrderShopInterface; | |||
use Lc\ShopBundle\Context\OrderUtilsInterface; | |||
use Lc\ShopBundle\Context\ProductInterface; | |||
use Lc\ShopBundle\Context\ReductionCartInterface; | |||
use Lc\ShopBundle\Context\ReductionCreditInterface; | |||
use Lc\ShopBundle\Context\TicketInterface; | |||
use Lc\ShopBundle\Context\TicketMessageInterface; | |||
use Lc\ShopBundle\Form\DataTransformer\ProductToIdTransformer; | |||
use Lc\ShopBundle\Model\CreditHistory; | |||
use Lc\ShopBundle\Model\Ticket; | |||
use Lc\ShopBundle\Services\Utils; | |||
use Symfony\Bridge\Doctrine\Form\Type\EntityType; | |||
use Symfony\Component\Form\AbstractType; | |||
use Symfony\Component\Form\Extension\Core\Type\ButtonType; | |||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; | |||
use Symfony\Component\Form\Extension\Core\Type\DateType; | |||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; | |||
use Symfony\Component\Form\Extension\Core\Type\MoneyType; | |||
use Symfony\Component\Form\Extension\Core\Type\NumberType; | |||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextareaType; | |||
use Symfony\Component\Form\Extension\Core\Type\TextType; | |||
use Symfony\Component\Form\FormBuilderInterface; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
class TicketStatusType extends AbstractType | |||
{ | |||
protected $em; | |||
public function __construct(EntityManagerInterface $em) | |||
{ | |||
$this->em = $em; | |||
} | |||
public function buildForm(FormBuilderInterface $builder, array $options) | |||
{ | |||
$builder->add('ticketStatus', ChoiceType::class, array( | |||
'choices'=>array( | |||
'field.Ticket.ticketStatusOptions.'.Ticket::TICKET_STATUS_OPEN => Ticket::TICKET_STATUS_OPEN, | |||
'field.Ticket.ticketStatusOptions.'.Ticket::TICKET_STATUS_BEING_PROCESSED => Ticket::TICKET_STATUS_BEING_PROCESSED, | |||
'field.Ticket.ticketStatusOptions.'.Ticket::TICKET_STATUS_CLOSED => Ticket::TICKET_STATUS_CLOSED, | |||
), | |||
'required'=>true, | |||
'expanded'=>true | |||
)); | |||
} | |||
public function configureOptions(OptionsResolver $resolver) | |||
{ | |||
$resolver->setDefaults([ | |||
'data_class' => $this->em->getClassMetadata(TicketInterface::class)->getName(), | |||
'translation_domain' => 'lcshop' | |||
]); | |||
} | |||
} |
@@ -116,6 +116,12 @@ abstract class OrderShop extends AbstractEntity implements FilterMerchantInterfa | |||
*/ | |||
protected $updatedBy; | |||
/** | |||
* @ORM\OneToMany(targetEntity="Lc\ShopBundle\Context\TicketInterface", mappedBy="orderShop") | |||
*/ | |||
protected $tickets; | |||
public function __construct() | |||
{ | |||
$this->orderStatusHistories = new ArrayCollection(); | |||
@@ -503,6 +509,37 @@ abstract class OrderShop extends AbstractEntity implements FilterMerchantInterfa | |||
} | |||
/** | |||
* @return Collection|Ticket[] | |||
*/ | |||
public function getTickets(): Collection | |||
{ | |||
return $this->tickets; | |||
} | |||
public function addTicket(Ticket $ticket): self | |||
{ | |||
if (!$this->tickets->contains($ticket)) { | |||
$this->tickets[] = $ticket; | |||
$ticket->setOrderShop($this); | |||
} | |||
return $this; | |||
} | |||
public function removeTicket(Ticket $ticket): self | |||
{ | |||
if ($this->tickets->contains($ticket)) { | |||
$this->tickets->removeElement($ticket); | |||
// set the owning side to null (unless already changed) | |||
if ($ticket->getOrderShop() === $this) { | |||
$ticket->setOrderShop(null); | |||
} | |||
} | |||
return $this; | |||
} | |||
public function isValid() { | |||
if($this->getOrderStatus() && in_array($this->getOrderStatus()->getAlias(), OrderStatus::$statusAliasAsValid) > 0) { | |||
return true ; |
@@ -54,11 +54,6 @@ abstract class Ticket extends AbstractEntity implements FilterMerchantInterface | |||
*/ | |||
protected $type; | |||
/** | |||
* @ORM\Column(type="text", nullable=true) | |||
*/ | |||
protected $typeHelp; | |||
/** | |||
* @ORM\Column(type="string", length=32) | |||
*/ | |||
@@ -114,6 +109,20 @@ abstract class Ticket extends AbstractEntity implements FilterMerchantInterface | |||
$this->ticketMessages = new ArrayCollection(); | |||
} | |||
public function getUsername(){ | |||
if($this->getUser()){ | |||
return $this->getUser()->getName(); | |||
}else{ | |||
return strtoupper($this->getVisitorLastname()).' '.$this->getVisitorFirstname(); | |||
} | |||
} | |||
public function getVisitorInfos(){ | |||
return strtoupper($this->getVisitorLastname()).' '.$this->getVisitorFirstname(). ' ('.$this->getVisitorEmail().')'; | |||
} | |||
public function getMerchant(): ?MerchantInterface | |||
{ | |||
return $this->merchant; | |||
@@ -143,18 +152,6 @@ abstract class Ticket extends AbstractEntity implements FilterMerchantInterface | |||
return 'field.Ticket.typeOptions.'.$this->getType() ; | |||
} | |||
public function getTypeHelp(): ?string | |||
{ | |||
return $this->typeHelp; | |||
} | |||
public function setTypeHelp(?string $typeHelp): self | |||
{ | |||
$this->typeHelp = $typeHelp; | |||
return $this; | |||
} | |||
public function getTicketStatus(): ?string | |||
{ | |||
return $this->ticketStatus; |
@@ -39,6 +39,16 @@ abstract class TicketMessage extends AbstractEntity | |||
*/ | |||
protected $ticket; | |||
/** | |||
* @ORM\Column(type="boolean", nullable=true) | |||
*/ | |||
protected $answerByAdmin; | |||
public function __toString() | |||
{ | |||
return $this->message; | |||
} | |||
public function getMessage(): ?string | |||
{ | |||
return $this->message; | |||
@@ -62,4 +72,16 @@ abstract class TicketMessage extends AbstractEntity | |||
return $this; | |||
} | |||
public function getAnswerByAdmin(): ?bool | |||
{ | |||
return $this->answerByAdmin; | |||
} | |||
public function setAnswerByAdmin(?bool $answerByAdmin): self | |||
{ | |||
$this->answerByAdmin = $answerByAdmin; | |||
return $this; | |||
} | |||
} |
@@ -109,7 +109,12 @@ abstract class User extends UserModelFOS | |||
public function getSummary() | |||
{ | |||
return strtoupper($this->getLastname()).' '.$this->getFirstname(). ' ('.$this->getEmail().')'; | |||
return '#'.$this->getId().' '.strtoupper($this->getLastname()).' '.$this->getFirstname(). ' ('.$this->getEmail().')'; | |||
} | |||
public function getName() | |||
{ | |||
return strtoupper($this->getLastname()).' '.$this->getFirstname(); | |||
} | |||
public function setEmail($email) |
@@ -245,3 +245,5 @@ table th .select2-container--default .select2-selection--single{padding:0.3rem 0 | |||
.todo-list > li{position: relative;} | |||
.todo-list > li .text{margin-left: 30px;} | |||
.todo-list > li .tools {position: absolute; top: 4px; right: 15px; } | |||
#addTicketMessageForm{margin-top: 30px; border-top:2px dotted #eee; padding-top: 30px} |
@@ -0,0 +1,14 @@ | |||
jQuery(document).ready(function () { | |||
$('.ticket-status').on("change", function(){ | |||
$.ajax({ | |||
url: $('#ticketStatusForm').prop('action'), | |||
method: "POST", | |||
data: $('#ticketStatusForm').serialize(), | |||
dataType: "json", | |||
success: function (response) { | |||
setFlashMessages(response.flashMessages); | |||
} | |||
}); | |||
}); | |||
}); |
@@ -49,6 +49,8 @@ group: | |||
orderPayment: Ajouter un règlement | |||
orderStatus: Changer de status | |||
addRedeliveryOrderProduct: Ajouter une relivraison | |||
Ticket: | |||
listMessages: Liste des messages | |||
None: Aucune valeur | |||
label.form.empty_value: Choisissez une option | |||
form.label.delete: Supprimer l'image | |||
@@ -67,6 +69,9 @@ success: | |||
credit: | |||
debited: Le compte prépayé a bien été débité | |||
added: Le compte a bien été crédité | |||
ticket: | |||
statusChange: Le status a bien été modifié | |||
addMessage: Le message a bien été envoyé | |||
error: | |||
form: | |||
submitted: Une erreur est survenue à la soumission du formulaire | |||
@@ -107,7 +112,7 @@ field: | |||
deliveryPointSale: Lieu de livraison | |||
deliveryAvailabilty: Créneau de livraison | |||
id: Id | |||
status: En ligne | |||
status: Statut | |||
statusOptions: | |||
offline: <span class="badge badge-danger">Hors ligne</span> | |||
online: <span class="badge badge-success">En ligne</span> | |||
@@ -139,6 +144,7 @@ field: | |||
priceWithTax: Prix de vente TTC | |||
username: Nom d'utilisateur | |||
user: Utilisateur | |||
visitor: Visiteur | |||
email: E-mail | |||
plainPassword: Mot de passe | |||
roles: Rôle attribué | |||
@@ -177,6 +183,7 @@ field: | |||
isPublic: Publique | |||
isDepository: Dépôt | |||
productCategories: Catégories | |||
category: Catégorie | |||
parent: Parent | |||
date: Date | |||
content: Contenu | |||
@@ -343,6 +350,7 @@ field: | |||
usersHelp: Laissez vide si vous souhaitez ajouter ce pense-bête à tout les utilisateurs | |||
Ticket: | |||
type: Catégorie | |||
message: Votre réponse | |||
typeOptions: | |||
general-question: Questions générales | |||
product-unavailable: Produit manquant | |||
@@ -360,6 +368,7 @@ action: | |||
switchMerchant: Votre hub | |||
show: Voir | |||
choiceFile: Parcourir | |||
send: Envoyer | |||
edit: Éditer | |||
search: Rechercher | |||
delete: Supprimer |
@@ -0,0 +1,9 @@ | |||
<div class="info-box"> | |||
<span class="info-box-icon {% block class %}bg-info{% endblock %}"> | |||
<i class="fa fa-{% block icon %}bg-info{% endblock %}"></i></span> | |||
<div class="info-box-content"> | |||
<span class="info-box-text">{% block label %}{% endblock %}</span> | |||
<strong>{% block value %}{% endblock %}</strong> | |||
</div> | |||
</div> |
@@ -1,21 +0,0 @@ | |||
<div class="card {% block style %}{% endblock %}"> | |||
<div class="card-header"> | |||
{% block header %} | |||
<h3 class="card-title"> | |||
{% block title %}{% endblock title %} | |||
</h3> | |||
{% block tools %}{% endblock tools %} | |||
{% endblock header %} | |||
</div> | |||
<div class="card-body"> | |||
{% block content %} | |||
{% endblock %} | |||
</div> | |||
<div class="card-footer"> | |||
{% block footer %} | |||
{% endblock %} | |||
</div> | |||
</div> |
@@ -1,3 +1,30 @@ | |||
{% macro card_start(zone = "default", card ='primary', fullWidth = false ) %} | |||
<div class="card card-{{ card }}"> | |||
<div class="card-header"> | |||
<h3 class="card-title"> | |||
{% set label = "group."~zone %} | |||
{{ label|trans({}, 'lcshop')|raw }} | |||
</h3> | |||
</div> | |||
<div class="card-body {{ fullWidth == true ? 'p-0' : 'row' }}"> | |||
{% endmacro card_start %} | |||
{% macro card_overlay(attr) %} | |||
</div> | |||
<div v-if="{{ attr }}==true" class="overlay"> | |||
<i class="fas fa-2x fa-sync-alt"></i> | |||
</div> | |||
{% endmacro card_overlay %} | |||
{% macro card_end(noCol = false) %} | |||
</div> | |||
</div> | |||
{% endmacro card_end %} | |||
{% macro startCard(col, zone = "default", card ='primary', fullWidth = false ) %} | |||
{% if col > 0 %} | |||
<div class="col-{{ col }}">{% endif %} | |||
@@ -193,3 +220,16 @@ | |||
} | |||
</script> | |||
{% endmacro reductionCatalogFormValues %} | |||
{% macro box_info(class="bg-info", icon, label, value) %} | |||
{% embed '@LcShop/backend/default/block/embed_box.twig' %} | |||
{% trans_default_domain 'lcshop' %} | |||
{% block class %}{{ class }}{% endblock %} | |||
{% block icon %}{{ icon }}{% endblock %} | |||
{% block label %}{{ label }}{% endblock %} | |||
{% block value %} | |||
{{ value }} | |||
{% endblock %} | |||
{% endembed %} | |||
{% endmacro box_info %} |
@@ -137,7 +137,7 @@ | |||
{% block aside_logo %} | |||
<a class="brand-link {{ easyadmin_config('site_name')|length > 14 ? 'logo-long' }}" | |||
title="{{ easyadmin_config('site_name')|striptags }}" href="{{ path('easyadmin') }}"> | |||
{{ easyadmin_config('site_name')|raw }} <span>Besançon</span> | |||
{{ easyadmin_config('site_name')|raw }} | |||
</a> | |||
{% endblock aside_logo %} | |||
<!-- Sidebar --> |
@@ -7,8 +7,7 @@ | |||
item.type == 'link' ? item.url : | |||
item.type == 'route' ? path(item.route, item.params) : | |||
item.type == 'entity' ? path('easyadmin', { entity: item.entity, action: 'list' }|merge(menu_params)|merge(item.params)) : | |||
item.type == 'empty' ? '#' : '' | |||
%} | |||
item.type == 'empty' ? '#' : '' %} | |||
{# if the URL generated for the route belongs to the backend, regenerate | |||
the URL to include the menu_params to display the selected menu item | |||
@@ -21,10 +20,11 @@ | |||
<a href="{{ path }}" | |||
class="nav-link {{ item.css_class|default('') }} {{ active ? 'active' }}" | |||
{% if item.target|default(false) %}target="{{ item.target }}"{% endif %} | |||
{% if item.rel|default(false) %}rel="{{ item.rel }}"{% endif %}> | |||
{% if item.rel|default(false) %}rel="{{ item.rel }}"{% endif %}> | |||
{% if item.icon is not empty %}<i class="fa fa-fw {{ item.icon }}"></i>{% endif %} | |||
<p>{{ item.label|trans(domain = translation_domain) }} | |||
{% if item.children|default([]) is not empty %}<i class="right fas fa-angle-left"></i>{% endif %} | |||
{% if item.params.count_menu_item is defined %}<span class="badge badge-info right">{{ count_menu_items(item.params.count_menu_item) }}</span>{% endif %} | |||
</p> | |||
</a> | |||
{% endif %} | |||
@@ -46,23 +46,23 @@ | |||
{% set is_selected_submenu = is_selected_menu and app.request.query.get('submenuIndex')|default(-1) != -1 %} | |||
{% if easyadmin_is_granted(item.permission) %} | |||
<li class="{{ item.type == 'divider' ? 'nav-header' : 'nav-item'}} {{ item.children is not empty ? 'treeview' }} {{ is_selected_menu ? 'menu-open' }}"> | |||
{{ helper.render_menu_item(item, _translation_domain, is_selected_menu) }} | |||
<li class="{{ item.type == 'divider' ? 'nav-header' : 'nav-item' }} {{ item.children is not empty ? 'treeview' }} {{ is_selected_menu ? 'menu-open' }}"> | |||
{{ helper.render_menu_item(item, _translation_domain, is_selected_menu) }} | |||
{% if item.children|default([]) is not empty %} | |||
<ul class="nav nav-treeview"> | |||
{% for subitem in item.children %} | |||
{% block menu_subitem %} | |||
{% if easyadmin_is_granted(subitem.permission) %} | |||
<li class="nav-item "> | |||
{{ helper.render_menu_item(subitem, _translation_domain, is_selected_menu and app.request.query.get('submenuIndex')|default(-1) == subitem.submenu_index ? true) }} | |||
</li> | |||
{% endif %} | |||
{% endblock menu_subitem %} | |||
{% endfor %} | |||
</ul> | |||
{% endif %} | |||
</li> | |||
{% if item.children|default([]) is not empty %} | |||
<ul class="nav nav-treeview"> | |||
{% for subitem in item.children %} | |||
{% block menu_subitem %} | |||
{% if easyadmin_is_granted(subitem.permission) %} | |||
<li class="nav-item "> | |||
{{ helper.render_menu_item(subitem, _translation_domain, is_selected_menu and app.request.query.get('submenuIndex')|default(-1) == subitem.submenu_index ? true) }} | |||
</li> | |||
{% endif %} | |||
{% endblock menu_subitem %} | |||
{% endfor %} | |||
</ul> | |||
{% endif %} | |||
</li> | |||
{% endif %} | |||
{% endblock menu_item %} | |||
{% endfor %} |
@@ -0,0 +1,92 @@ | |||
{% extends '@LcShop/backend/default/show.html.twig' %} | |||
{% import '@LcShop/backend/default/block/macros.html.twig' as macros %} | |||
{% trans_default_domain 'lcshop' %} | |||
{% block main %} | |||
<div class="row"> | |||
<div class="col-4"> | |||
{% embed '@LcShop/backend/default/block/embed_box.twig' %} | |||
{% trans_default_domain 'lcshop' %} | |||
{% block class %}bg-info{% endblock %} | |||
{% block icon %}toggle-on{% endblock %} | |||
{% block label %} {{ "field.default.status"|trans }}{% endblock %} | |||
{% block value %} | |||
{{ form_start(form_ticket_status,{'attr' : {'id' : 'ticketStatusForm'}}) }} | |||
{% form_theme form_ticket_status '@LcShop/backend/form/custom_bootstrap_4.html.twig' %} | |||
{% for field in form_ticket_status.ticketStatus %} | |||
{{ form_widget(field, {'attr': {"class" : 'ticket-status'}}) }} | |||
{% endfor %} | |||
{{ form_end(form_ticket_status) }} | |||
{% endblock %} | |||
{% endembed %} | |||
{% if entity.user %} | |||
{{ macros.box_info('bg-info', 'user', "field.default.user"|trans, entity.user.summary) }} | |||
{% else %} | |||
{{ macros.box_info('bg-info', 'user-secret', "field.default.visitor"|trans, entity.user ? entity.user.summary : entity.visitorInfos) }} | |||
{% endif %} | |||
{{ macros.box_info('bg-warning', 'calendar', "field.default.date"|trans, entity.createdAt|date('d/m/Y')) }} | |||
{% set trad = "field.Ticket.typeOptions."~entity.type %} | |||
{{ macros.box_info('bg-success', 'archive', "field.default.category"|trans, trad|trans) }} | |||
{% set trad = "field.Ticket.ticketStatusOptions."~entity.ticketStatus %} | |||
{% if entity.orderShop is not null %} | |||
{{ macros.box_info('bg-danger', 'credit-card', "field.default.order"|trans, entity.orderShop.reference) }} | |||
{% endif %} | |||
</div> | |||
<div class="col-8"> | |||
{{ macros.card_start('Ticket.listMessages') }} | |||
<div class="col-12 direct-chat-primary"> | |||
{% for message in entity.ticketMessages %} | |||
<div class="direct-chat-msg {{ message.answerByAdmin ? 'right' }}"> | |||
<div class="direct-chat-infos clearfix"> | |||
<span class="direct-chat-name {{ message.answerByAdmin ? 'float-right' : 'float-left' }}"> | |||
{{ entity.username }} | |||
</span> | |||
<span class="direct-chat-timestamp {{ message.answerByAdmin ? 'float-left' : 'float-right' }}"> | |||
{{ message.createdAt|date('d/m/Y H:i') }} | |||
</span> | |||
</div> | |||
{% if message.answerByAdmin %} | |||
<img src="{{ asset('assets/img/backend/logo-pdl.png') }}" alt="" class="direct-chat-img"/> | |||
{% 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"> | |||
{{ message.message|nl2br }} | |||
</div> | |||
</div> | |||
{% endfor %} | |||
</div> | |||
<hr /> | |||
{{ form_start(form_add_ticket_message, {"attr" : {"class" : 'col-12', 'id' : 'addTicketMessageForm'}}) }} | |||
{% form_theme form_add_ticket_message '@LcShop/backend/form/custom_bootstrap_4.html.twig' %} | |||
<div class="row"> | |||
<div class="col-12"> | |||
{{ form_row(form_add_ticket_message.message) }} | |||
</div> | |||
</div> | |||
{{ form_end(form_add_ticket_message) }} | |||
{{ macros.card_end('ticketMessages') }} | |||
<div> | |||
</div> | |||
</div> | |||
</div> | |||
{% endblock %} | |||
{% block script_javascript %} | |||
{{ parent() }} | |||
<script src="{{ asset('bundles/lcshop/js/backend/script/ticket/init-edit.js') }}"></script> | |||
{% endblock %} |
@@ -68,12 +68,16 @@ class TicketUtils | |||
$ticketMessage->setStatus(1) ; | |||
$ticketMessage->setTicket($ticket) ; | |||
$ticketMessage->setMessage($params['message']) ; | |||
if(isset($params['answerByAdmin']) && $params['answerByAdmin']) { | |||
$ticketMessage->setAnswerByAdmin($params['answerByAdmin']) ; | |||
} | |||
$this->em->persist($ticketMessage); | |||
if(isset($params['closeTicket']) && $params['closeTicket']) { | |||
$ticket->setTicketStatus(Ticket::TICKET_STATUS_CLOSED) ; | |||
} | |||
$ticket->setUpdatedAt(new \DateTime()) ; | |||
$this->em->persist($ticket); | |||
@@ -4,6 +4,7 @@ namespace Lc\ShopBundle\Twig; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\ShopBundle\Context\ReductionCartInterface; | |||
use Lc\ShopBundle\Context\TicketInterface; | |||
use Symfony\Contracts\Translation\TranslatorInterface; | |||
use Twig\Extension\AbstractExtension; | |||
use Twig\TwigFilter; | |||
@@ -26,6 +27,7 @@ class BackendTwigExtension extends AbstractExtension | |||
{ | |||
return array( | |||
new TwigFunction('list_reduction_codes', [$this, 'getListReductionCodes']), | |||
new TwigFunction('count_menu_items', [$this, 'countMenuItems']), | |||
); | |||
} | |||
@@ -72,7 +74,16 @@ class BackendTwigExtension extends AbstractExtension | |||
} | |||
; | |||
return $codesToReturn; | |||
} | |||
public function countMenuItems($entityName){ | |||
switch($entityName){ | |||
case 'ticket' : | |||
$ticketRepo = $this->em->getRepository(TicketInterface::class); | |||
return $ticketRepo->countByTicketStatus('open'); | |||
} | |||
} | |||
} |