From 6cedf621464fe6dc3b2083f0de049d4b65c32ec1 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Tue, 6 Nov 2018 17:11:11 +0000 Subject: [PATCH 01/15] priority and email templates --- src/Support.php | 9 +- .../TicketPrioritiesController.php | 152 ++++++++++++ src/controllers/TicketsController.php | 9 +- src/elements/Ticket.php | 76 +++++- src/elements/db/TicketQuery.php | 16 +- src/migrations/Install.php | 27 ++- src/models/TicketPriority.php | 71 ++++++ src/records/TicketPriority.php | 27 +++ src/services/MailService.php | 6 +- src/services/TicketPriorityService.php | 218 ++++++++++++++++++ src/services/TicketService.php | 22 +- src/templates/_emails/newTicket-copy.twig | 14 ++ src/templates/_emails/newTicket.twig | 38 +++ src/templates/_layouts/settings.twig | 1 + .../_settings/ticket-priorities/edit.twig | 133 +++++++++++ .../_settings/ticket-priorities/index.twig | 63 +++++ src/templates/_tickets/new.twig | 57 +++-- src/templates/_tickets/ticket.twig | 13 ++ 18 files changed, 912 insertions(+), 40 deletions(-) create mode 100644 src/controllers/TicketPrioritiesController.php create mode 100644 src/models/TicketPriority.php create mode 100644 src/records/TicketPriority.php create mode 100644 src/services/TicketPriorityService.php create mode 100644 src/templates/_emails/newTicket-copy.twig create mode 100644 src/templates/_emails/newTicket.twig create mode 100644 src/templates/_settings/ticket-priorities/edit.twig create mode 100644 src/templates/_settings/ticket-priorities/index.twig diff --git a/src/Support.php b/src/Support.php index 58b645e..48f37b1 100644 --- a/src/Support.php +++ b/src/Support.php @@ -74,7 +74,11 @@ function (RegisterUrlRulesEvent $event) { $event->rules['support/settings/ticket-statuses'] = 'support/ticket-statuses/index'; $event->rules['support/settings/ticket-statuses/new'] = 'support/ticket-statuses/edit'; - $event->rules['support/settings/ticket-statuses/'] = 'support/ticket-statuses/edit'; + $event->rules['support/settings/ticket-statuses/'] = 'support/ticket-statuses/edit'; + + $event->rules['support/settings/ticket-priorities'] = 'support/ticket-priorities/index'; + $event->rules['support/settings/ticket-priorities/new'] = 'support/ticket-priorities/edit'; + $event->rules['support/settings/ticket-priorities/'] = 'support/ticket-priorities/edit'; $event->rules['support/settings/emails'] = 'support/emails/index'; $event->rules['support/settings/emails/new'] = 'support/emails/edit'; @@ -141,7 +145,8 @@ function (PluginEvent $event) { 'mailService' => \lukeyouell\support\services\MailService::class, 'messageService' => \lukeyouell\support\services\MessageService::class, 'ticketService' => \lukeyouell\support\services\TicketService::class, - 'ticketStatusService' => \lukeyouell\support\services\TicketStatusService::class, + 'ticketStatusService' => \lukeyouell\support\services\TicketStatusService::class, + 'ticketPriorityService' => \lukeyouell\support\services\TicketPriorityService::class, ]); } diff --git a/src/controllers/TicketPrioritiesController.php b/src/controllers/TicketPrioritiesController.php new file mode 100644 index 0000000..e90aa5c --- /dev/null +++ b/src/controllers/TicketPrioritiesController.php @@ -0,0 +1,152 @@ +settings = Support::$plugin->getSettings(); + if (!$this->settings->validate()) { + throw new InvalidConfigException('Support settings don’t validate.'); + } + } + + public function actionIndex() + { + + $settings = $this->settings; + $ticketPriorities = Support::getInstance()->ticketPriorityService->getAllTicketPriorities(); + + $variables = [ + 'settings' => $settings, + 'ticketPriorities' => $ticketPriorities, + ]; + + return $this->renderTemplate('support/_settings/ticket-priorities/index', $variables); + } + + public function actionEdit(int $id = null, TicketPriorityModel $ticketPriority = null) + { + $variables = [ + 'id' => $id, + 'ticketPriority' => $ticketPriority, + ]; + + if (!$variables['ticketPriority']) { + if ($variables['id']) { + $variables['ticketPriority'] = Support::getInstance()->ticketPriorityService->getTicketPriorityById($variables['id']); + + if (!$variables['ticketPriority']) { + throw new NotFoundHttpException('Ticket priority not found'); + } + } else { + $variables['ticketPriority'] = new TicketPriorityModel(); + } + } + + if ($variables['ticketPriority']->id) { + $variables['title'] = $variables['ticketPriority']->name; + } else { + $variables['title'] = 'Create a new ticket priority'; + } + + $emails = Support::getInstance()->emailService->getAllEmails(); + $variables['emails'] = ArrayHelper::map($emails, 'id', 'name'); + + return $this->renderTemplate('support/_settings/ticket-priorities/edit', $variables); + } + + public function actionSave() + { + $this->requirePostRequest(); + + $request = Craft::$app->getRequest(); + $id = $request->post('id'); + $ticketPriority = Support::getInstance()->ticketPriorityService->getTicketPriorityById($id); + + if (!$ticketPriority) { + $ticketPriority = new TicketPriorityModel(); + } + + $ticketPriority->name = $request->post('name'); + $ticketPriority->handle = $request->post('handle'); + $ticketPriority->colour = $request->post('colour'); + $ticketPriority->default = $request->post('default'); + // $emailIds = $request->post('emails'); + + // if (!$emailIds) { + // $emailIds = []; + // } + + // Save it + // $save = Support::getInstance()->ticketPriorityService->saveTicketPriority($ticketPriority, $emailIds); + $save = Support::getInstance()->ticketPriorityService->saveTicketPriority($ticketPriority); + + if ($save) { + Craft::$app->getSession()->setNotice('Ticket priority saved.'); + + $this->redirectToPostedUrl(); + } else { + Craft::$app->getSession()->setError('Couldn’t save ticket priority.'); + } + + Craft::$app->getUrlManager()->setRouteParams(compact('ticketPriority')); + } + + public function actionReorder(): Response + { + $this->requirePostRequest(); + $this->requireAcceptsJson(); + + $ids = Json::decode(Craft::$app->getRequest()->getRequiredBodyParam('ids')); + + if ($success = Support::getInstance()->ticketPriorityService->reorderTicketPriorities($ids)) { + return $this->asJson(['success' => $success]); + } + + return $this->asJson(['error' => 'Couldn’t reorder ticket priorities.']); + } + + public function actionDelete() + { + $this->requireAcceptsJson(); + + $ticketPriorityId = Craft::$app->getRequest()->getRequiredParam('id'); + + if ($success = Support::getInstance()->ticketPriorityService->deleteTicketPriorityById($ticketPriorityId)) { + return $this->asJson(['success' => true]); + } + + return $this->asJson(['error' => 'Couldn’t delete ticket priority.']); + } +} diff --git a/src/controllers/TicketsController.php b/src/controllers/TicketsController.php index d9281fe..271764f 100644 --- a/src/controllers/TicketsController.php +++ b/src/controllers/TicketsController.php @@ -51,7 +51,8 @@ public function actionNew() $volume = $this->settings->volumeId ? Craft::$app->getVolumes()->getVolumeById($this->settings->volumeId) : null; $variables = [ - 'volume' => $volume, + 'volume' => $volume, + 'ticketPriorities' => Support::getInstance()->ticketPriorityService->getAllTicketPriorities(), 'elementType' => Asset::class, 'settings' => $this->settings, ]; @@ -72,6 +73,7 @@ public function actionView(string $ticketId = null) $variables = [ 'ticket' => $ticket, 'ticketStatuses' => Support::getInstance()->ticketStatusService->getAllTicketStatuses(), + 'ticketPriorities' => Support::getInstance()->ticketPriorityService->getAllTicketPriorities(), 'volume' => $volume, 'assetElementType' => Asset::class, 'settings' => $this->settings, @@ -133,6 +135,7 @@ public function actionSave() $request = Craft::$app->getRequest(); $ticketId = Craft::$app->security->validateData($request->post('ticketId')); $ticketStatusId = $request->post('ticketStatusId'); + $ticketPriorityId = $request->post('ticketPriorityId'); if ($ticketId) { $ticket = Support::getInstance()->ticketService->getTicketById($ticketId); @@ -143,6 +146,10 @@ public function actionSave() if ($request->post('ticketStatusId')) { Support::getInstance()->ticketService->changeTicketStatus($ticket, $ticketStatusId); + } + + if ($request->post('ticketPriorityId')) { + Support::getInstance()->ticketService->changeTicketPriority($ticket, $ticketPriorityId); } Craft::$app->getElements()->saveElement($ticket, false); diff --git a/src/elements/Ticket.php b/src/elements/Ticket.php index 6ce0a47..d6d43b3 100644 --- a/src/elements/Ticket.php +++ b/src/elements/Ticket.php @@ -27,11 +27,15 @@ class Ticket extends Element // Public Properties // ========================================================================= - public $ticketStatusId; + public $ticketStatusId; + + public $ticketPriorityId; public $authorId; - public $_ticketStatus; + public $_ticketStatus; + + public $_ticketPriority; public $_author; @@ -63,6 +67,15 @@ public static function hasTitles(): bool public static function isLocalized(): bool { return true; + } + + public function rules() + { + $rules = parent::rules(); + + $rules[] = [['ticketPriorityId'], 'required']; + + return $rules; } public static function hasStatuses(): bool @@ -121,6 +134,23 @@ protected static function defineSources(string $context = null): array ], 'defaultSort' => ['dateCreated', 'desc'], ]; + } + + $sources[] = ['heading' => 'Ticket Priority']; + + $priorities = Support::getInstance()->ticketPriorityService->getAllTicketPriorities(); + + foreach ($priorities as $priority) { + $sources[] = [ + 'key' => 'priority:'.$priority['handle'], + 'status' => $priority['colour'], + 'label' => $priority['name'], + 'criteria' => [ + 'authorId' => $canManageTickets ? '' : $userId, + 'ticketPriorityId' => $priority['id'], + ], + 'defaultSort' => ['dateCreated', 'desc'], + ]; } return $sources; @@ -158,16 +188,18 @@ protected static function defineTableAttributes(): array $attributes = [ 'title' => Craft::t('support', 'Title'), 'ticketStatus' => Craft::t('support', 'Status'), + 'ticketPriority' => Craft::t('support', 'Priority'), 'author' => Craft::t('support', 'Author'), 'dateCreated' => Craft::t('support', 'Date Created'), 'dateUpdated' => Craft::t('support', 'Date Updated'), ]; } else { $attributes = [ - 'title' => Craft::t('support', 'Title'), - 'ticketStatus' => Craft::t('support', 'Status'), - 'dateCreated' => Craft::t('support', 'Date Created'), - 'dateUpdated' => Craft::t('support', 'Date Updated'), + 'title' => Craft::t('support', 'Title'), + 'ticketStatus' => Craft::t('support', 'Status'), + 'ticketPriority' => Craft::t('support', 'Priority'), + 'dateCreated' => Craft::t('support', 'Date Created'), + 'dateUpdated' => Craft::t('support', 'Date Updated'), ]; } @@ -180,9 +212,9 @@ protected static function defineDefaultTableAttributes(string $source): array $canManageTickets = $userSessionService->checkPermission('support-manageTickets'); if ($canManageTickets) { - $attributes = ['title', 'ticketStatus', 'dateCreated', 'dateUpdated', 'author']; + $attributes = ['title', 'ticketStatus', 'ticketPriority', 'dateCreated', 'dateUpdated', 'author']; } else { - $attributes = ['title', 'ticketStatus', 'dateCreated', 'dateUpdated']; + $attributes = ['title', 'ticketStatus', 'ticketPriority', 'dateCreated', 'dateUpdated']; } return $attributes; @@ -194,7 +226,11 @@ public function getTableAttributeHtml(string $attribute): string case 'ticketStatus': $status = $this->getTicketStatus(); - return ''.$status['name']; + return ''.$status['name']; + case 'ticketPriority': + $priority = $this->getTicketPriority(); + + return ''.$priority['name']; case 'author': $author = $this->getAuthor(); @@ -213,6 +249,7 @@ public function extraFields() { $names = parent::extraFields(); $names[] = 'ticketStatus'; + $names[] = 'ticketPriority'; $names[] = 'author'; $names[] = 'messages'; return $names; @@ -241,6 +278,21 @@ public function getTicketStatus() $this->_ticketStatus = Support::getInstance()->ticketStatusService->getTicketStatusById($this->ticketStatusId); return $this->_ticketStatus; + } + + public function getTicketPriority() + { + if ($this->_ticketPriority !== null) { + return $this->_ticketPriority; + } + + if ($this->ticketPriorityId === null) { + return null; + } + + $this->_ticketPriority = Support::getInstance()->ticketPriorityService->getTicketPriorityById($this->ticketPriorityId); + + return $this->_ticketPriority; } public function getAuthor() @@ -289,11 +341,14 @@ protected static function defineSortOptions(): array public function afterSave(bool $isNew) { - if ($isNew) { + + + if ($isNew) { Craft::$app->db->createCommand() ->insert('{{%support_tickets}}', [ 'id' => $this->id, 'ticketStatusId' => $this->ticketStatusId, + 'ticketPriorityId' => $this->ticketPriorityId, 'authorId' => $this->authorId, ]) ->execute(); @@ -301,6 +356,7 @@ public function afterSave(bool $isNew) Craft::$app->db->createCommand() ->update('{{%support_tickets}}', [ 'ticketStatusId' => $this->ticketStatusId, + 'ticketPriorityId' => $this->ticketPriorityId, ], ['id' => $this->id]) ->execute(); } diff --git a/src/elements/db/TicketQuery.php b/src/elements/db/TicketQuery.php index a87c73b..22ccc3e 100644 --- a/src/elements/db/TicketQuery.php +++ b/src/elements/db/TicketQuery.php @@ -19,6 +19,8 @@ class TicketQuery extends ElementQuery { public $ticketStatusId; + + public $ticketPriorityId; public $authorId; @@ -30,6 +32,13 @@ public function ticketStatusId($value) { $this->ticketStatusId = $value; + return $this; + } + + public function ticketPriorityId($value) + { + $this->ticketPriorityId = $value; + return $this; } @@ -74,12 +83,17 @@ protected function beforePrepare(): bool // select the columns $this->query->select([ 'support_tickets.ticketStatusId', + 'support_tickets.ticketPriorityId', 'support_tickets.authorId', ]); if ($this->ticketStatusId) { $this->subQuery->andWhere(Db::parseParam('support_tickets.ticketStatusId', $this->ticketStatusId)); - } + } + + if ($this->ticketPriorityId) { + $this->subQuery->andWhere(Db::parseParam('support_tickets.ticketPriorityId', $this->ticketPriorityId)); + } if ($this->authorId) { $this->subQuery->andWhere(Db::parseParam('support_tickets.authorId', $this->authorId)); diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 2b75556..0ea235f 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -123,6 +123,7 @@ protected function createTables() 'uid' => $this->uid(), // Custom columns in the table 'ticketStatusId' => $this->integer(), + 'ticketPriorityId' => $this->integer(), 'authorId' => $this->integer(), ] ); @@ -141,6 +142,22 @@ protected function createTables() 'sortOrder' => $this->integer(), 'default' => $this->boolean(), 'newMessage' => $this->boolean(), + ] + ); + + $this->createTable( + '{{%support_ticketpriorities}}', + [ + 'id' => $this->primaryKey(), + 'dateCreated' => $this->dateTime()->notNull(), + 'dateUpdated' => $this->dateTime()->notNull(), + 'uid' => $this->uid(), + // Custom columns in the table + 'name' => $this->string()->notNull(), + 'handle' => $this->string()->notNull(), + 'colour' => $this->enum('colour', ['green', 'orange', 'red', 'blue', 'yellow', 'pink', 'purple', 'turquoise', 'light', 'grey', 'black'])->notNull()->defaultValue('green'), + 'sortOrder' => $this->integer(), + 'default' => $this->boolean() ] ); @@ -170,6 +187,7 @@ protected function addForeignKeys() $this->addForeignKey(null, '{{%support_tickets}}', ['id'], '{{%elements}}', ['id'], 'CASCADE'); $this->addForeignKey(null, '{{%support_tickets}}', ['authorId'], '{{%users}}', ['id'], null, 'CASCADE'); $this->addForeignKey(null, '{{%support_tickets}}', ['ticketStatusId'], '{{%support_ticketstatuses}}', ['id'], null, 'CASCADE'); + $this->addForeignKey(null, '{{%support_tickets}}', ['ticketpriorityId'], '{{%support_ticketpriorities}}', ['id'], null, 'CASCADE'); $this->addForeignKey(null, '{{%support_ticketstatus_emails}}', ['emailId'], '{{%support_emails}}', ['id'], 'CASCADE', 'CASCADE'); $this->addForeignKey(null, '{{%support_ticketstatus_emails}}', ['ticketStatusId'], '{{%support_ticketstatuses}}', ['id'], 'CASCADE', 'CASCADE'); @@ -180,6 +198,7 @@ protected function dropForeignKeys() MigrationHelper::dropAllForeignKeysOnTable('{{%support_messages}}', $this); MigrationHelper::dropAllForeignKeysOnTable('{{%support_tickets}}', $this); MigrationHelper::dropAllForeignKeysOnTable('{{%support_ticketstatuses}}', $this); + MigrationHelper::dropAllForeignKeysOnTable('{{%support_ticketpriorities}}', $this); MigrationHelper::dropAllForeignKeysOnTable('{{%support_ticketstatus_emails}}', $this); } @@ -189,6 +208,7 @@ protected function dropTables() $this->dropTable('{{%support_messages}}'); $this->dropTable('{{%support_tickets}}'); $this->dropTable('{{%support_ticketstatuses}}'); + $this->dropTable('{{%support_ticketpriorities}}'); $this->dropTable('{{%support_ticketstatus_emails}}'); } @@ -297,5 +317,10 @@ private function _defaultTicketStatuses() 'emailId' => 3, ]; $this->insert(TicketStatusEmailRecord::tableName(), $data); - } + } + + private function _defaultTicketPriority() + { + + } } diff --git a/src/models/TicketPriority.php b/src/models/TicketPriority.php new file mode 100644 index 0000000..4811e9b --- /dev/null +++ b/src/models/TicketPriority.php @@ -0,0 +1,71 @@ +name; + } + + public function rules() + { + return [ + [['name', 'handle'], 'required'], + [['handle'], UniqueValidator::class, 'targetClass' => TicketPriorityRecord::class], + ]; + } + + public function getCpEditUrl(): string + { + return UrlHelper::cpUrl('support/settings/ticket-priorities/'.$this->id); + } + + public function getLabelHtml(): string + { + $html = '
'; + $html .= ''; + $html .= '
'; + $html .= ''.$this->name.''; + $html .='
'; + $html .= '
'; + + return $html; + } +} diff --git a/src/records/TicketPriority.php b/src/records/TicketPriority.php new file mode 100644 index 0000000..754ec67 --- /dev/null +++ b/src/records/TicketPriority.php @@ -0,0 +1,27 @@ +getView()->renderObjectTemplate($email->subject, $ticket); + $subject = Craft::$app->getView()->renderObjectTemplate($email->subject, $ticket); + return $subject; } @@ -117,7 +118,8 @@ public function getTemplateHtml($email, $ticket) // Set Craft to the site template mode $view = Craft::$app->getView(); $oldTemplateMode = $view->getTemplateMode(); - $view->setTemplateMode($view::TEMPLATE_MODE_SITE); + // $view->setTemplateMode($view::TEMPLATE_MODE_SITE); + $view->setTemplateMode($view::TEMPLATE_MODE_CP); // Render template $html = Craft::$app->view->renderTemplate($email->templatePath, $variables); diff --git a/src/services/TicketPriorityService.php b/src/services/TicketPriorityService.php new file mode 100644 index 0000000..9272934 --- /dev/null +++ b/src/services/TicketPriorityService.php @@ -0,0 +1,218 @@ +_fetchedAllPriorities) { + $results = $this->_createTicketPriorityQuery()->all(); + + foreach ($results as $row) { + $this->_memoizeTicketPriority(new TicketPriorityModel($row)); + } + + $this->_fetchedAllPriorities = true; + } + + return $this->_ticketPrioritiesById; + } + + public function getTicketPriorityById($id) + { + $result = $this->_createTicketPriorityQuery() + ->where(['id' => $id]) + ->one(); + + return new TicketPriorityModel($result); + } + + public function getDefaultTicketPriority() + { + $result = $this->_createTicketPriorityQuery() + ->where(['default' => 1]) + ->one(); + + return new TicketPriorityModel($result); + } + + public function checkIfTicketPriorityInUse($id) + { + $result = Ticket::find() + ->TicketPriorityId($id) + ->one(); + + return $result; + } + + public function reorderTicketPriorities(array $ids) + { + foreach ($ids as $sortOrder => $id) { + Craft::$app->getDb()->createCommand() + ->update('{{%support_ticketpriorities}}', ['sortOrder' => $sortOrder + 1], ['id' => $id]) + ->execute(); + } + + return true; + } + + public function saveTicketPriority(TicketPriorityModel $model, bool $runValidation = true) + { + if ($model->id) { + $record = TicketPriorityRecord::findOne($model->id); + + if (!$record->id) { + throw new Exception(Craft::t('support', 'No ticket priority exists with the ID "{id}"', + ['id' => $model->id])); + } + } else { + $record = new TicketPriorityRecord(); + } + + if ($runValidation && !$model->validate()) { + Craft::info('Ticket priority not saved due to a validation error.', __METHOD__); + + return false; + } + + $record->name = $model->name; + $record->handle = $model->handle; + $record->colour = $model->colour; + $record->sortOrder = $model->sortOrder ?: 999; + $record->default = $model->default; + + // Validate email ids + // $exist = EmailRecord::find()->where(['in', 'id', $emailIds])->exists(); + // $hasEmails = (boolean) count($emailIds); + + // if (!$exist && $hasEmails) { + // $model->addError('emails', 'One or more emails do not exist in the system.'); + // } + + $db = Craft::$app->getDb(); + $transaction = $db->beginTransaction(); + + try { + // Only one default priority can be among priorities + if ($record->default) { + TicketPriorityRecord::updateAll(['default' => 0]); + } + + // Save it + $record->save(false); + + /* + // Delete old email links + if ($model->id) { + $rows = TicketPriorityEmailRecord::find()->where(['TicketPriorityId' => $model->id])->all(); + + foreach ($rows as $row) { + $row->delete(); + } + } + + // Save new email links + $rows = array_map( + function ($id) use ($record) { + return [$id, $record->id]; + }, $emailIds); + + $cols = ['emailId', 'TicketPriorityId']; + $table = TicketPriorityEmailRecord::tableName(); + Craft::$app->getDb()->createCommand()->batchInsert($table, $cols, $rows)->execute(); + */ + + // Now that we have a record ID, save it on the model + $model->id = $record->id; + + $transaction->commit(); + } catch (\Exception $e) { + $transaction->rollBack(); + + throw $e; + } + + return true; + } + + public function deleteTicketPrioritybyId($id) + { + $priorities = $this->getAllTicketPriorities(); + + $existingTicket = $this->checkIfTicketPriorityInUse($id); + + // Don't delete if it's still in use + if ($existingTicket) { + return false; + } + + // Don't delete if it's the only priority left + if (count($priorities) > 1) { + $record = TicketPriorityRecord::findOne($id); + + return $record->delete(); + } + + return false; + } + + // Private Methods + // ========================================================================= + + private function _memoizeTicketPriority(TicketPriorityModel $TicketPriority) + { + $this->_ticketPrioritiesById[$TicketPriority->id] = $TicketPriority; + $this->_ticketPrioritiesByHandle[$TicketPriority->handle] = $TicketPriority; + } + + private function _createTicketPriorityQuery() + { + return (new Query()) + ->select([ + 'id', + 'name', + 'handle', + 'colour', + 'sortOrder', + 'default', + ]) + ->orderBy('sortOrder') + ->from(['{{%support_ticketpriorities}}']); + } +} diff --git a/src/services/TicketService.php b/src/services/TicketService.php index 70c66d7..b91f7aa 100644 --- a/src/services/TicketService.php +++ b/src/services/TicketService.php @@ -26,10 +26,11 @@ class TicketService extends Component public function createTicket($submission = null) { if ($submission) { - $defaultTicketStatus = Support::getInstance()->ticketStatusService->getDefaultTicketStatus(); + $defaultTicketStatus = Support::getInstance()->ticketStatusService->getDefaultTicketStatus(); $ticket = new Ticket(); $ticket->ticketStatusId = $defaultTicketStatus['id']; + $ticket->ticketPriorityId = $submission->post('ticketPriorityId'); $ticket->title = $submission->post('title'); $ticket->authorId = Craft::$app->getUser()->getIdentity()->id; @@ -81,6 +82,25 @@ public function changeTicketStatus($ticket = null, $ticketStatusId = null) return true; } + return false; + } + + public function changeTicketPriority($ticket = null, $ticketPriorityId = null) + { + if ($ticket->id && $ticketPriorityId) { + $priority = Support::getInstance()->ticketPriorityService->getTicketPriorityById($ticketPriorityId); + + if (!$priority->id) { + throw new NotFoundHttpException('Ticket priority not found'); + } + + $ticket->ticketPriorityId = $priority->id; + + Craft::$app->getElements()->saveElement($ticket, false); + + return true; + } + return false; } diff --git a/src/templates/_emails/newTicket-copy.twig b/src/templates/_emails/newTicket-copy.twig new file mode 100644 index 0000000..b880b6a --- /dev/null +++ b/src/templates/_emails/newTicket-copy.twig @@ -0,0 +1,14 @@ +ID: {{ ticket.id }}
+Priority: {{ ticket.ticketPriority.name }}
+Status: {{ ticket.ticketStatus.name }}
+Title: {{ ticket.title }}
+Author {{ ticket.author.name }}
+
+Message
+
+ {% for message in ticket.messages %} + {{ message.content|nl2br }} +{% endfor %} +
+
+View ticket: {{ ticket.cpEditUrl }} \ No newline at end of file diff --git a/src/templates/_emails/newTicket.twig b/src/templates/_emails/newTicket.twig new file mode 100644 index 0000000..7cc5d4c --- /dev/null +++ b/src/templates/_emails/newTicket.twig @@ -0,0 +1,38 @@ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + {% for message in ticket.messages %} + + + + {% endfor %} + +
ID: {{ ticket.id }}
Priority: {{ ticket.ticketPriority.name }}
Status: {{ ticket.ticketStatus.name }}
Title: {{ ticket.title }}
Author: {{ ticket.author.name }}
Message
{{ message.content|nl2br }}
+
View ticket
\ No newline at end of file diff --git a/src/templates/_layouts/settings.twig b/src/templates/_layouts/settings.twig index c7ba15f..8a1b9ca 100644 --- a/src/templates/_layouts/settings.twig +++ b/src/templates/_layouts/settings.twig @@ -8,6 +8,7 @@ {% set navItems = { 'general': { title: 'General Settings' }, 'ticket-statuses': { title: 'Ticket Statuses' }, + 'ticket-priorities': { title: 'Ticket Priorities' }, 'emails': { title: 'Emails' }, 'attachments': { title: 'Attachments' }, } %} diff --git a/src/templates/_settings/ticket-priorities/edit.twig b/src/templates/_settings/ticket-priorities/edit.twig new file mode 100644 index 0000000..46e46d2 --- /dev/null +++ b/src/templates/_settings/ticket-priorities/edit.twig @@ -0,0 +1,133 @@ +{% extends "support/_layouts/settingscp" %} +{% requireAdmin %} + +{% set crumbs = [ + { label: 'Support Settings', url: url('support/settings') }, + { label: 'Ticket Priorities', url: url('support/settings/ticket-priority') } +] %} + +{% set fullPageForm = true %} + +{% import "_includes/forms" as forms %} + +{% block content %} + + {{ forms.hidden({ + name: 'action', + value: 'support/ticket-priorities/save', + })}} + + {{ redirectInput('support/settings/ticket-priorities') }} + + {% if ticketPriority.id %} + {{ forms.hidden({ + name: 'id', + value: ticketPriority.id, + })}} + + {{ forms.hidden({ + name: 'sortOrder', + value: ticketPriority.sortOrder, + })}} + {% endif %} + + {{ forms.textField({ + first: true, + required: true, + label: 'Name', + instructions: 'What this priority will be called in the CP.', + id: 'name', + name: 'name', + autofocus: true, + value: ticketPriority.name, + errors: ticketPriority.getErrors('name'), + })}} + + {{ forms.textField({ + required: true, + label: 'Handle', + instructions: 'How you’ll refer to this priority in the templates.', + id: 'handle', + name: 'handle', + value: ticketPriority.handle, + errors: ticketPriority.getErrors('handle'), + })}} + + {{ forms.hidden({ + id: 'colour', + name: 'colour', + value: ticketPriority.colour, + })}} + + {% set colourField %} +
+ + {{ ticketPriority.colour|title }} + + +
+ {% endset %} + + {{ forms.field({ + label: 'Colour', + instructions: 'Choose a colour to represent the ticket’s priority'|t + }, colourField) }} + + {# {% if not emails|length %} + {{ forms.field({ + label: 'Status Emails', + instructions: 'You currently have no emails configured to select for this priority.', + disabled: true + }) }} + {% else %} + {{ forms.multiselectField({ + label: 'Status Emails', + instructions: 'Select the emails that will be sent when transitioning to this status.', + id: 'emails', + name: 'emails', + options: emails, + values: emailIds is defined ? emailIds : ticketPriority.getEmailIds(), + errors: ticketPriority.getErrors('emails'), + class: 'selectize fullwidth', + }) }} + {% endif %} #} + + {{ forms.checkboxField({ + label: 'New tickets get this priority by default', + name: 'default', + value: 1, + checked: ticketPriority.default, + errors: ticketPriority.getErrors('default') + })}} + +{% endblock %} + +{% js %} + {% if not ticketPriority.handle %}new Craft.HandleGenerator('#name', '#handle');{% endif %} + $(function () { + $colourSelect = $('#colour-menu-btn'); + new Garnish.MenuBtn($colourSelect, { + onOptionSelect: function(data){ + var val = $(data).data('val'); + $('#colour').val(val); + var html = ""+Craft.uppercaseFirst(val); + $colourSelect.html(html); + } + }); + + $('#emails').selectize({ + plugins: ['remove_button'], + dropdownParent: 'body' + }); + }); +{% endjs %} diff --git a/src/templates/_settings/ticket-priorities/index.twig b/src/templates/_settings/ticket-priorities/index.twig new file mode 100644 index 0000000..117c217 --- /dev/null +++ b/src/templates/_settings/ticket-priorities/index.twig @@ -0,0 +1,63 @@ +{% extends "support/_layouts/settings" %} + +{% block content %} + +

Ticket Priorites

+ +

Define the ticket priorities that can be set.

+ + + + + + + + + + + + + + {% for status in ticketPriorities %} + + + + + + + + {% endfor %} + +
NameHandleDefault
+ {{ status.labelHtml|raw }} + + {{ status.handle }} + + {% if status.default %} + + {% endif %} + + + + +
+ +
+ New ticket priority + + +{% endblock %} + +{% js %} + new Craft.AdminTable({ + tableSelector: '#ticket-priorities', + deleteAction: 'support/ticket-priorities/delete', + deleteSuccessMessage: 'Ticket status deleted.', + deleteFailMessage: 'Couldn’t delete ticket status.', + minObjects: 1, + sortable: true, + reorderAction: 'support/ticket-priorities/reorder', + reorderSuccessMessage: 'Ticket priorities reordered.' , + reorderFailMessage: 'Couldn’t reorder ticket priorities.', + }); +{% endjs %} diff --git a/src/templates/_tickets/new.twig b/src/templates/_tickets/new.twig index 1b6320f..ffeffeb 100644 --- a/src/templates/_tickets/new.twig +++ b/src/templates/_tickets/new.twig @@ -23,31 +23,44 @@ {% do view.registerAssetBundle("craft\\web\\assets\\fileupload\\FileUploadAsset") %} {% block content %} - {{ forms.hidden({ - name: 'action', - value: 'support/tickets/create', - })}} + {{ forms.hidden({ + name: 'action', + value: 'support/tickets/create', + })}} - {{ redirectInput('support/tickets') }} + {{ redirectInput('support/tickets') }} - {{ forms.textField({ - first: true, - required: true, - label: 'Title', - id: 'title', - name: 'title', - placeholder: 'Title', - autofocus: true, - })}} + {{ forms.textField({ + first: true, + required: true, + label: 'Title', + id: 'title', + name: 'title', + placeholder: 'Title', + autofocus: true, + })}} - {{ forms.textareaField({ - required: true, - label: 'Message', - id: 'message', - name: 'message', - placeholder: 'Message', - rows: 8, - })}} + {{ forms.textareaField({ + required: true, + label: 'Message', + id: 'message', + name: 'message', + placeholder: 'Message', + rows: 8, + })}} + + {% set priorityOptions = [{'value': null, 'label': 'Please Select'}] %} + {% for priority in ticketPriorities %} + {% set priorityOptions = priorityOptions|merge([{'value': priority.id, 'label': priority.name}]) %} + {% endfor %} + + {{ forms.selectField({ + required: true, + label: 'Ticket priority', + id: 'ticketPriorityId', + name: 'ticketPriorityId', + options: priorityOptions, + })}} {% if settings.attachments and volume %} {% include "_components/fieldtypes/Assets/input" with { diff --git a/src/templates/_tickets/ticket.twig b/src/templates/_tickets/ticket.twig index 388ef9f..1f3e829 100644 --- a/src/templates/_tickets/ticket.twig +++ b/src/templates/_tickets/ticket.twig @@ -106,6 +106,19 @@ options: statusOptions, })}} + {% set priorityOptions = [] %} + {% for priority in ticketPriorities %} + {% set priorityOptions = priorityOptions|merge([{'value': priority.id, 'label': priority.name}]) %} + {% endfor %} + + {{ forms.selectField({ + label: 'Ticket Priority', + id: 'ticketPriorityId', + name: 'ticketPriorityId', + value: ticket.ticketPriorityId, + options: priorityOptions, + })}} +
From 904c870fa4b39ba92833ec095aa043adf4a98e26 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Tue, 6 Nov 2018 21:45:59 +0000 Subject: [PATCH 02/15] bcc fix and setTo update --- src/services/MailService.php | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/services/MailService.php b/src/services/MailService.php index 55fcb96..17a0b45 100644 --- a/src/services/MailService.php +++ b/src/services/MailService.php @@ -69,12 +69,20 @@ public function sendEmail($email, $ticket) ->setSubject($this->getSubject($email, $ticket)) ->setHtmlBody($this->getTemplateHtml($email, $ticket)); + //get bcc emails + if($this->getBccEmails($email, $ticket)) { + $message->setBcc($bccEmail); + } + $toEmails = $this->getToEmails($email, $ticket); - foreach ($toEmails as $toEmail) { - $message->setTo($toEmail); - $mailer->send($message); - } + $message->setTo($toEmails); + $mailer->send($message); + + // foreach ($toEmails as $toEmail) { + // $message->setTo($toEmail); + // $mailer->send($message); + // } } public function getFromEmail() @@ -100,11 +108,18 @@ public function getToEmails($email, $ticket) return is_string($toEmail) ? StringHelper::split($toEmail) : $toEmail; } + public function getBccEmails($email, $ticket) + { + + $bccEmail = $email->bcc ?? ''; + + return is_string($bccEmail) ? StringHelper::split($bccEmail) : $bccEmail; + } + public function getSubject($email, $ticket) { // Replace keys with ticket values - $subject = Craft::$app->getView()->renderObjectTemplate($email->subject, $ticket); - + $subject = Craft::$app->getView()->renderObjectTemplate($email->subject, $ticket); return $subject; } @@ -118,8 +133,7 @@ public function getTemplateHtml($email, $ticket) // Set Craft to the site template mode $view = Craft::$app->getView(); $oldTemplateMode = $view->getTemplateMode(); - // $view->setTemplateMode($view::TEMPLATE_MODE_SITE); - $view->setTemplateMode($view::TEMPLATE_MODE_CP); + $view->setTemplateMode($view::TEMPLATE_MODE_SITE); // Render template $html = Craft::$app->view->renderTemplate($email->templatePath, $variables); From 8e5bf060c62326be885bdfadecd08c746887ed33 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 7 Nov 2018 10:42:14 +0000 Subject: [PATCH 03/15] email to help@ka and default priorites and emails --- src/migrations/Install.php | 61 +++++++++++++++---- src/services/MailService.php | 40 +++++++----- .../_settings/ticket-priorities/edit.twig | 4 +- .../_settings/ticket-priorities/index.twig | 6 +- 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 0ea235f..92342bb 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -14,6 +14,7 @@ use lukeyouell\support\records\Email as EmailRecord; use lukeyouell\support\records\TicketStatus as TicketStatusRecord; use lukeyouell\support\records\TicketStatusEmail as TicketStatusEmailRecord; +use lukeyouell\support\records\TicketPriority as TicketPriorityRecord; use Craft; use craft\config\DbConfig; @@ -214,7 +215,8 @@ protected function dropTables() protected function insertDefaultData() { - $this->_defaultTicketStatuses(); + $this->_defaultTicketStatuses(); + $this->_defaultTicketPriority(); } // Private Methods @@ -265,12 +267,14 @@ private function _defaultTicketStatuses() ]; $this->insert(TicketStatusRecord::tableName(), $data); - // Default emails + // Default emails $data = [ 'name' => 'New Ticket', - 'subject' => LitEmoji::unicodeToShortcode('[📥 New Support Ticket] {title} (#{id})'), - 'recipientType' => 'custom', - 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + // 'subject' => LitEmoji::unicodeToShortcode('[📥 New Support Ticket] {title} (#{id})'), + 'subject' => "{{siteName}}: {title} {% if ticketPriority.handle == 'critical' %}{ticketPriority.name}{% endif %}", + 'recipientType' => 'author', + // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/newTicket', 'sortOrder' => 1, 'enabled' => true, @@ -279,9 +283,11 @@ private function _defaultTicketStatuses() $data = [ 'name' => 'New Message', - 'subject' => LitEmoji::unicodeToShortcode('[📥 New Message] {title} (#{id})'), - 'recipientType' => 'custom', - 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + // 'subject' => LitEmoji::unicodeToShortcode('[📥 New Message] {title} (#{id})'), + 'subject' => "{{siteName}}: {title}", + 'recipientType' => 'author', + // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/newMessage', 'sortOrder' => 2, 'enabled' => true, @@ -290,9 +296,11 @@ private function _defaultTicketStatuses() $data = [ 'name' => 'Ticket Closed', - 'subject' => LitEmoji::unicodeToShortcode('[📕 Ticket Closed] {title} (#{id})'), - 'recipientType' => 'custom', - 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + // 'subject' => LitEmoji::unicodeToShortcode('[📕 Ticket Closed] {title} (#{id})'), + 'subject' => "{{siteName}}: {title}", + 'recipientType' => 'author', + // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + // 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/ticketClosed', 'sortOrder' => 3, 'enabled' => true, @@ -321,6 +329,37 @@ private function _defaultTicketStatuses() private function _defaultTicketPriority() { + // Default ticket priorities + $data = [ + 'name' => 'Critical', + 'handle' => 'critical', + 'colour' => 'red', + 'sortOrder' => 1 + ]; + $this->insert(TicketPriorityRecord::tableName(), $data); + + $data = [ + 'name' => 'Major', + 'handle' => 'major', + 'colour' => 'orange', + 'sortOrder' => 2, + ]; + $this->insert(TicketPriorityRecord::tableName(), $data); + + $data = [ + 'name' => 'Minor', + 'handle' => 'minor', + 'colour' => 'green', + 'sortOrder' => 3, + ]; + $this->insert(TicketPriorityRecord::tableName(), $data); + $data = [ + 'name' => 'Enhancement', + 'handle' => 'enhancement', + 'colour' => 'blue', + 'sortOrder' => 4, + ]; + $this->insert(TicketPriorityRecord::tableName(), $data); } } diff --git a/src/services/MailService.php b/src/services/MailService.php index 17a0b45..c6af86f 100644 --- a/src/services/MailService.php +++ b/src/services/MailService.php @@ -62,27 +62,39 @@ public function handleEmail($ticketId = null) public function sendEmail($email, $ticket) { - $mailer = Craft::$app->getMailer(); - + $mailer = Craft::$app->getMailer(); + $message = (new Message()) ->setFrom([$this->getFromEmail() => $this->getFromName()]) ->setSubject($this->getSubject($email, $ticket)) ->setHtmlBody($this->getTemplateHtml($email, $ticket)); - //get bcc emails - if($this->getBccEmails($email, $ticket)) { - $message->setBcc($bccEmail); - } + //get bcc emails + // $bccEmail = $this->getBccEmails($email, $ticket); + // if($bccEmail) { + // $message->setBcc($bccEmail); + // } + + // $toEmails = $this->getToEmails($email, $ticket); + + // $message->setTo($toEmails); + // $mailer->send($message); - $toEmails = $this->getToEmails($email, $ticket); + $toEmails = $this->getToEmails($email, $ticket); - $message->setTo($toEmails); - $mailer->send($message); + foreach ($toEmails as $toEmail) { + $message->setTo($toEmail); + $mailer->send($message); + } + + // resend email again as the Gmail fitler we use to forward emails to Asana needs the "to address" to be help@kurious.agency + $bccEmails = $this->getBccEmails($email, $ticket); - // foreach ($toEmails as $toEmail) { - // $message->setTo($toEmail); - // $mailer->send($message); - // } + foreach ($bccEmails as $bccEmail) { + $message->setTo($bccEmail); + $mailer->send($message); + } + } public function getFromEmail() @@ -133,7 +145,7 @@ public function getTemplateHtml($email, $ticket) // Set Craft to the site template mode $view = Craft::$app->getView(); $oldTemplateMode = $view->getTemplateMode(); - $view->setTemplateMode($view::TEMPLATE_MODE_SITE); + $view->setTemplateMode($view::TEMPLATE_MODE_SITE); // Render template $html = Craft::$app->view->renderTemplate($email->templatePath, $variables); diff --git a/src/templates/_settings/ticket-priorities/edit.twig b/src/templates/_settings/ticket-priorities/edit.twig index 46e46d2..db13569 100644 --- a/src/templates/_settings/ticket-priorities/edit.twig +++ b/src/templates/_settings/ticket-priorities/edit.twig @@ -102,13 +102,13 @@ }) }} {% endif %} #} - {{ forms.checkboxField({ + {# {{ forms.checkboxField({ label: 'New tickets get this priority by default', name: 'default', value: 1, checked: ticketPriority.default, errors: ticketPriority.getErrors('default') - })}} + })}} #} {% endblock %} diff --git a/src/templates/_settings/ticket-priorities/index.twig b/src/templates/_settings/ticket-priorities/index.twig index 117c217..5c1f3fc 100644 --- a/src/templates/_settings/ticket-priorities/index.twig +++ b/src/templates/_settings/ticket-priorities/index.twig @@ -11,7 +11,7 @@ Name Handle - Default + {# Default #} @@ -26,11 +26,11 @@ {{ status.handle }} - + {# {% if status.default %} {% endif %} - + #} From 4154c7564daa0ef52fc4ee7fe6bf78188a55d589 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 7 Nov 2018 10:43:26 +0000 Subject: [PATCH 04/15] remove default bcc from install --- src/migrations/Install.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 92342bb..57bf78d 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -274,7 +274,6 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title} {% if ticketPriority.handle == 'critical' %}{ticketPriority.name}{% endif %}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/newTicket', 'sortOrder' => 1, 'enabled' => true, @@ -287,7 +286,6 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/newMessage', 'sortOrder' => 2, 'enabled' => true, From c989b4c6e6d0458bd183885e17e88dae49386d22 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 7 Nov 2018 10:51:52 +0000 Subject: [PATCH 05/15] tidy --- src/templates/_emails/newTicket-copy.twig | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 src/templates/_emails/newTicket-copy.twig diff --git a/src/templates/_emails/newTicket-copy.twig b/src/templates/_emails/newTicket-copy.twig deleted file mode 100644 index b880b6a..0000000 --- a/src/templates/_emails/newTicket-copy.twig +++ /dev/null @@ -1,14 +0,0 @@ -ID: {{ ticket.id }}
-Priority: {{ ticket.ticketPriority.name }}
-Status: {{ ticket.ticketStatus.name }}
-Title: {{ ticket.title }}
-Author {{ ticket.author.name }}
-
-Message
-
- {% for message in ticket.messages %} - {{ message.content|nl2br }} -{% endfor %} -
-
-View ticket: {{ ticket.cpEditUrl }} \ No newline at end of file From 190ade8485022d30fbf1d3f27d1d9abb3a9cfa05 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 7 Nov 2018 11:10:23 +0000 Subject: [PATCH 06/15] tidy --- src/migrations/Install.php | 1 - src/services/MailService.php | 2 +- src/templates/_emails/newTicket.twig | 38 ---------------------------- 3 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 src/templates/_emails/newTicket.twig diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 57bf78d..68431f5 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -298,7 +298,6 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - // 'bcc' => 'help@kurious.agency', 'templatePath' => 'support/_emails/ticketClosed', 'sortOrder' => 3, 'enabled' => true, diff --git a/src/services/MailService.php b/src/services/MailService.php index c6af86f..2d506be 100644 --- a/src/services/MailService.php +++ b/src/services/MailService.php @@ -87,7 +87,7 @@ public function sendEmail($email, $ticket) $mailer->send($message); } - // resend email again as the Gmail fitler we use to forward emails to Asana needs the "to address" to be help@kurious.agency + // resend email again as the Gmail fitler we use to forward emails needs the "to address" $bccEmails = $this->getBccEmails($email, $ticket); foreach ($bccEmails as $bccEmail) { diff --git a/src/templates/_emails/newTicket.twig b/src/templates/_emails/newTicket.twig deleted file mode 100644 index 7cc5d4c..0000000 --- a/src/templates/_emails/newTicket.twig +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - {% for message in ticket.messages %} - - - - {% endfor %} - -
ID: {{ ticket.id }}
Priority: {{ ticket.ticketPriority.name }}
Status: {{ ticket.ticketStatus.name }}
Title: {{ ticket.title }}
Author: {{ ticket.author.name }}
Message
{{ message.content|nl2br }}
-
View ticket
\ No newline at end of file From d40f9e96830d726af64caa47a4c736408f533608 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 7 Nov 2018 11:16:03 +0000 Subject: [PATCH 07/15] default email location --- src/migrations/Install.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 68431f5..43ee4a8 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -274,7 +274,7 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title} {% if ticketPriority.handle == 'critical' %}{ticketPriority.name}{% endif %}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => 'support/_emails/newTicket', + 'templatePath' => '_emails/support/newTicket', 'sortOrder' => 1, 'enabled' => true, ]; @@ -286,7 +286,7 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => 'support/_emails/newMessage', + 'templatePath' => '_emails/support/newMessage', 'sortOrder' => 2, 'enabled' => true, ]; @@ -298,7 +298,7 @@ private function _defaultTicketStatuses() 'subject' => "{{siteName}}: {title}", 'recipientType' => 'author', // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => 'support/_emails/ticketClosed', + 'templatePath' => '_emails/support/ticketClosed', 'sortOrder' => 3, 'enabled' => true, ]; From 44367fd5840001fb0deda9861b1fce27e50c5ce9 Mon Sep 17 00:00:00 2001 From: Samuel Birch Date: Wed, 7 Nov 2018 13:53:28 +0000 Subject: [PATCH 08/15] colours in priority select --- src/templates/_tickets/new.twig | 37 +++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/templates/_tickets/new.twig b/src/templates/_tickets/new.twig index ffeffeb..2233377 100644 --- a/src/templates/_tickets/new.twig +++ b/src/templates/_tickets/new.twig @@ -49,18 +49,47 @@ rows: 8, })}} - {% set priorityOptions = [{'value': null, 'label': 'Please Select'}] %} + {# {% set priorityOptions = [{'value': null, 'label': 'Please Select'}] %} {% for priority in ticketPriorities %} {% set priorityOptions = priorityOptions|merge([{'value': priority.id, 'label': priority.name}]) %} - {% endfor %} + {% endfor %} #} - {{ forms.selectField({ + {# {{ forms.selectField({ required: true, label: 'Ticket priority', id: 'ticketPriorityId', name: 'ticketPriorityId', options: priorityOptions, - })}} + })}} #} + +
+
+ +
+
+ + Please Select + + +{% js %} + var $ticketPriority = $('#ticketPriority'); +if ($ticketPriority[0]) { + new Garnish.MenuBtn($ticketPriority, { + onOptionSelect: function(option) { + $('#ticketPriorityId').val($(option).data('id')) + $ticketPriority.html(' ' + $(option).data('name')); + } + }); +} +{% endjs %} {% if settings.attachments and volume %} {% include "_components/fieldtypes/Assets/input" with { From 5bf45cb9cea00b346866098d39687910ad63d582 Mon Sep 17 00:00:00 2001 From: Samuel Birch Date: Wed, 7 Nov 2018 13:59:57 +0000 Subject: [PATCH 09/15] =?UTF-8?q?removed=20sending=20the=20bcc=E2=80=99s?= =?UTF-8?q?=20as=20to=E2=80=99s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/MailService.php | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/services/MailService.php b/src/services/MailService.php index 2d506be..4fa699b 100644 --- a/src/services/MailService.php +++ b/src/services/MailService.php @@ -70,30 +70,15 @@ public function sendEmail($email, $ticket) ->setHtmlBody($this->getTemplateHtml($email, $ticket)); //get bcc emails - // $bccEmail = $this->getBccEmails($email, $ticket); - // if($bccEmail) { - // $message->setBcc($bccEmail); - // } - - // $toEmails = $this->getToEmails($email, $ticket); - - // $message->setTo($toEmails); - // $mailer->send($message); - - $toEmails = $this->getToEmails($email, $ticket); - - foreach ($toEmails as $toEmail) { - $message->setTo($toEmail); - $mailer->send($message); + $bccEmail = $this->getBccEmails($email, $ticket); + if($bccEmail) { + $message->setBcc($bccEmail); } - - // resend email again as the Gmail fitler we use to forward emails needs the "to address" - $bccEmails = $this->getBccEmails($email, $ticket); - foreach ($bccEmails as $bccEmail) { - $message->setTo($bccEmail); - $mailer->send($message); - } + $toEmails = $this->getToEmails($email, $ticket); + + $message->setTo($toEmails); + $mailer->send($message); } From 6ee42694f19c0a4e7e8cfe7583ea4571d830a820 Mon Sep 17 00:00:00 2001 From: Samuel Birch Date: Wed, 7 Nov 2018 14:03:41 +0000 Subject: [PATCH 10/15] restored defaults --- src/migrations/Install.php | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 43ee4a8..c68b707 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -270,11 +270,10 @@ private function _defaultTicketStatuses() // Default emails $data = [ 'name' => 'New Ticket', - // 'subject' => LitEmoji::unicodeToShortcode('[📥 New Support Ticket] {title} (#{id})'), - 'subject' => "{{siteName}}: {title} {% if ticketPriority.handle == 'critical' %}{ticketPriority.name}{% endif %}", - 'recipientType' => 'author', - // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => '_emails/support/newTicket', + 'subject' => LitEmoji::unicodeToShortcode('[📥 New Support Ticket] {title} (#{id})'), + 'recipientType' => 'custom', + 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + 'templatePath' => 'support/_emails/newTicket', 'sortOrder' => 1, 'enabled' => true, ]; @@ -282,11 +281,10 @@ private function _defaultTicketStatuses() $data = [ 'name' => 'New Message', - // 'subject' => LitEmoji::unicodeToShortcode('[📥 New Message] {title} (#{id})'), - 'subject' => "{{siteName}}: {title}", - 'recipientType' => 'author', - // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => '_emails/support/newMessage', + 'subject' => LitEmoji::unicodeToShortcode('[📥 New Message] {title} (#{id})'), + 'recipientType' => 'custom', + 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + 'templatePath' => 'support/_emails/newMessage', 'sortOrder' => 2, 'enabled' => true, ]; @@ -294,11 +292,10 @@ private function _defaultTicketStatuses() $data = [ 'name' => 'Ticket Closed', - // 'subject' => LitEmoji::unicodeToShortcode('[📕 Ticket Closed] {title} (#{id})'), - 'subject' => "{{siteName}}: {title}", - 'recipientType' => 'author', - // 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), - 'templatePath' => '_emails/support/ticketClosed', + 'subject' => LitEmoji::unicodeToShortcode('[📕 Ticket Closed] {title} (#{id})'), + 'recipientType' => 'custom', + 'to' => Craft::$app->systemSettings->getSetting('email', 'fromEmail'), + 'templatePath' => 'support/_emails/ticketClosed', 'sortOrder' => 3, 'enabled' => true, ]; From bf9377fd5b1eb7aa1e7f6a30f34302c08226807d Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Fri, 30 Nov 2018 16:49:39 +0000 Subject: [PATCH 11/15] ticket priority email fix, admin permission for update --- src/controllers/TicketsController.php | 8 ++++---- src/templates/_tickets/ticket.twig | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/controllers/TicketsController.php b/src/controllers/TicketsController.php index 271764f..98e1800 100644 --- a/src/controllers/TicketsController.php +++ b/src/controllers/TicketsController.php @@ -142,16 +142,16 @@ public function actionSave() if (!$ticket) { throw new NotFoundHttpException('Ticket not found'); - } - - if ($request->post('ticketStatusId')) { - Support::getInstance()->ticketService->changeTicketStatus($ticket, $ticketStatusId); } if ($request->post('ticketPriorityId')) { Support::getInstance()->ticketService->changeTicketPriority($ticket, $ticketPriorityId); } + if ($request->post('ticketStatusId')) { + Support::getInstance()->ticketService->changeTicketStatus($ticket, $ticketStatusId); + } + Craft::$app->getElements()->saveElement($ticket, false); Craft::$app->getSession()->setNotice('Ticket updated.'); diff --git a/src/templates/_tickets/ticket.twig b/src/templates/_tickets/ticket.twig index 1f3e829..ca06964 100644 --- a/src/templates/_tickets/ticket.twig +++ b/src/templates/_tickets/ticket.twig @@ -78,7 +78,7 @@ {% endblock %} {% block details %} - {% if currentUser.can('support-manageTickets') %} + {% if currentUser.admin %}
{{ csrfInput() }} @@ -145,6 +145,15 @@
+
+
+ Priority +
+
+ {{ ticket.ticketPriority.name }} +
+
+ {% if currentUser.can('support-manageTickets') %}
From 93ffd364afa0a841b527cc102be340e7eab91d0e Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Mon, 17 Dec 2018 21:23:10 +0000 Subject: [PATCH 12/15] close ticket btn --- src/controllers/TicketsController.php | 18 +++++ src/migrations/Install.php | 2 +- src/services/TicketStatusService.php | 9 +++ src/templates/_tickets/ticket.twig | 96 +++++++++++++++------------ 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/src/controllers/TicketsController.php b/src/controllers/TicketsController.php index 98e1800..a8eb1a8 100644 --- a/src/controllers/TicketsController.php +++ b/src/controllers/TicketsController.php @@ -159,4 +159,22 @@ public function actionSave() return $this->redirectToPostedUrl(); } + + public function actionCloseTicket() { + + $request = Craft::$app->getRequest(); + $ticketId= $request->post('ticketId'); + + if ($ticketId) { + + $ticket = Support::getInstance()->ticketService->getTicketById($ticketId); + $ticketStatus = Support::getInstance()->ticketStatusService->getTicketStatusByHandle("closed"); + + Support::getInstance()->ticketService->changeTicketStatus($ticket, $ticketStatus->id); + Craft::$app->getElements()->saveElement($ticket, false); + Craft::$app->getSession()->setNotice('Ticket updated.'); + } + + + } } diff --git a/src/migrations/Install.php b/src/migrations/Install.php index c68b707..bbd3947 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -239,7 +239,7 @@ private function _defaultTicketStatuses() 'handle' => 'inProgress', 'colour' => 'orange', 'sortOrder' => 2, - 'newMessage' => true, + // 'newMessage' => true, ]; $this->insert(TicketStatusRecord::tableName(), $data); diff --git a/src/services/TicketStatusService.php b/src/services/TicketStatusService.php index 83e667c..a424852 100644 --- a/src/services/TicketStatusService.php +++ b/src/services/TicketStatusService.php @@ -63,6 +63,15 @@ public function getTicketStatusById($id) return new TicketStatusModel($result); } + public function getTicketStatusByHandle($handle) + { + $result = $this->_createTicketStatusQuery() + ->where(['handle' => $handle]) + ->one(); + + return new TicketStatusModel($result); + } + public function getDefaultTicketStatus() { $result = $this->_createTicketStatusQuery() diff --git a/src/templates/_tickets/ticket.twig b/src/templates/_tickets/ticket.twig index ca06964..8e348b1 100644 --- a/src/templates/_tickets/ticket.twig +++ b/src/templates/_tickets/ticket.twig @@ -78,50 +78,58 @@ {% endblock %} {% block details %} - {% if currentUser.admin %} - -
- {{ csrfInput() }} - - {{ forms.hidden({ - name: 'action', - value: 'support/tickets/save', - })}} - - {{ forms.hidden({ - name: 'ticketId', - value: ticket.id|hash, - })}} - - {% set statusOptions = [] %} - {% for status in ticketStatuses %} - {% set statusOptions = statusOptions|merge([{'value': status.id, 'label': status.name}]) %} - {% endfor %} - - {{ forms.selectField({ - label: 'Ticket Status', - id: 'ticketStatusId', - name: 'ticketStatusId', - value: ticket.ticketStatusId, - options: statusOptions, - })}} - - {% set priorityOptions = [] %} - {% for priority in ticketPriorities %} - {% set priorityOptions = priorityOptions|merge([{'value': priority.id, 'label': priority.name}]) %} - {% endfor %} - - {{ forms.selectField({ - label: 'Ticket Priority', - id: 'ticketPriorityId', - name: 'ticketPriorityId', - value: ticket.ticketPriorityId, - options: priorityOptions, - })}} - - -
- + +
+
+ {{ csrfInput() }} + Close Ticket +
+
+ {% if currentUser.admin %} +
+
+ + {{ csrfInput() }} + + {{ forms.hidden({ + name: 'action', + value: 'support/tickets/save', + })}} + + {{ forms.hidden({ + name: 'ticketId', + value: ticket.id|hash, + })}} + + {% set statusOptions = [] %} + {% for status in ticketStatuses %} + {% set statusOptions = statusOptions|merge([{'value': status.id, 'label': status.name}]) %} + {% endfor %} + + {{ forms.selectField({ + label: 'Ticket Status', + id: 'ticketStatusId', + name: 'ticketStatusId', + value: ticket.ticketStatusId, + options: statusOptions, + })}} + + {% set priorityOptions = [] %} + {% for priority in ticketPriorities %} + {% set priorityOptions = priorityOptions|merge([{'value': priority.id, 'label': priority.name}]) %} + {% endfor %} + + {{ forms.selectField({ + label: 'Ticket Priority', + id: 'ticketPriorityId', + name: 'ticketPriorityId', + value: ticket.ticketPriorityId, + options: priorityOptions, + })}} + + +
+

