diff --git a/Controller/Announcement.php b/Controller/Announcement.php new file mode 100755 index 0000000..2dcc0f0 --- /dev/null +++ b/Controller/Announcement.php @@ -0,0 +1,124 @@ +translator = $translator; + $this->userService = $userService; + } + + public function listAnnouncement(Request $request) + { + if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_KNOWLEDGEBASE')) { + return $this->redirect($this->generateUrl('helpdesk_member_dashboard')); + } + + return $this->render('@UVDeskSupportCenter/Staff/Announcement/listAnnouncement.html.twig'); + } + + public function listAnnouncementXHR(Request $request) + { + $json = array(); + $repository = $this->getDoctrine()->getRepository('UVDeskSupportCenterBundle:Announcement'); + $json = $repository->getAllAnnouncements($request->query, $this->container); + $response = new Response(json_encode($json)); + $response->headers->set('Content-Type', 'application/json'); + return $response; + } + + public function updateAnnouncement(Request $request) + { + if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_KNOWLEDGEBASE')) { + return $this->redirect($this->generateUrl('helpdesk_member_dashboard')); + } + + $em = $this->getDoctrine()->getManager(); + + if($request->attributes->get('announcementId')){ + $announcement = $this->getDoctrine()->getRepository('UVDeskSupportCenterBundle:Announcement') + ->findOneBy([ + 'id' => $request->attributes->get('announcementId') + ]); + $announcement->setCreatedAt(new \DateTime('now')); + if(!$announcement) + $this->noResultFound(); + } else { + $announcement = new MarketingAnnouncement; + $announcement->setCreatedAt(new \DateTime('now')); + } + + if($request->getMethod() == "POST") { + $request = $request->request->get('announcement_form'); + $group = $em->getRepository('UVDeskCoreFrameworkBundle:SupportGroup')->find($request['group']); + + $announcement->setTitle($request['title']); + $announcement->setPromoText($request['promotext']); + $announcement->setPromotag($request['promotag']); + $announcement->setTagColor($request['tagColor']); + $announcement->setLinkText($request['linkText']); + $announcement->setLinkURL($request['linkURL']); + $announcement->setIsActive($request['status']); + $announcement->setGroup($group); + $em->persist($announcement); + $em->flush(); + + $this->addFlash('success', 'Success! Announcement data saved successfully.'); + return $this->redirect($this->generateUrl('helpdesk_member_knowledgebase_marketing_announcement')); + + } + + return $this->render('@UVDeskSupportCenter/Staff/Announcement/announcementForm.html.twig', [ + 'announcement' => $announcement, + 'errors' => '' + ]); + } + + public function removeAnnouncementXHR(Request $request) + { + if (!$this->userService->isAccessAuthorized('ROLE_AGENT_MANAGE_KNOWLEDGEBASE')) { + return $this->redirect($this->generateUrl('helpdesk_member_dashboard')); + } + + $entityManager = $this->getDoctrine()->getManager(); + $knowledgebaseAnnouncementId = $request->attributes->get('id'); + + $knowledgebaseAnnouncement = $entityManager->getRepository(Announcement::class)->findOneBy([ + 'id' => $knowledgebaseAnnouncementId + ]); + + if ($knowledgebaseAnnouncement) { + $entityManager->remove($knowledgebaseAnnouncement); + $entityManager->flush(); + + $json = [ + 'alertClass' => 'success', + 'alertMessage' => 'Announcement deleted successfully!', + ]; + $responseCode = 200; + } else { + $json = [ + 'alertClass' => 'warning', + 'alertMessage' => 'Announcement not found!', + ]; + } + + $response = new Response(json_encode($json)); + $response->headers->set('Content-Type', 'application/json'); + return $response; + } +} diff --git a/Controller/Ticket.php b/Controller/Ticket.php index 26e10f5..dfe1a4f 100644 --- a/Controller/Ticket.php +++ b/Controller/Ticket.php @@ -192,12 +192,15 @@ public function ticketadd(Request $request) $thread = $this->ticketService->createTicketBase($data); - if ($thread) { - $request->getSession()->getFlashBag()->set('success', $this->translator->trans('Success ! Ticket has been created successfully.')); + if (!empty($thread)) { + $ticket = $thread->getTicket(); + if($request->request->get('customFields') || $request->files->get('customFields')) { + $this->get('ticket.service')->addTicketCustomFields($ticket, $request->request->get('customFields'), $request->files->get('customFields')); + } + $request->getSession()->getFlashBag()->set('success', sprintf('Success ! Ticket #%s has been created successfully.', $ticket->getId())); } else { - $request->getSession()->getFlashBag()->set('warning', $this->translator->trans('Warning ! Can not create ticket, invalid details.')); + $this->addFlash('warning', $this->translator->trans('Warning ! Can not create ticket, invalid details.')); } - // Trigger ticket created event $event = new GenericEvent(CoreWorkflowEvents\Ticket\Create::getId(), [ 'entity' => $thread->getTicket(), @@ -280,13 +283,22 @@ public function saveReply(int $id, Request $request) $data['ticket'] = $ticket; $data['user'] = $this->userService->getCurrentUser(); + // Checking if reply is from collaborator end + $isTicketCollaborator = $ticket->getCollaborators() ? $ticket->getCollaborators()->toArray() : []; + $isCollaborator = false; + foreach ($isTicketCollaborator as $value) { + if($value->getId() == $data['user']->getId()){ + $isCollaborator = true; + } + } + // @TODO: Refactor -> Why are we filtering only these two characters? $data['message'] = str_replace(['<script>', '</script>'], '', $data['message']); $userDetail = $this->userService->getCustomerPartialDetailById($data['user']->getId()); $data['fullname'] = $userDetail['name']; $data['source'] = 'website'; - $data['createdBy'] = 'customer'; + $data['createdBy'] = $isCollaborator ? 'collaborator' : 'customer'; $data['attachments'] = $request->files->get('attachments'); $thread = $this->ticketService->createThread($ticket, $data); @@ -303,10 +315,15 @@ public function saveReply(int $id, Request $request) $em->flush(); } - // Trigger customer reply event - $event = new GenericEvent(CoreWorkflowEvents\Ticket\CustomerReply::getId(), [ - 'entity' => $ticket, - ]); + if ($thread->getcreatedBy() == 'customer') { + $event = new GenericEvent(CoreWorkflowEvents\Ticket\CustomerReply::getId(), [ + 'entity' => $ticket, + ]); + } else { + $event = new GenericEvent(CoreWorkflowEvents\Ticket\CollaboratorReply::getId(), [ + 'entity' => $ticket, + ]); + } $this->eventDispatcher->dispatch('uvdesk.automation.workflow.execute', $event); @@ -327,9 +344,23 @@ public function tickets(Request $request) { $this->isWebsiteActive(); + // List Announcement if any + $announcements = $this->getDoctrine()->getRepository('UVDeskSupportCenterBundle:Announcement')->findBy(['isActive' => 1]); + + $groupAnnouncement = []; + foreach($announcements as $announcement) { + $announcementGroupId = $announcement->getGroup(); + $isTicketExist = $this->getDoctrine()->getRepository('UVDeskCoreFrameworkBundle:Ticket')->findBy(['supportGroup' => $announcementGroupId, 'customer' => $this->userService->getCurrentUser()]); + + if (!empty($isTicketExist)) { + $groupAnnouncement[] = $announcement; + } + } + return $this->render('@UVDeskSupportCenter/Knowledgebase/ticketList.html.twig', array( - 'searchDisable' => true + 'searchDisable' => true, + 'groupAnnouncement' => $groupAnnouncement ) ); } @@ -511,6 +542,7 @@ public function downloadAttachment(Request $request) $response->headers->set('Content-type', $attachment->getContentType()); $response->headers->set('Content-Disposition', 'attachment; filename='. $attachment->getName()); + $response->headers->set('Content-Length', $attachment->getSize()); $response->sendHeaders(); $response->setContent(readfile($path)); @@ -577,4 +609,4 @@ public function ticketCollaboratorXhr(Request $request) $response->headers->set('Content-Type', 'application/json'); return $response; } -} +} \ No newline at end of file diff --git a/Entity/Announcement.php b/Entity/Announcement.php new file mode 100644 index 0000000..5680af9 --- /dev/null +++ b/Entity/Announcement.php @@ -0,0 +1,195 @@ +id; + } + + public function getGroup(): ?SupportGroup + { + return $this->group; + } + + public function setGroup(?SupportGroup $group): self + { + $this->group = $group; + + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): self + { + $this->title = $title; + + return $this; + } + + public function getPromoText(): ?string + { + return $this->promoText; + } + + public function setPromoText(string $promoText): self + { + $this->promoText = $promoText; + + return $this; + } + + public function getPromoTag(): ?string + { + return $this->promoTag; + } + + public function setPromoTag(string $promoTag): self + { + $this->promoTag = $promoTag; + + return $this; + } + + public function getTagColor(): ?string + { + return $this->tagColor; + } + + public function setTagColor(?string $tagColor): self + { + $this->tagColor = $tagColor; + + return $this; + } + + public function getLinkText(): ?string + { + return $this->linkText; + } + + public function setLinkText(string $linkText): self + { + $this->linkText = $linkText; + + return $this; + } + + public function getLinkUrl(): ?string + { + return $this->linkUrl; + } + + public function setLinkUrl(string $linkUrl): self + { + $this->linkUrl = $linkUrl; + + return $this; + } + + public function getIsActive(): ?bool + { + return $this->isActive; + } + + public function setIsActive(bool $isActive): self + { + $this->isActive = $isActive; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(?\DateTimeInterface $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function getUpdatedAt(): ?\DateTimeInterface + { + return $this->updatedAt; + } + + public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + { + $this->updatedAt = $updatedAt; + + return $this; + } +} diff --git a/Entity/KnowledgebaseWebsite.php b/Entity/KnowledgebaseWebsite.php index d11f9e8..f2caef2 100644 --- a/Entity/KnowledgebaseWebsite.php +++ b/Entity/KnowledgebaseWebsite.php @@ -107,7 +107,7 @@ class KnowledgebaseWebsite /** * @var string - * @ORM\Column(type="string", length=255, nullable=true) + * @ORM\Column(type="text", nullable=true) */ private $broadcastMessage; diff --git a/Repository/AnnouncementRepository.php b/Repository/AnnouncementRepository.php new file mode 100644 index 0000000..31d3e44 --- /dev/null +++ b/Repository/AnnouncementRepository.php @@ -0,0 +1,95 @@ +getEntityManager()->createQueryBuilder(); + $qb->select('a')->from($this->getEntityName(), 'a'); + + $data = $obj->all(); + $data = array_reverse($data); + foreach ($data as $key => $value) { + if(!in_array($key,$this->safeFields)) { + if($key!='dateUpdated' AND $key!='dateAdded' AND $key!='search') { + $qb->Andwhere('a.'.$key.' = :'.$key); + $qb->setParameter($key, $value); + } else { + if($key == 'search') { + $qb->orwhere('a.title'.' LIKE :name'); + $qb->setParameter('name', '%'.urldecode($value).'%'); + $qb->orwhere('a.promoText'.' LIKE :promoText'); + $qb->setParameter('promoText', '%'.urldecode($value).'%'); + } + } + } + } + + if(!isset($data['sort'])){ + $qb->orderBy('a.id',Criteria::DESC); + } + + $paginator = $container->get('knp_paginator'); + + $results = $paginator->paginate( + $qb, + isset($data['page']) ? $data['page'] : 1, + self::LIMIT, + array('distinct' => false) + ); + + $newResult = []; + foreach ($results as $key => $result) { + $newResult[] = array( + 'id' => $result->getId(), + 'title' => $result->getTitle(), + 'promoText' => $result->getPromoText(), + 'promoTag' => $result->getPromoTag(), + 'tagColor' => $result->getTagColor(), + 'linkText' => $result->getLinkText(), + 'linkUrl' => $result->getLinkUrl(), + 'isActive' => $result->getIsActive(), + 'createdAt' => $result->getCreatedAt(), + 'group' => array( + 'id' => $result->getGroup()->getId(), + 'name' => $result->getGroup()->getName() + ) + ); + } + + $paginationData = $results->getPaginationData(); + $queryParameters = $results->getParams(); + + $paginationData['url'] = '#'.$container->get('uvdesk.service')->buildPaginationQuery($queryParameters); + + $json['groups'] = $newResult; + $json['pagination_data'] = $paginationData; + + return $json; + } +} diff --git a/Resources/config/routes/private-agents.yaml b/Resources/config/routes/private-agents.yaml index 8cda20b..7605f90 100644 --- a/Resources/config/routes/private-agents.yaml +++ b/Resources/config/routes/private-agents.yaml @@ -132,3 +132,26 @@ helpdesk_member_knowledgebase_spam: helpdesk_member_knowledgebase_update_theme_xhr: path: /branding/ajax controller: Webkul\UVDesk\SupportCenterBundle\Controller\Branding::BrandingXhr + +# Marketing Announcement section resources +helpdesk_member_knowledgebase_marketing_announcement: + path: /announcement/list + controller: Webkul\UVDesk\SupportCenterBundle\Controller\Announcement::listAnnouncement + +helpdesk_member_knowledgebase_marketing_announcement_xhr: + path: /announcement/xhr + controller: Webkul\UVDesk\SupportCenterBundle\Controller\Announcement::listAnnouncementXHR + +helpdesk_member_knowledgebase_create_marketing_announcement: + path: /knowledgebase/announcement/new + controller: Webkul\UVDesk\SupportCenterBundle\Controller\Announcement::updateAnnouncement + +helpdesk_member_knowledgebase_update_marketing_announcement: + path: /knowledgebase/announcement/update/{announcementId} + controller: Webkul\UVDesk\SupportCenterBundle\Controller\Announcement::updateAnnouncement + defaults: { announcementId: 0 } + +helpdesk_member_knowledgebase_remove_marketing_announcement_xhr: + path: /knowledgebase/announcement/remove/{announcementId} + controller: Webkul\UVDesk\SupportCenterBundle\Controller\Announcement::removeAnnouncement + defaults: { announcementId: 0 } diff --git a/Resources/config/routes/private-customers.yaml b/Resources/config/routes/private-customers.yaml index 6d6e804..a4afb11 100644 --- a/Resources/config/routes/private-customers.yaml +++ b/Resources/config/routes/private-customers.yaml @@ -80,4 +80,4 @@ helpdesk_customer_view_ticket_attachment: helpdesk_customer_front_article_search: path: /search/article/{s} controller: Webkul\UVDesk\SupportCenterBundle\Controller\Customer::searchArticle - defaults: { s: 0 } + defaults: { s: 0 } \ No newline at end of file diff --git a/Resources/public/css/knowledgebase.css b/Resources/public/css/knowledgebase.css index e791f8a..22c2b91 100644 --- a/Resources/public/css/knowledgebase.css +++ b/Resources/public/css/knowledgebase.css @@ -426,6 +426,12 @@ input[type="radio"][disabled="disabled"] + .uv-radio-view { background-position: 0px -21px; } .uv-checkbox-label, +.uv-split-field { + display: inline-block; + clear: both; + width: 100%; + margin-top: 10px; +} .uv-radio-label { vertical-align: middle; display: inline-block; @@ -3352,4 +3358,4 @@ p { .uv-rtl .uv-kudo .uv-kudo-button .uv-kudo-icon { margin: 0px; } -} +} \ No newline at end of file diff --git a/Resources/views/Knowledgebase/darkSkin.html.twig b/Resources/views/Knowledgebase/darkSkin.html.twig index 54afd8b..ec69c3a 100644 --- a/Resources/views/Knowledgebase/darkSkin.html.twig +++ b/Resources/views/Knowledgebase/darkSkin.html.twig @@ -1,6 +1,40 @@ {% set brandColor = websiteConfiguration.brandColor ?: '#7C70F4' %} {% if brandColor != '#7C70F4' and brandColor != '#7c70f4' %} + {% set themeTemplate = themeTemplate ? themeTemplate : 'masonryView' %} {% include "@UVDeskSupportCenter/Themes/" ~ themeTemplate ~ ".html.twig" %} {{parent()}} diff --git a/Resources/views/Knowledgebase/lightSkin.html.twig b/Resources/views/Knowledgebase/lightSkin.html.twig index bcdce3e..85c9e43 100644 --- a/Resources/views/Knowledgebase/lightSkin.html.twig +++ b/Resources/views/Knowledgebase/lightSkin.html.twig @@ -62,18 +62,23 @@ .uv-hero { background-color: {{ brandColor }}; } - + .uv-cta-wrapper .uv-cta-lt svg path { fill: {{ brandColor }}; } .uv-kb-layout-folder .uv-kb-folder { border-color: {{ brandColor }}; } + + .uv-kb-layout-grid .uv-kb-folder{ + border-color: {{ brandColor }}; + } + .uv-kb-layout-folder .uv-kb-folder .uv-kb-folder-lt { background-position: -90px 0px; background-color: {{ brandColor }}; } - + .uv-paper-article .uv-paper-section .uv-folder-title:after { background-color: {{ brandColor }}; } diff --git a/Resources/views/Knowledgebase/ticket.html.twig b/Resources/views/Knowledgebase/ticket.html.twig index 8d1641c..c21ffd4 100644 --- a/Resources/views/Knowledgebase/ticket.html.twig +++ b/Resources/views/Knowledgebase/ticket.html.twig @@ -105,6 +105,93 @@ {% endif %} + {# CustomFields #} + {% set CustomerCustomFields = ticket_service.getCustomerCreateTicketCustomFieldSnippet() %} + {% set removeMe = [] %} + {% if CustomerCustomFields %} +