{% endif %} From 14b94b87df257198cf31b14d6c1f4e0b74f65dc2 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Thu, 20 Dec 2018 20:27:12 +0000 Subject: [PATCH 13/15] close btn admin and status check --- src/templates/_tickets/ticket.twig | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/templates/_tickets/ticket.twig b/src/templates/_tickets/ticket.twig index 8e348b1..74652ed 100644 --- a/src/templates/_tickets/ticket.twig +++ b/src/templates/_tickets/ticket.twig @@ -79,12 +79,17 @@ {% block details %} -
-
- {{ csrfInput() }} - Close Ticket -
-
+ {% if not currentUser.admin and ticket.ticketStatus.handle != "closed "%} + +
+
+ {{ csrfInput() }} + Close Ticket +
+
+ + {% endif %} + {% if currentUser.admin %}
From 3d30bfd37a540cc9bab8c0bac5615bedbf58a586 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Fri, 21 Dec 2018 14:13:52 +0000 Subject: [PATCH 14/15] remove closed btn --- src/templates/_tickets/ticket.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/_tickets/ticket.twig b/src/templates/_tickets/ticket.twig index 74652ed..c489913 100644 --- a/src/templates/_tickets/ticket.twig +++ b/src/templates/_tickets/ticket.twig @@ -79,7 +79,7 @@ {% block details %} - {% if not currentUser.admin and ticket.ticketStatus.handle != "closed "%} + {% if not currentUser.admin and ticket.ticketStatus.handle != "closed" %}
From 9dd68d81df86502a1766d3f5722528279d514aca Mon Sep 17 00:00:00 2001 From: Samuel Birch Date: Sat, 19 Jan 2019 14:40:43 +0000 Subject: [PATCH 15/15] message element fix --- src/Support.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Support.php b/src/Support.php index 48f37b1..f146889 100644 --- a/src/Support.php +++ b/src/Support.php @@ -10,6 +10,7 @@ namespace lukeyouell\support; +use lukeyouell\support\elements\Message as MessageElement; use lukeyouell\support\elements\Ticket as TicketElement; use lukeyouell\support\models\Settings; use lukeyouell\support\services\SupportService as SupportServiceService;