From e6b23c7f2937b98b5eba61388c218031ac09e70c Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Wed, 14 Nov 2018 12:28:01 -0300 Subject: [PATCH 01/10] Refactor backend of mailtemplates, addd removal of last logs --- server/controllers/system.php | 4 +- .../controllers/system/edit-mail-template.php | 31 ++--- server/controllers/system/get-logs.php | 10 +- .../controllers/system/get-mail-template.php | 57 +++++++++ .../controllers/system/get-mail-templates.php | 37 ------ server/controllers/system/init-settings.php | 16 +-- .../system/recover-mail-template.php | 25 ++-- server/data/InitialMails.php | 57 --------- server/data/MailTexts.php | 85 -------------- .../mail-templates/ticket-created-staff.html | 2 +- .../data/mail-templates/ticket-created.html | 2 +- .../mail-templates/user-password-forgot.html | 2 +- server/data/mail-templates/user-signup.html | 2 +- .../mail-templates/user-system-disabled.html | 2 +- .../mail-templates/user-system-enabled.html | 2 +- server/libs/MailSender.php | 9 +- server/models/MailTemplate.php | 58 +++++++--- tests/init.rb | 4 +- tests/system/edit-mail-template.rb | 22 ---- tests/system/get-mail-templates.rb | 15 --- tests/system/mail-templates.rb | 109 ++++++++++++++++++ tests/system/recover-mail-template.rb | 19 --- 22 files changed, 274 insertions(+), 296 deletions(-) create mode 100755 server/controllers/system/get-mail-template.php delete mode 100755 server/controllers/system/get-mail-templates.php delete mode 100755 server/data/InitialMails.php delete mode 100644 tests/system/edit-mail-template.rb delete mode 100644 tests/system/get-mail-templates.rb create mode 100644 tests/system/mail-templates.rb delete mode 100644 tests/system/recover-mail-template.rb diff --git a/server/controllers/system.php b/server/controllers/system.php index 458dd036..59de6d88 100755 --- a/server/controllers/system.php +++ b/server/controllers/system.php @@ -10,7 +10,7 @@ require_once 'system/add-department.php'; require_once 'system/edit-department.php'; require_once 'system/delete-department.php'; require_once 'system/get-logs.php'; -require_once 'system/get-mail-templates.php'; +require_once 'system/get-mail-template.php'; require_once 'system/edit-mail-template.php'; require_once 'system/recover-mail-template.php'; require_once 'system/disable-registration.php'; @@ -41,7 +41,7 @@ $systemControllerGroup->addController(new AddDepartmentController); $systemControllerGroup->addController(new EditDepartmentController); $systemControllerGroup->addController(new DeleteDepartmentController); $systemControllerGroup->addController(new GetLogsController); -$systemControllerGroup->addController(new GetMailTemplatesController); +$systemControllerGroup->addController(new GetMailTemplateController); $systemControllerGroup->addController(new EditMailTemplateController); $systemControllerGroup->addController(new RecoverMailTemplateController); $systemControllerGroup->addController(new DisableRegistrationController); diff --git a/server/controllers/system/edit-mail-template.php b/server/controllers/system/edit-mail-template.php index 711a85da..781e64ca 100755 --- a/server/controllers/system/edit-mail-template.php +++ b/server/controllers/system/edit-mail-template.php @@ -9,20 +9,21 @@ use Respect\Validation\Validator as DataValidator; * * @apiGroup System * - * @apiDescription This path edit a mail template. + * @apiDescription This path edits a mail template. * * @apiPermission staff3 * - * @apiParam {String} templateType The new type of the template. - * @apiParam {String} language The new language of the template. + * @apiParam {String} template The template to edit. + * @apiParam {String} language The language of the template to edit. * @apiParam {String} subject The new subject of the template. - * @apiParam {String} body The new content of the template. + * @apiParam {String} text1 The first paragraph template. + * @apiParam {String} text2 The second paragraph template. + * @apiParam {String} text3 The third paragraph template. * * @apiUse NO_PERMISSION * @apiUse INVALID_TEMPLATE * @apiUse INVALID_LANGUAGE * @apiUse INVALID_SUBJECT - * @apiUse INVALID_BODY * * @apiSuccess {Object} data Empty object * @@ -36,7 +37,7 @@ class EditMailTemplateController extends Controller { return [ 'permission' => 'staff_3', 'requestData' => [ - 'templateType' => [ + 'template' => [ 'validation' => DataValidator::length(4), 'error' => ERRORS::INVALID_TEMPLATE ], @@ -48,26 +49,28 @@ class EditMailTemplateController extends Controller { 'validation' => DataValidator::length(4), 'error' => ERRORS::INVALID_SUBJECT ], - 'body' => [ - 'validation' => DataValidator::length(4), - 'error' => ERRORS::INVALID_BODY - ] ] ]; } public function handler() { $language = Controller::request('language'); - $templateType = Controller::request('templateType'); + $templateType = Controller::request('template'); $subject = Controller::request('subject', true); - $body = Controller::request('body'); + $texts = [ + Controller::request('text1'), + Controller::request('text2'), + Controller::request('text3'), + ]; - $mailTemplate = MailTemplate::findOne(' language = ? AND type = ?', [$language, $templateType]); + $mailTemplate = MailTemplate::findOne(' language = ? AND template = ?', [$language, $templateType]); if($mailTemplate->isNull()) { throw new Exception(ERRORS::INVALID_TEMPLATE); } $mailTemplate->subject = $subject; - $mailTemplate->body = $body; + $mailTemplate->text1 = $texts[0]; + $mailTemplate->text2 = $texts[1]; + $mailTemplate->text3 = $texts[2]; $mailTemplate->store(); Response::respondSuccess(); diff --git a/server/controllers/system/get-logs.php b/server/controllers/system/get-logs.php index 44fb4896..3784c4a0 100755 --- a/server/controllers/system/get-logs.php +++ b/server/controllers/system/get-logs.php @@ -39,9 +39,17 @@ class GetLogsController extends Controller { } public function handler() { + $this->deleteLastLogs(); $page = Controller::request('page'); $logList = Log::find('ORDER BY id desc LIMIT ? OFFSET ?', [10, 10*($page-1)]); Response::respondSuccess($logList->toArray()); } -} \ No newline at end of file + + public function deleteLastLogs() { + $removeOlderThanDays = 31; + $oldDate = floor(Date::getPreviousDate($removeOlderThanDays) / 10000); + + RedBean::exec("DELETE FROM log WHERE date < $oldDate"); + } +} diff --git a/server/controllers/system/get-mail-template.php b/server/controllers/system/get-mail-template.php new file mode 100755 index 00000000..de135229 --- /dev/null +++ b/server/controllers/system/get-mail-template.php @@ -0,0 +1,57 @@ + 'staff_3', + 'requestData' => [ + 'template' => [ + 'validation' => DataValidator::length(4), + 'error' => ERRORS::INVALID_TEMPLATE + ], + 'language' => [ + 'validation' => DataValidator::length(2, 2), + 'error' => ERRORS::INVALID_LANGUAGE + ], + ] + ]; + } + + public function handler() { + $type = Controller::request('template'); + $language = Controller::request('language'); + + $mailTemplate = MailTemplate::findOne(' language = ? AND template = ?', [$language, $type]); + + if($mailTemplate->isNull()) { + throw new Exception(ERRORS::INVALID_TEMPLATE); + } + + Response::respondSuccess($mailTemplate->toArray()); + } +} diff --git a/server/controllers/system/get-mail-templates.php b/server/controllers/system/get-mail-templates.php deleted file mode 100755 index 8dfbffa5..00000000 --- a/server/controllers/system/get-mail-templates.php +++ /dev/null @@ -1,37 +0,0 @@ - 'staff_3', - 'requestData' => [] - ]; - } - - public function handler() { - Response::respondSuccess(MailTemplate::getAll()->toArray()); - - } -} \ No newline at end of file diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php index ae177b14..4233d8a8 100755 --- a/server/controllers/system/init-settings.php +++ b/server/controllers/system/init-settings.php @@ -93,17 +93,19 @@ class InitSettingsController extends Controller { } private function storeMailTemplates() { - $mails = InitialMails::retrieve(); + $mailLanguages = MailTexts::getTexts(); - foreach ($mails as $mailType => $mailLanguages) { - foreach ($mailLanguages as $mailLanguage => $mailContent) { + foreach ($mailLanguages as $language => $mailTemplate) { + foreach ($mailTemplate as $template => $texts) { $mailTemplate = new MailTemplate(); $mailTemplate->setProperties([ - 'type' => $mailType, - 'language' => $mailLanguage, - 'subject' => $mailContent['subject'], - 'body' => $mailContent['body'] + 'template' => $template, + 'language' => $language, + 'subject' => $texts[0], + 'text1' => array_key_exists(1, $texts) ? $texts[1] : '', + 'text2' => array_key_exists(2, $texts) ? $texts[2] : '', + 'text3' => array_key_exists(3, $texts) ? $texts[3] : '', ]); $mailTemplate->store(); diff --git a/server/controllers/system/recover-mail-template.php b/server/controllers/system/recover-mail-template.php index 73803a37..8768d7e9 100755 --- a/server/controllers/system/recover-mail-template.php +++ b/server/controllers/system/recover-mail-template.php @@ -13,7 +13,7 @@ use Respect\Validation\Validator as DataValidator; * * @apiPermission staff3 * - * @apiParam {String} templateType Type of the template. + * @apiParam {String} template Type of the template. * @apiParam {String} language Lenguage of the template. * * @apiUse NO_PERMISSION @@ -32,7 +32,7 @@ class RecoverMailTemplateController extends Controller { return [ 'permission' => 'staff_3', 'requestData' => [ - 'templateType' => [ + 'template' => [ 'validation' => DataValidator::length(4), 'error' => ERRORS::INVALID_TEMPLATE ], @@ -45,23 +45,24 @@ class RecoverMailTemplateController extends Controller { } public function handler() { - $type = Controller::request('templateType'); + $templateType = Controller::request('template'); $language = Controller::request('language'); - $mailTemplate = MailTemplate::findOne(' language = ? AND type = ?', [$language, $type]); + $mailTemplate = MailTemplate::findOne(' language = ? AND template = ?', [$language, $templateType]); if($mailTemplate->isNull()) { - Response::respondError(ERRORS::INVALID_TEMPLATE); - return; + throw new Exception(ERRORS::INVALID_TEMPLATE); } - $defaultTemplates = InitialMails::retrieve(); - $mailTemplate->body = $defaultTemplates[$type][$language]['body'] ; - $mailTemplate->subject = $defaultTemplates[$type][$language]['subject'] ; + $mailTexts = MailTexts::getTexts()[$language][$templateType]; + + $mailTemplate->subject = $mailTexts[0]; + $mailTemplate->text1 = (array_key_exists(1, $mailTexts)) ? $mailTexts[1] : ''; + $mailTemplate->text2 = (array_key_exists(2, $mailTexts)) ? $mailTexts[2] : ''; + $mailTemplate->text3 = (array_key_exists(3, $mailTexts)) ? $mailTexts[3] : ''; $mailTemplate->store(); - - Response::respondSuccess(); + Response::respondSuccess(); } -} \ No newline at end of file +} diff --git a/server/data/InitialMails.php b/server/data/InitialMails.php deleted file mode 100755 index 70030839..00000000 --- a/server/data/InitialMails.php +++ /dev/null @@ -1,57 +0,0 @@ - 'data/mail-templates/user-signup.html', - 'USER_PASSWORD' => 'data/mail-templates/user-edit-password.html', - 'USER_EMAIL' => 'data/mail-templates/user-edit-email.html', - 'PASSWORD_FORGOT' => 'data/mail-templates/user-password-forgot.html', - 'USER_SYSTEM_DISABLED' => 'data/mail-templates/user-system-disabled.html', - 'USER_SYSTEM_ENABLED' => 'data/mail-templates/user-system-enabled.html', - 'TICKET_CREATED' => 'data/mail-templates/ticket-created.html', - 'TICKET_RESPONDED' => 'data/mail-templates/ticket-responded.html', - 'TICKET_CLOSED' => 'data/mail-templates/ticket-closed.html', - 'TICKET_CREATED_STAFF' => 'data/mail-templates/ticket-created-staff.html', - ]; - array_shift($texts); - - $matches = []; - foreach($texts as $key => $val) { - $matches[] = '{{' . $templateCode . '_MATCH_' . ($key + 1) . '}}'; - } - - return str_replace($matches, $texts, file_get_contents($templateFilePaths[$templateCode])); - } - - public static function generateTemplateTexts($templateCode) { - $mailTexts = MailTexts::getTexts(); - $templateTexts = []; - - foreach($mailTexts as $language => $languageTexts) { - $templateTexts[$language] = [ - 'subject' => $languageTexts[$templateCode][0], - 'body' => InitialMails::getBody($templateCode, $languageTexts[$templateCode]), - ]; - } - - return $templateTexts; - } - - public static function retrieve() { - return [ - 'USER_SIGNUP' => InitialMails::generateTemplateTexts('USER_SIGNUP'), - 'USER_PASSWORD' => InitialMails::generateTemplateTexts('USER_PASSWORD'), - 'USER_EMAIL' => InitialMails::generateTemplateTexts('USER_EMAIL'), - 'PASSWORD_FORGOT' => InitialMails::generateTemplateTexts('PASSWORD_FORGOT'), - 'USER_SYSTEM_DISABLED' => InitialMails::generateTemplateTexts('USER_SYSTEM_DISABLED'), - 'USER_SYSTEM_ENABLED' => InitialMails::generateTemplateTexts('USER_SYSTEM_ENABLED'), - 'TICKET_CREATED' => InitialMails::generateTemplateTexts('TICKET_CREATED'), - 'TICKET_RESPONDED' => InitialMails::generateTemplateTexts('TICKET_RESPONDED'), - 'TICKET_CLOSED' => InitialMails::generateTemplateTexts('TICKET_CLOSED'), - 'TICKET_CREATED_STAFF' => InitialMails::generateTemplateTexts('TICKET_CREATED_STAFF'), - ]; - } -} diff --git a/server/data/MailTexts.php b/server/data/MailTexts.php index 6721e058..3c291d31 100644 --- a/server/data/MailTexts.php +++ b/server/data/MailTexts.php @@ -8,7 +8,6 @@ class MailTexts { 'Verify your account', 'Welcome to our support center, {{name}}!. We need you to verify this email in order to get access to your account.', 'Use this code in {{url}}/verify-token/{{to}}/{{verificationToken}} or click the button below.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Password edited - OpenSupports', @@ -25,28 +24,24 @@ class MailTexts { 'Recover password', 'Hi, {{name}}. You have requested to recover your password.', 'Use this code in {{url}}/recover-password?email={{to}}&token={{token}} or click the button below.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Access system changed - OpenSupports', 'Access system changed', 'Hello, {{name}}. The system to access tickets has changed.', 'You can access and see to your tickets by using your email and the ticket number.Click in the button below to see your tickets.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Account created - OpenSupports', 'Account created', 'Hello, {{name}}. We have created an account where you can access the tickets you have sent us.', 'You can access your account by using this email ({{to}}) and password below.Please change the password as soon as you log in.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket created - OpenSupports', 'Ticket created', 'Hello, {{name}}. You have sent a new ticket titled {{title}} to our support center.', 'You can access to the ticket by its ticket number or you can click on the button below.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} New response - OpenSupports', @@ -65,7 +60,6 @@ class MailTexts { 'Ticket created', 'User {{name}} has created a new ticket titled {{title}}.', 'You can access to the ticket by its ticket number.', - '{{ticketNumber}}' ], ], 'cn' => [ @@ -74,7 +68,6 @@ class MailTexts { '验证您的帐户', '欢迎来到我们的支援中心{{name}} !. 我们需要您验证此电子邮件才能访问您的帐户。', '使用此代码 {{url}}/verify-token/{{to}}/{{verificationToken}} 或单击下面的按钮.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ '密码已编辑 - OpenSupports', @@ -91,28 +84,24 @@ class MailTexts { '恢复密码', '喂 {{name}}。 您已要求恢复密码。', '使用此代码 {{url}}/recover-password?email={{to}}&token={{token}} 或单击下面的按钮.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ '访问系统更改 - OpenSupports', '访问系统更改', '您好,{{name}}。 访问票证的系统已更改。', '您可以通过使用您的电子邮件和票号访问和查看您的机票。 点击下面的按钮查看您的票。', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ '帐户已创建 - OpenSupports', '帐户已创建', '您好,{{name}}。 我们已经创建了一个帐户,您可以访问您发送给我们的票。', '您可以在下面使用此电子邮件 ({{to}}) 和密码访问您的帐户。 请在登录后立即更改密码。', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} 已创建票证 - OpenSupports', '票据创建', '您好,{{name}}。 您已将一张名为 {{title}} 的新票发送到我们的支持中心。', '您可以通过其票号访问票证。 或者你可以点击下面的按钮。', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} 新反应 - OpenSupports', @@ -131,7 +120,6 @@ class MailTexts { '票据创建', '用戶 {{name}}。 他創造了一個題為新票 {{title}}。', '您可以通过其票号访问票证。', - '{{ticketNumber}}' ], ], 'de' => [ @@ -140,7 +128,6 @@ class MailTexts { 'Überprüfen Sie Ihr Konto', 'Willkommen in unserem Support-Center, {{name}} !. Wir müssen Sie diese E-Mail bestätigen, um Zugang zu Ihrem Konto zu erhalten.', 'Verwenden Sie diesen Code in {{url}}/verify-token/{{to}}/{{verificationToken}} oder klicken Sie auf die Schaltfläche unten.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Passwort bearbeitet - OpenSupports', @@ -157,28 +144,24 @@ class MailTexts { 'Passwort wiederherstellen', 'Hallo, {{name}}. Sie haben aufgefordert, Ihr Passwort wiederherzustellen.', 'Verwenden Sie diesen Code in {{url}}/recover-password?email={{to}}&token={{token}} oder klicken Sie auf die Schaltfläche unten.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Access system changed - OpenSupports', 'Zugriffssystem geändert', 'Hallo, {{name}}. Das System für den Zugriff auf Tickets hat sich geändert.', 'können mit Ihren E-Mails und der Ticketnummer auf Ihre Tickets zugreifen und sie sehen.Klicken Sie auf die Schaltfläche unten, um Ihre Tickets zu sehen.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Account erstellt - OpenSupports', 'Account erstellt', 'Hallo, {{name}}. Wir haben ein Konto erstellt, wo Sie auf die Tickets zugreifen können, die Sie uns geschickt haben.', 'Sie können auf Ihr Konto zugreifen, indem Sie diese E-Mail ({{to}}) und das Passwort unten verwenden.Bitte ändern Sie das Passwort, sobald Sie sich anmelden.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket erstellt - OpenSupports', 'Ticket erstellt', 'Hallo, {{name}}. Sie haben ein neues Ticket mit dem Titel {{title}} an unser Support-Center geschickt.', 'Sie können das Ticket nach der Fahrkartennummer erreichen. Oder klicken Sie auf die Schaltfläche unten.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Neue Antwort - OpenSupports', @@ -197,7 +180,6 @@ class MailTexts { 'Ticket erstellt', 'Der Benutzer {{name}} hat ein neues Ticket erstellt berechtigt {{title}}.', 'Sie können das Ticket nach der Fahrkartennummer erreichen.', - '{{ticketNumber}}' ], ], 'es' => [ @@ -206,7 +188,6 @@ class MailTexts { 'Verifica tu cuenta', 'Bienvenido a nuestro contro de soporte, {{name}}!. Necesitamos que verifiques este email para poder acceder a tu cuenta.', 'Usá este código en {{url}}/verify-token/{{to}}/{{verificationToken}} o hacé click en el botón de abajo.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Contraseña a cambiado - OpenSupports', @@ -223,28 +204,24 @@ class MailTexts { 'Recuperar contraseña', 'Hola, {{name}}. Has requerido recuperar tu contraseña.', 'Usá este codigo en {{url}}/recover-password?email={{to}}&token={{token}} o hacé click en el botón de abajo.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Sistema de acceso cambiado - OpenSupports', 'Sistema de acceso cambiado', 'Hola, {{name}}. El sistema para acceder a los tickets ha cambiado.', 'Ahora podes acceder a los tickets usando tu email y el numero de ticket.Hacé click en el botón de abajo para poder ver los tickets.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Cuenta creada - OpenSupports', 'Cuenta creada', 'Hola, {{name}}. Hemos creado una cuenta donde puedes acceder a los tickets que nos has enviado.', 'Puedes acceder usando tu email ({{to}}) y el la contraseña de abajo.Por favor, cambia tu contraseña tan pronto como ingreses al panel de usuario.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket creado - OpenSupports', 'Ticket creado', 'Hola, {{name}}. Has creado un nuevo ticket titulado {{title}} en nuestro sistema de soporte.', 'Puedes ver el ticket usando el numero de ticket prensentado abajo o puedes hacer click en el botón de más abajo.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Nueva respuesta - OpenSupports', @@ -263,7 +240,6 @@ class MailTexts { 'Ticket creado', 'El usuario {{name}} ha creado un nuevo ticket titulado {{title}}.', 'Puedes ver el ticket usando el numero de ticket prensentado abajo.', - '{{ticketNumber}}' ], ], 'fr' => [ @@ -272,7 +248,6 @@ class MailTexts { 'Vérifiez votre compte', 'Bienvenue dans notre centre de support, {{name}}!. Nous vous demandons de vérifier cet e-mail afin d accéder à votre compte.', 'Utilisez ce code dans {{url}}/verify-token/{{to}}/{{verificationToken}} ou cliquez sur le bouton ci-dessous.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Mot de passe modifié - OpenSupports', @@ -289,28 +264,24 @@ class MailTexts { 'Récupérer mot de passe', 'Salut, {{name}}. Vous avez demandé à récupérer votre mot de passe.', 'Utilisez ce code dans {{url}}/recover-password?email={{to}}&token={{token}} ou cliquez sur le bouton ci-dessous.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Système d\'accès modifié - OpenSupports', 'Système d\'accès modifié', 'Bonjour, {{name}}.Le système d\'accès aux tickets a changé.', 'Vous pouvez accéder et voir vos billets en utilisant votre email et le numéro de ticket.Cliquez sur le bouton ci-dessous pour voir vos billets.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Compte créé - OpenSupports', 'Compte créé', 'Bonjour, {{name}}. Nous avons créé un compte où vous pouvez accéder aux billets que vous nous avez envoyés.', 'Vous pouvez accéder à votre compte en utilisant ce courriel ({{to}}) et votre mot de passe ci-dessous.Veuillez modifier le mot de passe dès que vous vous connectez.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket créé - OpenSupports', 'Ticket créé', 'Bonjour, {{name}}. Vous avez envoyé un nouveau ticket intitulé {{title}} à notre centre de support.', 'Vous pouvez accéder au billet par son numéro de ticket. Ou vous pouvez cliquer sur le bouton ci-dessous.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Nouvelle réponse - OpenSupports', @@ -329,7 +300,6 @@ class MailTexts { 'Ticket créé', 'L\'utilisateur {{name}}. a créé un nouveau poste intitulé {{title}}.', 'Vous pouvez accéder au billet par son numéro de ticket.', - '{{ticketNumber}}' ], ], 'in' => [ @@ -338,7 +308,6 @@ class MailTexts { 'अपने खाते को सत्यापित करें', 'हमारे समर्थन केंद्र में आपका स्वागत है {{name}}!. आपके खाते तक पहुंच प्राप्त करने के लिए हमें आपको यह ईमेल सत्यापित करने की आवश्यकता है।', 'इस कोड का उपयोग करें {{url}}/verify-token/{{to}}/{{verificationToken}} या नीचे दिए गए बटन पर क्लिक करें।', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'sandi diedit - OpenSupports', @@ -355,28 +324,24 @@ class MailTexts { 'गोपनीय शब्द पुन प्राप्त करे', 'नमस्ते {{name}}. आपने अपना पासवर्ड पुनर्प्राप्त करने का अनुरोध किया है', 'इस कोड का उपयोग करें {{url}}/recover-password?email={{to}}&token={{token}} या नीचे दिए गए बटन पर क्लिक करें.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'sistem akses berubah - OpenSupports', 'एक्सेस सिस्टम बदल गया', 'नमस्ते {{name}}. टिकट का उपयोग करने के लिए सिस्टम बदल गया है।', 'आप अपने ईमेल और टिकट नंबर का उपयोग करके अपने टिकट तक पहुंच सकते हैं और देख सकते हैं।अपने टिकट देखने के लिए नीचे दिए गए बटन पर क्लिक करें।', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Akun telah dibuat - OpenSupports', 'खाता बन गय', 'नमस्ते {{name}}. हमने एक खाता बनाया है, जहां आप हमारे द्वारा भेजे गए टिकटों तक पहुंच सकते हैं।', 'आप इस ईमेल ({{to}}) और नीचे दिए गए पासवर्ड का उपयोग करके अपने खाते का उपयोग कर सकते हैं।जैसे ही आप लॉग इन करते हैं, तभी पासवर्ड बदल दें।', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} tiket dibuat - OpenSupports', 'टिकट बनाय', 'नमस्ते {{name}}. आपने हमारे समर्थन केंद्र पर {{title}} नामक एक नया टिकट भेजा है.', 'आप अपने टिकट नंबर से टिकट तक पहुंच सकते हैं। या आप नीचे दिए गए बटन पर क्लिक कर सकते हैं।', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} tanggapan baru - OpenSupports', @@ -395,7 +360,6 @@ class MailTexts { 'टिकट बनाया', 'उपयोगकर्ता {{name}} हकदार एक नया पद बनाया गया है {{title}}.', 'आप अपने टिकट नंबर से टिकट तक पहुंच सकते हैं।', - '{{ticketNumber}}' ], ], 'it' => [ @@ -404,7 +368,6 @@ class MailTexts { 'Verifica il tuo account', 'Benvenuto, {{name}}!. Devi verificare questa email per accedere al tuo account.', 'Clicca sul link {{url}}/verify-token/{{to}}/{{verificationToken}} o clicca sul pulsante qui sotto.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Password modificata - OpenSupports', @@ -421,28 +384,24 @@ class MailTexts { 'Recupera password', 'Ciao, {{name}}. Hai richiesto di recuperare la tua password.', 'Clicca sul link {{url}}/recover-password?email={{to}}&token={{token}} o clicca sul pulsante qui sotto.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Il sistema di accesso è cambiato - OpenSupports', 'Modifica sistema di accesso', 'Ciao, {{name}}. Il sistema di accesso ai tuoi tickets è cambiato.', 'Puoi accedere ai tuoi ticket usando la tua email e il numero del ticket.Clicca sul bottone qui sotto per vedere i tuoi tickets.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Account creato - OpenSupports', 'Account creato', 'Ciao, {{name}}. Abbiamo creato il tuo account.', ' Puoi accedere al tuo account utilizzando questa email ({{to}}) e la password qui sotto.Ti consigliamo di cambiare la password dopo il primo accesso.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} ticket creato - OpenSupports', 'Ticket inviato', 'Ciao, {{name}}. Hai inviato un nuovo ticket {{title}} al nostro centro si assistenza.', 'È possibile accedere al ticket attraverso il numero del ticket. Oppure puoi cliccare sul bottone qui sotto.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Ticket risposto - OpenSupports', @@ -461,7 +420,6 @@ class MailTexts { 'Ticket inviato', 'l\'utente {{name}} ha creato un nuovo titolo dal titolo {{title}}', 'È possibile accedere al ticket con il suo numero di ticket.', - '{{ticketNumber}}' ], ], 'jp' => [ @@ -470,7 +428,6 @@ class MailTexts { 'アカウントを確認する', 'サポートセンターへようこそ, {{name}}!. アカウントにアクセスするには、このメールを確認する必要があります。', 'でこのコードを使用 {{url}}/verify-token/{{to}}/{{verificationToken}} 下のボタンをクリックしてください.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'パスワードの編集 - OpenSupports', @@ -487,28 +444,24 @@ class MailTexts { 'パスワードを回復', 'こんにちは、{{name}}。 パスワードの回復を要求しました。', 'でこのコードを使用 {{url}}/recover-password?email={{to}}&token={{token}} 下のボタンをクリックしてください.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'アクセスシステムが変更されました - OpenSupports', 'アクセスシステムが変更されました', 'こんにちは、{{name}}。 チケットにアクセスするシステムが変更されました。', 'あなたはあなたの電子メールとチケット番号を使ってチケットにアクセスして見ることができます。チケットを見るには、下のボタンをクリックしてください。', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'アカウントが作成されました - OpenSupports', 'アカウントが作成されました', 'こんにちは、{{name}}。 あなたが送ったチケットにアクセスできるアカウントを作成しました。', '下記のメール({{to}})とパスワードを使用してアカウントにアクセスできます。ログインするとすぐにパスワードを変更してください。', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} チケットが作成されました - OpenSupports', 'チケットが作成されました', 'こんにちは、{{name}}。{{title}} という新しいチケットをサポートセンターにお送りしました。', 'そのチケット番号でチケットにアクセスできます。 または、下のボタンをクリックしてください。', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} 新しい応答 - OpenSupports', @@ -527,7 +480,6 @@ class MailTexts { 'チケットが作成されました', 'ユーザーは {{name}} 彼は題した新しいチケットを作成しました {{title}}。', 'そのチケット番号でチケットにアクセスできます。', - '{{ticketNumber}}' ], ], 'pt' => [ @@ -536,7 +488,6 @@ class MailTexts { 'Verifique sua conta', 'Bem-vindo ao nosso centro de suporte, {{name}}!. Precisamos que você verifique este e-mail para acessar sua conta.', 'Use este código em {{url}}/verify-token/{{to}}/{{verificationToken}} ou clique no botão abaixo.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Senha editada - OpenSupports', @@ -553,28 +504,24 @@ class MailTexts { 'Recuperar senha', 'Olá, {{name}}. Você solicitou a recuperação da sua senha.', 'Use este código em {{url}}/recover-password?email={{to}}&token={{token}} ou clique no botão abaixo.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Sistema de acesso alterado - OpenSupports', 'Sistema de acesso alterado', 'Oi, {{name}}. O sistema de acesso aos tickets mudou.', 'Você pode acessar e ver seus bilhetes usando seu e-mail eo número do bilhete.Clique no botão abaixo para ver os seus bilhetes.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Conta criada - OpenSupports', 'Conta criada', 'Oi, {{name}}. Criamos uma conta onde você pode acessar os ingressos que você nos enviou.', 'Você pode acessar sua conta usando este e-mail ({{to}}) e a senha abaixo.Por favor, altere a senha assim que fizer login.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket criado - OpenSupports', 'Ticket criado', 'Olá, {{name}}. Você enviou um novo ticket intitulado {{title}} para o nosso centro de suporte.', 'Você pode acessar o bilhete pelo seu número de bilhete. Ou você pode clicar no botão abaixo.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Nova resposta - OpenSupports', @@ -593,7 +540,6 @@ class MailTexts { 'Ticket criado', 'O usuário {{name}} criou um novo bilhete de direito {{title}}.', 'Você pode acessar o bilhete pelo seu número de bilhete.', - '{{ticketNumber}}' ], ], 'ru' => [ @@ -602,7 +548,6 @@ class MailTexts { 'подтвердите ваш аккаунт', 'Добро пожаловать в наш центр поддержки, {{name}}!. Нам нужно, чтобы вы подтвердили это письмо, чтобы получить доступ к вашей учетной записи.', 'Используйте этот код в {{url}}/verify-token/{{to}}/{{verificationToken}} или нажмите кнопку ниже.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Пароль изменен - OpenSupports', @@ -619,28 +564,24 @@ class MailTexts { 'Восстановить пароль', 'Здравствуй, {{name}}. Вы запросили восстановить пароль.', 'Используйте этот код в {{url}}/recover-password?email={{to}}&token={{token}} или нажмите кнопку ниже.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Система доступа изменена - OpenSupports', 'Система доступа изменена', 'Здравствуйте, {{name}}. Система доступа к билетам изменилась.', 'Вы можете получить доступ к своим билетам и посмотреть их, используя свою электронную почту и номер билета.Нажмите кнопку ниже, чтобы увидеть свои билеты.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Аккаунт создан - OpenSupports', 'Аккаунт создан', 'Здравствуйте, {{name}}. Мы создали учетную запись, где вы можете получить доступ к билетам, которые вы нам отправили.', 'Вы можете получить доступ к своей учетной записи, используя это электронное письмо ({{to}}) и пароль ниже.Измените пароль, как только вы войдете в систему.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Создан билет - OpenSupports', 'Создан билет', 'Здравствуйте, {{name}}. Вы отправили новый билет с названием {{title}} в наш центр поддержки.', 'Вы можете получить доступ к билету по его номеру билета. Или вы можете нажать на кнопку ниже.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Новый ответ - OpenSupports', @@ -659,7 +600,6 @@ class MailTexts { 'Создан билет', 'Пользователь {{name}} создал новый билет под названием {{title}}.', 'Вы можете получить доступ к билету по его номеру билета.', - '{{ticketNumber}}' ], ], 'tr' => [ @@ -668,7 +608,6 @@ class MailTexts { 'Hesabınızı doğrulayın', 'Destek merkezimize hoş geldiniz, {{name}}!. Hesabınıza erişebilmek için bu e-postayı doğrulamanız gerekiyor.', 'Bu kodu şu adreste kullanın {{url}}/verify-token/{{to}}/{{verificationToken}} veya aşağıdaki butona tıklayın.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Şifre düzenlendi - OpenSupports', @@ -685,28 +624,24 @@ class MailTexts { 'Şifre kurtarma', 'Merhaba, {{name}}. Şifrenizi geri yüklemenizi istediniz.', 'Bu kodu şu adreste kullanın {{url}}/recover-password?email={{to}}&token={{token}} veya aşağıdaki butona tıklayın.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Erişim sistemi değiştirildi - OpenSupports', 'Erişim sistemi değiştirildi', 'Merhaba, {{name}}. Biletleri erişmek için sistem değişti.', 'E-posta adresinizi ve bilet numaranızı kullanarak biletinize erişebilir ve biletlerini görebilirsiniz.Biletlerini görmek için aşağıdaki butona tıklayın.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Hesap oluşturuldu - OpenSupports', 'Hesap oluşturuldu', 'Merhaba, {{name}}. Bize gönderdiğiniz bilete erişebileceğiniz bir hesap oluşturduk.', 'Hesabınıza, ({{to}}) e-posta adresini kullanarak ve aşağıdaki şifreyle erişebilirsiniz.Lütfen giriş yaptığınızda şifreyi değiştirin.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Bilet oluşturuldu - OpenSupports', 'Bilet oluşturuldu', 'Merhaba, {{name}}. Destek merkezimize {{title}} başlıklı yeni bir bilet gönderdiniz.', 'Bilete bilet numarasından erişebilirsiniz. Ya da aşağıdaki düğmeyi tıklayabilirsiniz.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Yeni yanıt - OpenSupports', @@ -725,7 +660,6 @@ class MailTexts { 'Bilet oluşturuldu', 'Kullanıcı {{name}} başlıklı yeni bir bilet yarattı {{title}} .', 'Bilete bilet numarasından erişebilirsiniz.', - '{{ticketNumber}}' ], ], 'br' => [ @@ -734,7 +668,6 @@ class MailTexts { 'Verifique sua conta', 'Bem-vindo ao nosso centro de suporte, {{name}}!. Precisamos que você verifique este e-mail para acessar sua conta.', 'Use este código em {{url}}/verify-token/{{to}}/{{verificationToken}} ou clique no botão abaixo.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Senha editada - OpenSupports', @@ -751,28 +684,24 @@ class MailTexts { 'Recuperar senha', 'Olá, {{name}}. Você solicitou a recuperação da sua senha.', 'Use este código em {{url}}/recover-password?email={{to}}&token={{token}} ou clique no botão abaixo.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Sistema de acesso alterado - OpenSupports', 'Sistema de acesso alterado', 'Oi, {{name}}. O sistema de acesso aos tickets mudou.', 'Você pode acessar e ver seus bilhetes usando seu e-mail eo número do bilhete.Clique no botão abaixo para ver os seus bilhetes.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ 'Conta criada - OpenSupports', 'Conta criada', 'Oi, {{name}}. Criamos uma conta onde você pode acessar os ingressos que você nos enviou.', 'Você pode acessar sua conta usando este e-mail ({{to}}) e a senha abaixo.Por favor, altere a senha assim que fizer login.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Ticket criado - OpenSupports', 'Ticket criado', 'Olá, {{name}}. Você enviou um novo ticket intitulado {{title}} para o nosso centro de suporte.', 'Você pode acessar o bilhete pelo seu número de bilhete. Ou você pode clicar no botão abaixo.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Nova resposta - OpenSupports', @@ -791,7 +720,6 @@ class MailTexts { 'Ticket criado', 'O usuário {{name}} criou um novo bilhete de direito {{title}}.', 'Você pode acessar o bilhete pelo seu número de bilhete.', - '{{ticketNumber}}' ], ], 'gr' => [ @@ -800,7 +728,6 @@ class MailTexts { 'Επιβεβαιώστε το λογαριασμό σας', 'Καλώς ήρθατε στο κέντρο υποστήριξης {{name}} !. Πρέπει να επαληθεύσετε αυτό το μήνυμα ηλεκτρονικού ταχυδρομείου για να αποκτήσετε πρόσβαση στο λογαριασμό σας.', 'Χρησιμοποιήστε αυτόν τον κωδικό στο {{url}}/verify-token/{{to}}/{{verificationToken}} ή κάντε κλικ στο παρακάτω κουμπί.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Ο κωδικός επεξεργασίας τροποποιήθηκε- OpenSupports', @@ -817,29 +744,24 @@ class MailTexts { 'Ανάκτηση κωδικού πρόσβασης', 'Γεια σου, {{name}}. Ζητήσατε να ανακτήσετε τον κωδικό πρόσβασής σας.', 'Χρησιμοποιήστε αυτόν τον κωδικό στο {{url}} / recover-password? Email = {{to}} & token = {{token}} ή κάντε κλικ στο παρακάτω κουμπί.', - '{{token}}' ], 'USER_SYSTEM_DISABLED' => [ 'Το σύστημα πρόσβασης άλλαξε - OpenSupports', 'Το σύστημα πρόσβασης άλλαξε', '«Γεια σας, {{name}}. Το σύστημα πρόσβασης στα εισιτήρια έχει αλλάξει. ', 'Μπορείτε να έχετε πρόσβαση και να δείτε τα εισιτήριά σας χρησιμοποιώντας το email σας και τον αριθμό του εισιτηρίου.Κάντε κλικ στο κουμπί παρακάτω για να δείτε τα εισιτήριά σας.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ - 'Δημιουργία λογαριασμού - OpenSupports', 'Λογαριασμός που δημιουργήθηκε', '«Γεια σας, {{name}}. Δημιουργήσαμε ένα λογαριασμό στον οποίο μπορείτε να έχετε πρόσβαση στα εισιτήρια που μας έχετε στείλει. ', 'Μπορείτε να αποκτήσετε πρόσβαση στο λογαριασμό σας χρησιμοποιώντας αυτό το μήνυμα ηλεκτρονικού ταχυδρομείου ({{to}}) και τον κωδικό πρόσβασης παρακάτω.Παρακαλώ αλλάξτε τον κωδικό πρόσβασης μόλις συνδεθείτε.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Δημιουργήθηκε εισιτήριο - OpenSupports', 'Δημιουργήθηκε εισιτήριο', 'Χαίρετε, {{name}}.Έχετε στείλει ένα νέο εισιτήριο με τίτλο {{title}} στο κέντρο υποστήριξης.', 'Μπορείτε να έχετε πρόσβαση στο εισιτήριο με τον αριθμό εισιτηρίου του ή μπορείτε να κάνετε κλικ στο παρακάτω κουμπί.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Νέα απάντηση- OpenSupports', @@ -858,7 +780,6 @@ class MailTexts { 'Incident aangemaakt', 'Gebruiker {{name}} heeft een nieuw incident aangemaakt met onderwerp {{title}}.', 'Bekijk dit incident via het incidentnummer.', - '{{ticketNumber}}' ], ], 'nl' => [ @@ -867,7 +788,6 @@ class MailTexts { 'Verifieer uw account', 'Welkom bij het Support Center, {{name}}!. U moet uw account verifiëren om toegang te krijgen tot het systeem.', 'Use this code in {{url}}/verify-token/{{to}}/{{verificationToken}} or click the button below.', - '{{verificationToken}}' ], 'USER_PASSWORD' => [ 'Wachtwoord is aangepast - OpenSupports', @@ -890,22 +810,18 @@ class MailTexts { 'Toegang tot incidenten is gewijzigd', 'Hallo, {{name}}. De toegang tot incidenten is gewijzigd.', 'U kunt uw incidenten bekijken d.m.v. uw email en het incident nummer.Klik op de knop hieronder om uw tickets te bekijken.', - '{{tickets}}' ], 'USER_SYSTEM_ENABLED' => [ - 'Account is aangemaakt - OpenSupports', 'Account Aangemaakt', 'Hallo, {{name}}. We hebben een account voor u aangemaakt waarmee u uw incidenten kunt bekijken.', 'U kunt inloggen met dit email adres ({{to}}) en onderstaande wachtwoord.Verander alstublieft het wachtwoord na het inloggen.', - '{{password}}' ], 'TICKET_CREATED' => [ '#{{ticketNumber}} Incident aangemaakt - OpenSupports', 'Incident aangemaakt', 'Hallo, {{name}}. U heeft zojuist een incident aangemaakt met onderwerp {{title}} in ons support center.', 'U kunt dit incident bekijken via het incidentnummer of via de knop hieronder.', - '{{ticketNumber}}' ], 'TICKET_RESPONDED' => [ '#{{ticketNumber}} Nieuw antwoord - OpenSupports', @@ -924,7 +840,6 @@ class MailTexts { 'Incident is gesloten', 'Hallo, {{name}}. Een incident met onderwerp {{title}} is gesloten.', 'U kunt dit incident bekijken via het incidentnummer. Of klik op de knop hieronder.', - '{{ticketNumber}}' ], ], ]; diff --git a/server/data/mail-templates/ticket-created-staff.html b/server/data/mail-templates/ticket-created-staff.html index b927e2bc..ce54e633 100644 --- a/server/data/mail-templates/ticket-created-staff.html +++ b/server/data/mail-templates/ticket-created-staff.html @@ -345,7 +345,7 @@ - {{TICKET_CREATED_STAFF_MATCH_4}} + {{ticketNumber}} diff --git a/server/data/mail-templates/ticket-created.html b/server/data/mail-templates/ticket-created.html index 5a8334c5..48c6b952 100755 --- a/server/data/mail-templates/ticket-created.html +++ b/server/data/mail-templates/ticket-created.html @@ -345,7 +345,7 @@ - {{TICKET_CREATED_MATCH_4}} + {{ticketNumber}} diff --git a/server/data/mail-templates/user-password-forgot.html b/server/data/mail-templates/user-password-forgot.html index bf8ca548..2aa238e9 100755 --- a/server/data/mail-templates/user-password-forgot.html +++ b/server/data/mail-templates/user-password-forgot.html @@ -345,7 +345,7 @@ - {{PASSWORD_FORGOT_MATCH_4}} + {{token}} diff --git a/server/data/mail-templates/user-signup.html b/server/data/mail-templates/user-signup.html index 6a976373..97d3b48f 100755 --- a/server/data/mail-templates/user-signup.html +++ b/server/data/mail-templates/user-signup.html @@ -345,7 +345,7 @@ - {{USER_SIGNUP_MATCH_4}} + {{verificationToken}} diff --git a/server/data/mail-templates/user-system-disabled.html b/server/data/mail-templates/user-system-disabled.html index 9d860c10..2ed326a5 100644 --- a/server/data/mail-templates/user-system-disabled.html +++ b/server/data/mail-templates/user-system-disabled.html @@ -345,7 +345,7 @@ - {{USER_SYSTEM_DISABLED_MATCH_4}} + {{tickets}} diff --git a/server/data/mail-templates/user-system-enabled.html b/server/data/mail-templates/user-system-enabled.html index 8a5b64a3..bb326785 100755 --- a/server/data/mail-templates/user-system-enabled.html +++ b/server/data/mail-templates/user-system-enabled.html @@ -345,7 +345,7 @@ - {{USER_SYSTEM_ENABLED_MATCH_4}} + {{password}} diff --git a/server/libs/MailSender.php b/server/libs/MailSender.php index 1d6b2172..bac63093 100755 --- a/server/libs/MailSender.php +++ b/server/libs/MailSender.php @@ -34,10 +34,13 @@ class MailSender { } public function setTemplate($type, $config) { - $mailTemplate = MailTemplate::getTemplate($type); - $compiledMailContent = $mailTemplate->compile($config); + $mailTemplate = MailTemplate::getMailTemplate($type); - $this->mailOptions = array_merge($this->mailOptions, $compiledMailContent); + $this->mailOptions = array_merge($this->mailOptions, [ + 'subject' => $mailTemplate->getSubject($config), + 'body' => $mailTemplate->getBody($config), + 'to' => $config['to'], + ]); } public function send() { diff --git a/server/models/MailTemplate.php b/server/models/MailTemplate.php index bbb6507b..17b93d1a 100755 --- a/server/models/MailTemplate.php +++ b/server/models/MailTemplate.php @@ -24,11 +24,26 @@ class MailTemplate extends DataStore { const TICKET_CLOSED = 'TICKET_CLOSED'; const TICKET_CREATED_STAFF = 'TICKET_CREATED_STAFF'; - public static function getTemplate($type) { + public static function getFilePaths() { + return [ + 'USER_SIGNUP' => 'data/mail-templates/user-signup.html', + 'USER_PASSWORD' => 'data/mail-templates/user-edit-password.html', + 'USER_EMAIL' => 'data/mail-templates/user-edit-email.html', + 'PASSWORD_FORGOT' => 'data/mail-templates/user-password-forgot.html', + 'USER_SYSTEM_DISABLED' => 'data/mail-templates/user-system-disabled.html', + 'USER_SYSTEM_ENABLED' => 'data/mail-templates/user-system-enabled.html', + 'TICKET_CREATED' => 'data/mail-templates/ticket-created.html', + 'TICKET_RESPONDED' => 'data/mail-templates/ticket-responded.html', + 'TICKET_CLOSED' => 'data/mail-templates/ticket-closed.html', + 'TICKET_CREATED_STAFF' => 'data/mail-templates/ticket-created-staff.html', + ]; + } + + public static function getMailTemplate($template) { $globalLanguage = Setting::getSetting('language')->value; - $bean = RedBean::findOne(MailTemplate::TABLE, 'type = :type AND language = :language', array( - ':type' => $type, + $bean = RedBean::findOne(MailTemplate::TABLE, 'template = :template AND language = :language', array( + ':template' => $template, ':language' => $globalLanguage )); @@ -37,19 +52,33 @@ class MailTemplate extends DataStore { public static function getProps() { return [ - 'type', + 'template', 'subject', 'language', - 'body' + 'text1', + 'text2', + 'text3', ]; } - public function compile($config) { - return [ - 'body' => $this->compileString($this->body, $config), - 'subject' => $this->compileString($this->subject, $config), - 'to' => $config['to'] - ]; + public function getSubject($config) { + return $this->compileString($this->subject, $config); + } + + public function getBody($config) { + $templateFilePaths = MailTemplate::getFilePaths(); + $texts = [ + $this->text1, $this->text2, $this->text3, $this->text4, + ]; + + $matches = []; + foreach($texts as $key => $val) { + $matches[] = '{{' . $this->template . '_MATCH_' . ($key + 1) . '}}'; + } + + $body = str_replace($matches, $texts, file_get_contents($templateFilePaths[$this->template])); + + return $this->compileString($body, $config); } public function compileString($string, $config) { @@ -61,12 +90,15 @@ class MailTemplate extends DataStore { return $compiledString; } + public function toArray() { return [ - 'type' => $this->type, + 'template' => $this->template, 'subject' => $this->subject, 'language' => $this->language, - 'body' => $this->body, + 'text1' => $this->text1, + 'text2' => $this->text2, + 'text3' => $this->text3, ]; } } diff --git a/tests/init.rb b/tests/init.rb index 04356833..f4b8e84b 100644 --- a/tests/init.rb +++ b/tests/init.rb @@ -49,9 +49,7 @@ require './system/add-department.rb' require './system/edit-department.rb' require './system/delete-department.rb' require './staff/last-events.rb' -require './system/get-mail-templates.rb' -require './system/edit-mail-template.rb' -require './system/recover-mail-template.rb' +require './system/mail-templates.rb' require './system/disable-registration.rb' require './system/enable-registration.rb' require './system/add-api-key.rb' diff --git a/tests/system/edit-mail-template.rb b/tests/system/edit-mail-template.rb deleted file mode 100644 index da539e53..00000000 --- a/tests/system/edit-mail-template.rb +++ /dev/null @@ -1,22 +0,0 @@ -describe'system/edit-mail-template' do - request('/user/logout') - Scripts.login($staff[:email], $staff[:password], true) - - it 'should edit mail template' do - result= request('/system/edit-mail-template', { - csrf_userid: $csrf_userid, - csrf_token: $csrf_token, - language: 'en', - templateType: 'USER_SIGNUP', - subject: 'new subject', - body: 'new message' - }) - - (result['status']).should.equal('success') - - row = $database.getRow('mailtemplate', 1, 'id') - - (row['subject']).should.equal('new subject') - (row['body']).should.equal('new message') - end -end diff --git a/tests/system/get-mail-templates.rb b/tests/system/get-mail-templates.rb deleted file mode 100644 index 6fcaddf0..00000000 --- a/tests/system/get-mail-templates.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe'system/get-mail-templates' do - request('/user/logout') - Scripts.login($staff[:email], $staff[:password], true) - - it 'should get mail templates' do - result= request('/system/get-mail-templates', { - csrf_userid: $csrf_userid, - csrf_token: $csrf_token - }) - - (result['status']).should.equal('success') - - (result['data'].size).should.equal(140) - end -end diff --git a/tests/system/mail-templates.rb b/tests/system/mail-templates.rb new file mode 100644 index 00000000..583e0c71 --- /dev/null +++ b/tests/system/mail-templates.rb @@ -0,0 +1,109 @@ +describe 'Mail templates' do + request('/user/logout') + Scripts.login($staff[:email], $staff[:password], true) + + describe 'system/get-mail-template' do + + it 'should get USER_SIGNUP mail template' do + result = request('/system/get-mail-template', { + template: 'USER_SIGNUP', + language: 'en', + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (result['status']).should.equal('success') + (result['data']['template']).should.equal('USER_SIGNUP') + (result['data']['subject']).should.equal('Signup {{to}} - OpenSupports') + (result['data']['text1']).should.equal('Verify your account') + (result['data']['text2']).should.equal('Welcome to our support center, {{name}}!. We need you to verify this email in order to get access to your account.') + (result['data']['text3']).should.equal('Use this code in {{url}}/verify-token/{{to}}/{{verificationToken}} or click the button below.') + end + + it 'should get USER_EMAIL mail template' do + result = request('/system/get-mail-template', { + template: 'USER_EMAIL', + language: 'de', + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (result['status']).should.equal('success') + (result['data']['template']).should.equal('USER_EMAIL') + (result['data']['subject']).should.equal('E-Mail bearbeitet - OpenSupports') + (result['data']['text1']).should.equal('E-Mail geändert') + (result['data']['text2']).should.equal('Hallo, {{name}}. Wir möchten Sie darüber informieren, dass Ihre E-Mail von Ihrem Kundenbereich zu {{newemail}} geändert wurde.') + (result['data']['text3']).should.equal('') + end + + it 'should not get mail template if language or type invalid' do + result = request('/system/get-mail-template', { + template: 'USER_EMAILS', + language: 'de', + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (result['status']).should.equal('fail') + (result['message']).should.equal('INVALID_TEMPLATE') + + result = request('/system/get-mail-template', { + template: 'USER_EMAIL', + language: 'wa', + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (result['status']).should.equal('fail') + (result['message']).should.equal('INVALID_TEMPLATE') + end + end + + describe 'system/edit-mail-template' do + + it 'should edit mail template' do + result = request('/system/edit-mail-template', { + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + language: 'en', + template: 'USER_SIGNUP', + subject: 'new subject', + text1: 'new text1', + text2: 'new text2', + text3: 'new text3', + }) + + (result['status']).should.equal('success') + + row = $database.getRow('mailtemplate', 1, 'id') + + (row['template']).should.equal('USER_SIGNUP') + (row['subject']).should.equal('new subject') + (row['text1']).should.equal('new text1') + (row['text2']).should.equal('new text2') + (row['text3']).should.equal('new text3') + end + end + + describe 'system/recover-mail-template' do + + it 'should recover mail template' do + result = request('/system/recover-mail-template', { + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + language: 'en', + template: 'USER_SIGNUP', + }) + + (result['status']).should.equal('success') + + row = $database.getRow('mailtemplate', 1, 'id') + + (row['template']).should.equal('USER_SIGNUP') + (row['subject']).should.equal('Signup {{to}} - OpenSupports') + (row['text1']).should.equal('Verify your account') + (row['text2']).should.equal('Welcome to our support center, {{name}}!. We need you to verify this email in order to get access to your account.') + (row['text3']).should.equal('Use this code in {{url}}/verify-token/{{to}}/{{verificationToken}} or click the button below.') + end + end +end diff --git a/tests/system/recover-mail-template.rb b/tests/system/recover-mail-template.rb deleted file mode 100644 index 0335da96..00000000 --- a/tests/system/recover-mail-template.rb +++ /dev/null @@ -1,19 +0,0 @@ -describe'system/recover-mail-template' do - request('/user/logout') - Scripts.login($staff[:email], $staff[:password], true) - - it 'should recover mail template' do - result= request('/system/recover-mail-template', { - csrf_userid: $csrf_userid, - csrf_token: $csrf_token, - language: 'en', - templateType: 'USER_SIGNUP', - }) - - (result['status']).should.equal('success') - - row = $database.getRow('mailtemplate', 1, 'id') - - (row['subject']).should.equal('Signup {{to}} - OpenSupports') - end -end From 614b5a1a6709dcbf8a5c1a4aba85d06e73ad9af8 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Wed, 14 Nov 2018 19:58:32 -0300 Subject: [PATCH 02/10] Refactor mail templates frontend, update backend refactor --- .../settings/admin-panel-email-templates.js | 221 ++++++++++-------- .../settings/admin-panel-email-templates.scss | 4 +- client/src/core-components/form-field.scss | 2 +- server/controllers/system.php | 2 + .../controllers/system/edit-mail-template.php | 83 ++++++- .../system/get-mail-template-list.php | 36 +++ .../controllers/system/get-mail-template.php | 2 +- server/data/ERRORS.php | 15 ++ server/models/MailTemplate.php | 4 +- tests/system/mail-templates.rb | 33 ++- 10 files changed, 281 insertions(+), 121 deletions(-) create mode 100644 server/controllers/system/get-mail-template-list.php diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.js b/client/src/app/admin/panel/settings/admin-panel-email-templates.js index 076be4d2..ce3e9372 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.js +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.js @@ -18,28 +18,31 @@ import SubmitButton from 'core-components/submit-button'; class AdminPanelEmailTemplates extends React.Component { state = { - loaded: false, - items: [], - formLoading: false, - selectedIndex: 0, + loadingList: true, + loadingTemplate: false, + templates: [], + loadingForm: false, + selectedIndex: -1, edited: false, errors: {}, language: 'en', form: { - title: '', - content: '' + subject: '', + text1: '', + text2: '', + text3: '', } }; componentDidMount() { - this.retrieveEmailTemplates(); + this.retrieveMailTemplateList(); } render() { return (
- {(this.state.loaded) ? this.renderContent() : this.renderLoading()} + {(!this.state.loadingList) ? this.renderContent() : this.renderLoading()}
); } @@ -50,33 +53,7 @@ class AdminPanelEmailTemplates extends React.Component {
-
- this.onItemChange(this.state.selectedIndex, event.target.value)} fieldProps={{ - type: 'allowed', - size: 'medium' - }}/> -
-
-
- -
-
- -
-
- {i18n('SAVE')} -
-
- {(this.state.edited) ? this.renderDiscardButton() : null} -
- -
-
-
- -
+ {(this.state.selectedIndex != -1) ? this.renderForm() : null} ); } @@ -89,6 +66,42 @@ class AdminPanelEmailTemplates extends React.Component { ); } + renderForm() { + return ( +
+ this.onItemChange(this.state.selectedIndex, event.target.value)} fieldProps={{ + type: 'allowed', + size: 'medium' + }}/> +
+
+
+ +
+
+ + + {(this.state.form.text2) ? : null} + {(this.state.form.text3) ? : null} + +
+
+ {i18n('SAVE')} +
+
+ {(this.state.edited) ? this.renderDiscardButton() : null} +
+ +
+
+
+ +
+ ); + } + renderDiscardButton() { return (
@@ -102,7 +115,7 @@ class AdminPanelEmailTemplates extends React.Component { getListingProps() { return { title: i18n('EMAIL_TEMPLATES'), - items: this.getItems(), + items: this.getTemplateItems(), selectedIndex: this.state.selectedIndex, onChange: this.onItemChange.bind(this) }; @@ -112,49 +125,79 @@ class AdminPanelEmailTemplates extends React.Component { return { values: this.state.form, errors: this.state.errors, - loading: this.state.formLoading, + loading: this.state.loadingForm, onChange: (form) => {this.setState({form, edited: true})}, onValidateErrors: (errors) => {this.setState({errors})}, onSubmit: this.onFormSubmit.bind(this) } } - getItems() { - return this.state.items.map((item) => { + getTemplateItems() { + return this.state.templates.map((template) => { return { - content: item.type + content: template }; }); } onItemChange(index, language) { if(this.state.edited) { - AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index, language)); + AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.retrieveEmailTemplate.bind(this, index, language || this.state.language)); } else { - this.updateForm(index, language); + this.retrieveEmailTemplate(index, language || this.state.language); } } onFormSubmit(form) { - this.setState({formLoading: true}); + const {selectedIndex, language, templates} = this.state; + + this.setState({loadingForm: true}); API.call({ path: '/system/edit-mail-template', data: { - templateType: this.state.items[this.state.selectedIndex].type, - subject: form.title, - body: form.content, - language: this.state.language + template: templates[selectedIndex], + language, + subject: form.subject, + text1: form.text1, + text2: form.text2, + text3: form.text3, } }).then(() => { - this.setState({formLoading: false}); - this.retrieveEmailTemplates(); + this.setState({loadingForm: false, edited: false}); + }).catch(response => { + this.setState({ + loadingForm: false, + }); + + switch(response.message) { + case 'INVALID_SUBJECT': + this.setState({ + errors: {subject: 'Invalid syntax'} + }); + break; + case 'INVALID_TEXT_1': + this.setState({ + errors: {text1: 'Invalid syntax'} + }); + break; + case 'INVALID_TEXT_2': + this.setState({ + errors: {text2: 'Invalid syntax'} + }); + break; + case 'INVALID_TEXT_3': + this.setState({ + errors: {text3: 'Invalid syntax'} + }); + break; + } }); } onDiscardChangesClick(event) { event.preventDefault(); - this.onItemChange(this.state.selectedIndex); + this.onItemChange(this.state.selectedIndex, this.state.language); } onRecoverClick(event) { @@ -163,73 +206,45 @@ class AdminPanelEmailTemplates extends React.Component { } recoverEmailTemplate() { + const {selectedIndex, language, templates} = this.state; + API.call({ path: '/system/recover-mail-template', data: { - templateType: this.state.items[this.state.selectedIndex].type, - language: this.state.language + template: templates[selectedIndex], + language } }).then(() => { - this.retrieveEmailTemplates(); + this.retrieveEmailTemplate(this.state.selectedIndex, language); }); } - updateForm(index, language) { - let form = _.clone(this.state.form); - let items = this.state.items; - - language = language || this.state.language; - - form.title = (items[index] && items[index][language].subject) || ''; - form.content = (items[index] && items[index][language].body) || ''; - + retrieveEmailTemplate(index, language) { this.setState({ - selectedIndex: index, - language: language, - edited: false, - formLoading: false, - form: form, - errors: {} + loadingForm: true, }); + + API.call({ + path: '/system/get-mail-template', + data: {template: this.state.templates[index], language} + }).then((result) => this.setState({ + language, + selectedIndex: index, + edited: false, + loadingForm: false, + form: result.data, + errors: {}, + })); } - retrieveEmailTemplates() { - return API.call({ - path: '/system/get-mail-templates', + retrieveMailTemplateList() { + API.call({ + path: '/system/get-mail-template-list', data: {} }).then((result) => this.setState({ - edited: false, - loaded: true, - items: this.getParsedItems(result.data) - }, this.updateForm.bind(this, this.state.selectedIndex))); - } - - getParsedItems(items) { - let parsedItems = {}; - - _.forEach(items, (item) => { - if(parsedItems[item.type]) { - parsedItems[item.type][item.language] = { - subject: item.subject, - body: item.body - }; - } else { - parsedItems[item.type] = { - [item.language]: { - subject: item.subject, - body: item.body - } - }; - } - }); - - parsedItems = Object.keys(parsedItems).map((type) => { - return _.extend({ - type: type - }, parsedItems[type]); - }); - - return parsedItems; + loadingList: false, + templates: result.data + })); } } diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.scss b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss index 43f49a28..2b7ade6b 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.scss +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss @@ -2,7 +2,7 @@ &__text-area { width: 100%; - height: 157px; + height: 45px; } &__save-button { @@ -23,4 +23,4 @@ display: inline-block; margin-left: 10px; } -} \ No newline at end of file +} diff --git a/client/src/core-components/form-field.scss b/client/src/core-components/form-field.scss index 28a3d6df..4629ee9a 100644 --- a/client/src/core-components/form-field.scss +++ b/client/src/core-components/form-field.scss @@ -45,4 +45,4 @@ padding-bottom: 10px; } } -} \ No newline at end of file +} diff --git a/server/controllers/system.php b/server/controllers/system.php index 59de6d88..539da3e1 100755 --- a/server/controllers/system.php +++ b/server/controllers/system.php @@ -10,6 +10,7 @@ require_once 'system/add-department.php'; require_once 'system/edit-department.php'; require_once 'system/delete-department.php'; require_once 'system/get-logs.php'; +require_once 'system/get-mail-template-list.php'; require_once 'system/get-mail-template.php'; require_once 'system/edit-mail-template.php'; require_once 'system/recover-mail-template.php'; @@ -41,6 +42,7 @@ $systemControllerGroup->addController(new AddDepartmentController); $systemControllerGroup->addController(new EditDepartmentController); $systemControllerGroup->addController(new DeleteDepartmentController); $systemControllerGroup->addController(new GetLogsController); +$systemControllerGroup->addController(new GetMailTemplateListController); $systemControllerGroup->addController(new GetMailTemplateController); $systemControllerGroup->addController(new EditMailTemplateController); $systemControllerGroup->addController(new RecoverMailTemplateController); diff --git a/server/controllers/system/edit-mail-template.php b/server/controllers/system/edit-mail-template.php index 781e64ca..b452cccb 100755 --- a/server/controllers/system/edit-mail-template.php +++ b/server/controllers/system/edit-mail-template.php @@ -24,6 +24,9 @@ use Respect\Validation\Validator as DataValidator; * @apiUse INVALID_TEMPLATE * @apiUse INVALID_LANGUAGE * @apiUse INVALID_SUBJECT + * @apiUse INVALID_TEXT_1 + * @apiUse INVALID_TEXT_2 + * @apiUse INVALID_TEXT_3 * * @apiSuccess {Object} data Empty object * @@ -33,6 +36,11 @@ class EditMailTemplateController extends Controller { const PATH = '/edit-mail-template'; const METHOD = 'POST'; + private $langauge; + private $templateType; + private $subject; + private $texts; + public function validations() { return [ 'permission' => 'staff_3', @@ -54,25 +62,82 @@ class EditMailTemplateController extends Controller { } public function handler() { - $language = Controller::request('language'); - $templateType = Controller::request('template'); - $subject = Controller::request('subject', true); - $texts = [ + $this->language = Controller::request('language'); + $this->templateType = Controller::request('template'); + $this->subject = Controller::request('subject', true); + $this->texts = [ Controller::request('text1'), Controller::request('text2'), Controller::request('text3'), ]; - $mailTemplate = MailTemplate::findOne(' language = ? AND template = ?', [$language, $templateType]); + $mailTemplate = MailTemplate::findOne(' language = ? AND template = ?', [$this->language, $this->templateType]); + if($mailTemplate->isNull()) { throw new Exception(ERRORS::INVALID_TEMPLATE); } - $mailTemplate->subject = $subject; - $mailTemplate->text1 = $texts[0]; - $mailTemplate->text2 = $texts[1]; - $mailTemplate->text3 = $texts[2]; + + $this->validateReplacements(); + + $mailTemplate->subject = $this->subject; + $mailTemplate->text1 = $this->texts[0]; + $mailTemplate->text2 = $this->texts[1]; + $mailTemplate->text3 = $this->texts[2]; + $mailTemplate->store(); Response::respondSuccess(); } + + public function validateReplacements() { + $originalText = MailTexts::getTexts()[$this->language][$this->templateType]; + + if(!$this->includes( + $this->getReplacementStrings($originalText[1]), + $this->getReplacementStrings($this->texts[0]) + )) { + throw new Exception(ERRORS::INVALID_TEXT_1); + } + + if(!$this->includes( + $this->getReplacementStrings($originalText[2]), + $this->getReplacementStrings($this->texts[1]) + )) { + throw new Exception(ERRORS::INVALID_TEXT_2); + } + + if(!$this->includes( + $this->getReplacementStrings($originalText[3]), + $this->getReplacementStrings($this->texts[2]) + )) { + throw new Exception(ERRORS::INVALID_TEXT_3); + } + } + + public function includes($array1, $array2) { + foreach($array1 as $item) { + if(!in_array($item, $array2)) return false; + } + + return true; + } + + public function getReplacementStrings($string) { + $replacements = []; + + for($i=0; $i 'staff_3', + 'requestData' => [] + ]; + } + + public function handler() { + Response::respondSuccess(array_keys(MailTemplate::getFilePaths())); + } +} diff --git a/server/controllers/system/get-mail-template.php b/server/controllers/system/get-mail-template.php index de135229..86b63e6a 100755 --- a/server/controllers/system/get-mail-template.php +++ b/server/controllers/system/get-mail-template.php @@ -18,7 +18,7 @@ use Respect\Validation\Validator as DataValidator; * * @apiUse NO_PERMISSION * - * @apiSuccess {[MailTemplate](#api-Data_Structures-ObjectMailtemplate)[]} data Array of mail templates + * @apiSuccess {[MailTemplate](#api-Data_Structures-ObjectMailtemplate)} data Data of the mail template * */ diff --git a/server/data/ERRORS.php b/server/data/ERRORS.php index 5776d831..add61421 100755 --- a/server/data/ERRORS.php +++ b/server/data/ERRORS.php @@ -187,6 +187,18 @@ * @apiDefine USER_DISABLED * @apiError {String} USER_DISABLED User is disabled */ +/** + * @apiDefine INVALID_TEXT_1 + * @apiError {String} INVALID_TEXT_1 text1 of mail template has an invalid syntax or missing variables + */ +/** + * @apiDefine INVALID_TEXT_2 + * @apiError {String} INVALID_TEXT_2 text2 of mail template has an invalid syntax or missing variables + */ +/** + * @apiDefine INVALID_TEXT_3 + * @apiError {String} INVALID_TEXT_3 text3 of mail template has an invalid syntax or missing variables + */ class ERRORS { const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS'; @@ -237,4 +249,7 @@ class ERRORS { const ALREADY_DISABLED = 'ALREADY_DISABLED'; const ALREADY_ENABLED = 'ALREADY_ENABLED'; const USER_DISABLED = 'USER_DISABLED'; + const INVALID_TEXT_1 = 'INVALID_TEXT_1'; + const INVALID_TEXT_2 = 'INVALID_TEXT_2'; + const INVALID_TEXT_3 = 'INVALID_TEXT_3'; } diff --git a/server/models/MailTemplate.php b/server/models/MailTemplate.php index 17b93d1a..a9f6c74f 100755 --- a/server/models/MailTemplate.php +++ b/server/models/MailTemplate.php @@ -8,7 +8,9 @@ use RedBeanPHP\Facade as RedBean; * @apiParam {String} type The type of the mail template. * @apiParam {String} subject The subject of the mail template. * @apiParam {string} language The language of the mail template. - * @apiParam {String} body The body of the mail template. + * @apiParam {String} text1 First paragraph of the mail template. + * @apiParam {String} text2 Second paragraph of the mail template. + * @apiParam {String} text3 Thrid paragraph of the mail template. */ class MailTemplate extends DataStore { diff --git a/tests/system/mail-templates.rb b/tests/system/mail-templates.rb index 583e0c71..5de33b1a 100644 --- a/tests/system/mail-templates.rb +++ b/tests/system/mail-templates.rb @@ -69,8 +69,8 @@ describe 'Mail templates' do template: 'USER_SIGNUP', subject: 'new subject', text1: 'new text1', - text2: 'new text2', - text3: 'new text3', + text2: 'new text2 {{name}}', + text3: 'new text3 {{url}}/verify-token/{{to}}/{{verificationToken}}', }) (result['status']).should.equal('success') @@ -80,9 +80,34 @@ describe 'Mail templates' do (row['template']).should.equal('USER_SIGNUP') (row['subject']).should.equal('new subject') (row['text1']).should.equal('new text1') - (row['text2']).should.equal('new text2') - (row['text3']).should.equal('new text3') + (row['text2']).should.equal('new text2 {{name}}') + (row['text3']).should.equal('new text3 {{url}}/verify-token/{{to}}/{{verificationToken}}') end + + it 'should fail if one of the texts has invalid syntax' do + result = request('/system/edit-mail-template', { + csrf_userid: $csrf_userid, + csrf_token: $csrf_token, + language: 'en', + template: 'USER_SIGNUP', + subject: 'new subject', + text1: 'new text1', + text2: 'new text2', + text3: 'new text3 {{url}}/verify-token/{{to}}/{{verificationToken}}', + }) + + (result['status']).should.equal('fail') + (result['message']).should.equal('INVALID_TEXT_2') + + row = $database.getRow('mailtemplate', 1, 'id') + + (row['template']).should.equal('USER_SIGNUP') + (row['subject']).should.equal('new subject') + (row['text1']).should.equal('new text1') + (row['text2']).should.equal('new text2 {{name}}') + (row['text3']).should.equal('new text3 {{url}}/verify-token/{{to}}/{{verificationToken}}') + end + end describe 'system/recover-mail-template' do From 8654433702e825de4a0e8bebe984eb665ba960a9 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Wed, 14 Nov 2018 22:53:46 -0300 Subject: [PATCH 03/10] Add email template image header edition --- .../settings/admin-panel-email-templates.js | 54 +++++++++++++++---- .../settings/admin-panel-email-templates.scss | 11 ++++ client/src/data/languages/br.js | 3 ++ client/src/data/languages/cn.js | 3 ++ client/src/data/languages/de.js | 3 ++ client/src/data/languages/en.js | 3 ++ client/src/data/languages/es.js | 5 +- client/src/data/languages/fr.js | 3 ++ client/src/data/languages/gr.js | 3 ++ client/src/data/languages/in.js | 3 ++ client/src/data/languages/it.js | 3 ++ client/src/data/languages/jp.js | 3 ++ client/src/data/languages/nl.js | 3 ++ client/src/data/languages/pt.js | 3 ++ client/src/data/languages/ru.js | 3 ++ client/src/data/languages/tr.js | 3 ++ server/controllers/system/edit-settings.php | 3 +- server/controllers/system/get-settings.php | 5 +- server/controllers/system/init-settings.php | 3 +- server/data/mail-templates/ticket-closed.html | 4 +- .../mail-templates/ticket-created-staff.html | 4 +- .../data/mail-templates/ticket-created.html | 4 +- .../data/mail-templates/ticket-responded.html | 4 +- .../data/mail-templates/user-edit-email.html | 4 +- .../mail-templates/user-edit-password.html | 4 +- .../mail-templates/user-password-forgot.html | 4 +- server/data/mail-templates/user-signup.html | 4 +- .../mail-templates/user-system-disabled.html | 4 +- .../mail-templates/user-system-enabled.html | 4 +- server/models/MailTemplate.php | 3 ++ 30 files changed, 129 insertions(+), 34 deletions(-) diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.js b/client/src/app/admin/panel/settings/admin-panel-email-templates.js index ce3e9372..b659510b 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.js +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.js @@ -1,5 +1,6 @@ import React from 'react'; import _ from 'lodash'; +import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; @@ -18,6 +19,8 @@ import SubmitButton from 'core-components/submit-button'; class AdminPanelEmailTemplates extends React.Component { state = { + headerImage: '', + loadingHeaderImage: false, loadingList: true, loadingTemplate: false, templates: [], @@ -36,6 +39,7 @@ class AdminPanelEmailTemplates extends React.Component { componentDidMount() { this.retrieveMailTemplateList(); + this.retrieveHeaderImage(); } render() { @@ -49,11 +53,19 @@ class AdminPanelEmailTemplates extends React.Component { renderContent() { return ( -
-
- +
+
+
+ +
+ {(this.state.selectedIndex != -1) ? this.renderForm() : null}
- {(this.state.selectedIndex != -1) ? this.renderForm() : null} +
this.setState({headerImage: form.headerImage})} onSubmit={this.onHeaderImageSubmit.bind(this)}> +
+ + {i18n('SAVE')} +
+
); } @@ -148,6 +160,21 @@ class AdminPanelEmailTemplates extends React.Component { } } + onHeaderImageSubmit(form) { + this.setState({ + loadingHeaderImage: true, + }); + + API.call({ + path: '/system/edit-settings', + data: { + 'mail-template-header-image': form['headerImage'] + } + }).then(() => this.setState({ + loadingHeaderImage: false, + })) + } + onFormSubmit(form) { const {selectedIndex, language, templates} = this.state; @@ -169,26 +196,26 @@ class AdminPanelEmailTemplates extends React.Component { this.setState({ loadingForm: false, }); - + switch(response.message) { case 'INVALID_SUBJECT': this.setState({ - errors: {subject: 'Invalid syntax'} + errors: {subject: i18n('INVALID_SYNTAX')} }); break; case 'INVALID_TEXT_1': this.setState({ - errors: {text1: 'Invalid syntax'} + errors: {text1: i18n('INVALID_SYNTAX')} }); break; case 'INVALID_TEXT_2': this.setState({ - errors: {text2: 'Invalid syntax'} + errors: {text2: i18n('INVALID_SYNTAX')} }); break; case 'INVALID_TEXT_3': this.setState({ - errors: {text3: 'Invalid syntax'} + errors: {text3: i18n('INVALID_SYNTAX')} }); break; } @@ -246,6 +273,15 @@ class AdminPanelEmailTemplates extends React.Component { templates: result.data })); } + + retrieveHeaderImage() { + API.call({ + path: '/system/get-settings', + data: {allSettings: 1} + }).then(result => this.setState({ + headerImage: result.data['mail-template-header-image'] + })); + } } export default AdminPanelEmailTemplates; diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.scss b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss index 2b7ade6b..3ee1bd2f 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.scss +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss @@ -1,3 +1,5 @@ +@import "../../../../scss/vars"; + .admin-panel-email-templates { &__text-area { @@ -23,4 +25,13 @@ display: inline-block; margin-left: 10px; } + + &__image-container { + background-color: $very-light-grey; + display: flex; + justify-content: space-between; + align-items: center; + padding: 5px 20px; + margin-top: 20px; + } } diff --git a/client/src/data/languages/br.js b/client/src/data/languages/br.js index dd90c3cb..d5679841 100644 --- a/client/src/data/languages/br.js +++ b/client/src/data/languages/br.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Inicio', 'TICKET_NUMBER': 'Número do chamado', 'NEXT': 'Próximo', + 'SUBJECT': 'Sujeito', 'SEND_EMAIL_ON_NEW_TICKET': 'Enviar email para cada novo ticket', 'STAFF_UPDATED': 'Membro da equipe atualizado', 'UPDATE': 'Atualizar', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Ativar usuário', 'DISABLE_USER': 'Desativar usuário', + 'IMAGE_HEADER_URL': 'URL do cabeçalho da imagem', 'CHART_CREATE_TICKET': 'Chamados criados', 'CHART_CLOSE': 'Chamados fechados', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Erros encontrados', 'ERROR_IMAGE_SIZE': 'Nenhuma imagem pode ter um tamanho maior que {size} MB', 'USER_DISABLED': 'Esta conta está desativada.', + 'INVALID_SYNTAX': 'Sintaxe inválida.', //MESSAGES 'SIGNUP_SUCCESS': 'Você se registrou com sucesso em nosso sistema de suporte.', diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js index 1927a8f4..b2158680 100644 --- a/client/src/data/languages/cn.js +++ b/client/src/data/languages/cn.js @@ -177,6 +177,7 @@ export default { 'HOME': '家', 'TICKET_NUMBER': '票號', 'NEXT': '下一個', + 'SUBJECT': '学科', 'SEND_EMAIL_ON_NEW_TICKET': '电子邮件为每个新票', 'STAFF_UPDATED': '工作人员已更新', 'UPDATE': '更新', @@ -187,6 +188,7 @@ export default { 'PRIVATE': '私人的', 'ENABLE_USER': '启用用户', 'DISABLE_USER': '禁用用户', + 'IMAGE_HEADER_URL': '图片标题网址', 'CHART_CREATE_TICKET': '已創建門票', 'CHART_CLOSE': '門票已關閉', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': '發現錯誤', 'ERROR_IMAGE_SIZE': '没有图像的大小可以超过{size}MB', 'USER_DISABLED': '此帐户已被停用。', + 'INVALID_SYNTAX': '无效的语法。', //MESSAGES 'SIGNUP_SUCCESS': '您已在我們的支持系統中成功註冊', diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js index bc04b41a..b291d9af 100644 --- a/client/src/data/languages/de.js +++ b/client/src/data/languages/de.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Home', 'TICKET_NUMBER': 'Ticketnummer', 'NEXT': 'Nächstes', + 'SUBJECT': 'Gegenstand', 'SEND_EMAIL_ON_NEW_TICKET': 'E-Mail für jedes neues Ticket', 'STAFF_UPDATED': 'Mitarbeiter wurde aktualisiert', 'UPDATE': 'Aktualisierung', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'Privatgelände', 'ENABLE_USER': 'Benutzer aktivieren', 'DISABLE_USER': 'Benutzer deaktivieren', + 'IMAGE_HEADER_URL': 'URL des Image-Headers', 'CHART_CREATE_TICKET': 'Tickets erstellt', 'CHART_CLOSE': 'Tickets geschlossen', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Fehler gefunden!', 'ERROR_IMAGE_SIZE': 'Kein Bild darf größer als {size} MB sein', 'USER_DISABLED': 'Dieser Account ist deaktiviert.', + 'INVALID_SYNTAX': 'Ungültiger Satzbau.', //MESSAGES 'SIGNUP_SUCCESS': 'Sie haben sich erfolgreich in unserem Support-System registriert.', diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index fa7cbaef..39ca0115 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Home', 'TICKET_NUMBER': 'Ticket number', 'NEXT': 'Next', + 'SUBJECT': 'Subject', 'SEND_EMAIL_ON_NEW_TICKET': 'Send email on new ticket', 'STAFF_UPDATED': 'Staff member has been updated', 'UPDATE': 'Update', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'Private', 'ENABLE_USER': 'Enable User', 'DISABLE_USER': 'Disable User', + 'IMAGE_HEADER_URL': 'Image header URL', 'CHART_CREATE_TICKET': 'Tickets created', 'CHART_CLOSE': 'Tickets closed', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Errors found', 'ERROR_IMAGE_SIZE': 'No image can have a size greater than {size} MB', 'USER_DISABLED': 'This account is disabled.', + 'INVALID_SYNTAX': 'Invalid syntax.', //MESSAGES 'SIGNUP_SUCCESS': 'You have registered successfully in our support system.', diff --git a/client/src/data/languages/es.js b/client/src/data/languages/es.js index 957f536f..aaf71692 100644 --- a/client/src/data/languages/es.js +++ b/client/src/data/languages/es.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Inicio', 'TICKET_NUMBER': 'Número de Ticket', 'NEXT': 'Siguiente', + 'SUBJECT': 'Asunto', 'SEND_EMAIL_ON_NEW_TICKET': 'Enviar email por cada nuevo ticket', 'STAFF_UPDATED': 'Miembro de Staff actualizado', 'UPDATE': 'Actualizar', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Habilitar usuario', 'DISABLE_USER': 'Deshabilitar usuario', + 'IMAGE_HEADER_URL': 'URL del encabezado de la imagen', 'CHART_CREATE_TICKET': 'Tickets creados', 'CHART_CLOSE': 'Tickets cerrados', @@ -330,6 +332,8 @@ export default { 'INVALID_EMAIL_OR_TICKET_NUMBER': 'Email o numero de ticket inválido', 'INVALID_FILE': 'Archivo inválido', 'ERRORS_FOUND': 'Se encontraron errores', + 'USER_DISABLED': 'Esta cuenta está deshabilitada.', + 'INVALID_SYNTAX': 'Sintaxis inválida.', //MESSAGES 'SIGNUP_SUCCESS': 'Se ha registrado con éxito en nuestro sistema de soporte.', @@ -356,7 +360,6 @@ export default { 'SUCCESS_IMPORTING_CSV_DESCRIPTION': 'El archivo CSV se ha importado correctamente', 'SUCCESS_DELETING_ALL_USERS': 'Los usuarios se han eliminado correctamente', 'ERROR_IMAGE_SIZE': 'Ninguna imagen puede tener un tamaño superior a {size} MB', - 'USER_DISABLED': 'Esta cuenta está deshabilitada.', 'LAST_7_DAYS': 'Últimos 7 dias', 'LAST_30_DAYS': 'Últimos 30 dias', diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js index bfe97276..480c5979 100644 --- a/client/src/data/languages/fr.js +++ b/client/src/data/languages/fr.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Accueil', 'TICKET_NUMBER': 'Numéro de ticket', 'NEXT': 'Suivant', + 'SUBJECT': 'Assujettir', 'SEND_EMAIL_ON_NEW_TICKET': 'Envoyer un e-mail pour chaque nouveau ticket', 'STAFF_UPDATED': 'Le membre du personnel a été mis à jour', 'UPDATE': 'Mettre à jour', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privé', 'ENABLE_USER': 'Activer l\'utilisateur', 'DISABLE_USER': 'Désactiver l\'utilisateur', + 'IMAGE_HEADER_URL': 'URL de l\'en-tête de l\'image', 'CHART_CREATE_TICKET': 'Tickets créés', 'CHART_CLOSE': 'Tickets fermés', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Des erreurs sont survenues', 'ERROR_IMAGE_SIZE': 'Aucune image ne peut avoir une taille supérieure à {size} MB', 'USER_DISABLED': 'Ce compte est désactivé.', + 'INVALID_SYNTAX': 'Syntaxe invalide.', //MESSAGES 'SIGNUP_SUCCESS': 'Vous êtes inscrit avec succès dans notre système de support.', diff --git a/client/src/data/languages/gr.js b/client/src/data/languages/gr.js index 4c3e89ba..e5b97abb 100644 --- a/client/src/data/languages/gr.js +++ b/client/src/data/languages/gr.js @@ -177,6 +177,7 @@ 'HOME': 'Σπίτι', 'TICKET_NUMBER': 'Αριθμός εισιτηρίου', 'NEXT': 'Επόμενο', + 'SUBJECT': 'Θέμα', 'SEND_EMAIL_ON_NEW_TICKET': 'Στείλτε μήνυμα ηλκετορνικού ταχυδρομείου στο νέο εισιτήριο', 'STAFF_UPDATED': 'Το μέλος προσωπικού έχει ενημερωθεί', 'UPDATE': 'Ενημέρωση', @@ -187,6 +188,7 @@ 'PRIVATE': 'ιδιωτικός', 'ENABLE_USER': 'Ενεργοποίηση χρήστη', 'DISABLE_USER': 'Απενεργοποίηση χρήστη', + 'IMAGE_HEADER_URL': 'Διεύθυνση URL κεφαλίδας εικόνας', 'CHART_CREATE_TICKET': 'Τα εισιτήρια δημιουργήθηκαν', 'CHART_CLOSE': 'Τα εισιτήρια κλείσανε', @@ -332,6 +334,7 @@ 'ERRORS_FOUND': 'Βρέθηκαν Σφάλματα', 'ERROR_IMAGE_SIZE': 'Καμία εικόνα δεν μπορεί να έχει μέγεθος μεγαλύτερο από {size} MB', 'USER_DISABLED': 'Αυτός ο λογαριασμός είναι απενεργοποιημένος.', + 'INVALID_SYNTAX': 'Μη έγκυρη σύνταξη.', //MESSAGES 'SIGNUP_SUCCESS': 'Έχετε εγγραφεί με επιτυχία στο σύστημα υποστήριξης μας.', diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js index bf38b957..a5fe8524 100644 --- a/client/src/data/languages/in.js +++ b/client/src/data/languages/in.js @@ -177,6 +177,7 @@ export default { 'HOME': 'घर', 'TICKET_NUMBER': 'टिकट नंबर', 'NEXT': 'आगामी', + 'SUBJECT': 'विषय', 'SEND_EMAIL_ON_NEW_TICKET': 'एक ईमेल भेजने के लिए प्रत्येक नए टिकट', 'STAFF_UPDATED': 'स्टाफ सदस्य को अद्यतन किया गया है', 'UPDATE': 'अद्यतन', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'निजी', 'ENABLE_USER': 'उपयोगकर्ता सक्षम करें', 'DISABLE_USER': 'उपयोगकर्ता को अक्षम करें', + 'IMAGE_HEADER_URL': 'छवि शीर्षलेख यूआरएल', 'CHART_CREATE_TICKET': 'टिकट बनाया', 'CHART_CLOSE': 'टिकट बंद कर दिया', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'त्रुटियां मिलीं', 'ERROR_IMAGE_SIZE': 'कोई छवि {size} एमबी से अधिक आकार नहीं हो सकती है', 'USER_DISABLED': 'यह खाता अक्षम है।', + 'INVALID_SYNTAX': 'अवैध वाक्य रचना।', //MESSAGES 'SIGNUP_SUCCESS': 'आप हमारे समर्थन प्रणाली में सफलतापूर्वक दर्ज कर लिया है।', diff --git a/client/src/data/languages/it.js b/client/src/data/languages/it.js index 001867b2..86c9efb3 100644 --- a/client/src/data/languages/it.js +++ b/client/src/data/languages/it.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Home', 'TICKET_NUMBER': 'Ticket numero', 'NEXT': 'Prossimo', + 'SUBJECT': 'Soggetto', 'SEND_EMAIL_ON_NEW_TICKET': 'Invia e-mail al nuovo ticket', 'STAFF_UPDATED': 'Il membro del personale è stato aggiornato', 'UPDATE': 'Aggiornare', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privato', 'ENABLE_USER': 'Abilita utente', 'DISABLE_USER': 'Disabilita utente', + 'IMAGE_HEADER_URL': 'URL dell\'intestazione dell\'immagine', 'CHART_CREATE_TICKET': 'Tickets creato', 'CHART_CLOSE': 'Tickets chiuso', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Trovati errori', 'ERROR_IMAGE_SIZE': 'Nessuna immagine può avere una dimensione superiore a {size} MB', 'USER_DISABLED': 'Questo account è disabilitato.', + 'INVALID_SYNTAX': 'Sintassi non valida.', //MESSAGES 'SIGNUP_SUCCESS': 'È stato registrato con successo nel nostro sistema di supporto.', diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js index 77f35216..9cc7489e 100644 --- a/client/src/data/languages/jp.js +++ b/client/src/data/languages/jp.js @@ -177,6 +177,7 @@ export default { 'HOME': 'ホーム', 'TICKET_NUMBER': 'チケット番号', 'NEXT': '次', + 'SUBJECT': '件名', 'SEND_EMAIL_ON_NEW_TICKET': 'メールを送信毎に新しいチケット', 'STAFF_UPDATED': 'スタッフメンバーが更新されました', 'UPDATE': '更新', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'プライベート', 'ENABLE_USER': 'ユーザーを有効にする', 'DISABLE_USER': 'ユーザーを無効にする', + 'IMAGE_HEADER_URL': '画像のヘッダーURL', 'CHART_CREATE_TICKET': '作成されたチケット', 'CHART_CLOSE': 'チケットが閉じられました', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'エラーが見つかりました', 'ERROR_IMAGE_SIZE': 'イメージのサイズが{size} MBを超えることはできません', 'USER_DISABLED': 'このアカウントは無効です。', + 'INVALID_SYNTAX': '無効な構文。', //MESSAGES 'SIGNUP_SUCCESS': 'あなたは私たちのサポートシステムに正常に登録しました。', diff --git a/client/src/data/languages/nl.js b/client/src/data/languages/nl.js index df5daa20..72cea7e1 100644 --- a/client/src/data/languages/nl.js +++ b/client/src/data/languages/nl.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Home', 'TICKET_NUMBER': 'Incidentnummer', 'NEXT': 'Volgende', + 'SUBJECT': 'Bedrijf', 'SEND_EMAIL_ON_NEW_TICKET': 'Stuur e-mail bij nieuw incident', 'STAFF_UPDATED': 'Medewerker is gewijzigd', 'UPDATE': 'Update', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privaat', 'ENABLE_USER': 'Schakel gebruiker in', 'DISABLE_USER': 'Gebruiker uitschakelen', + 'IMAGE_HEADER_URL': 'Image header URL', 'CHART_CREATE_TICKET': 'Aangemaakte incidenten', 'CHART_CLOSE': 'Gesloten incidenten', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Er is een fout opgetreden', 'ERROR_IMAGE_SIZE': 'Geen enkele afbeelding kan groter zijn dan {size} MB', 'USER_DISABLED': 'Dit account is uitgeschakeld.', + 'INVALID_SYNTAX': 'Ongeldige syntaxis.', //MESSAGES 'SIGNUP_SUCCESS': 'U hebt zich succesvol geregistreerd in ons ondersteuningssysteem.', diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js index f7c338d8..7e323c17 100644 --- a/client/src/data/languages/pt.js +++ b/client/src/data/languages/pt.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Casa', 'TICKET_NUMBER': 'Número do bilhete', 'NEXT': 'Próximo', + 'SUBJECT': 'Sujeito', 'SEND_EMAIL_ON_NEW_TICKET': 'Enviar email para cada novo ticket', 'STAFF_UPDATED': 'Membro da equipe foi atualizado', 'UPDATE': 'Actualizar', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'privado', 'ENABLE_USER': 'Ativar usuário', 'DISABLE_USER': 'Desativar usuário', + 'IMAGE_HEADER_URL': 'URL do cabeçalho da imagem', 'CHART_CREATE_TICKET': 'Ingressos criados', 'CHART_CLOSE': 'Ingressos fechados', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Erros encontrados', 'ERROR_IMAGE_SIZE': 'Nenhuma imagem pode ter um tamanho maior que {size} MB', 'USER_DISABLED': 'Esta conta está desativada.', + 'INVALID_SYNTAX': 'Sintaxe inválida.', //MESSAGES 'SIGNUP_SUCCESS': 'Você se registrou com sucesso em nosso sistema de suporte.', diff --git a/client/src/data/languages/ru.js b/client/src/data/languages/ru.js index 1da1eb24..a4eb3f83 100644 --- a/client/src/data/languages/ru.js +++ b/client/src/data/languages/ru.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Главная', 'TICKET_NUMBER': 'Номер билета', 'NEXT': 'следующий', + 'SUBJECT': 'Предмет', 'SEND_EMAIL_ON_NEW_TICKET': 'Отправить письмо на новый билет', 'STAFF_UPDATED': 'Сотрудник обновлен', 'UPDATE': 'Обновить', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'частный', 'ENABLE_USER': 'Включить пользователя', 'DISABLE_USER': 'Отключить пользователя', + 'IMAGE_HEADER_URL': 'URL заголовка изображения', 'CHART_CREATE_TICKET': 'Билеты создано', 'CHART_CLOSE': ' Билеты закрыты', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Ошибки найдены', 'ERROR_IMAGE_SIZE': 'Изображение не может иметь размер больше {size} МБ', 'USER_DISABLED': 'Эта учетная запись отключена.', + 'INVALID_SYNTAX': 'Недопустимый синтаксис.', //MESSAGES 'SIGNUP_SUCCESS': 'Вы успешно зарегистрировались в нашей системе поддержки.', diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js index 404ff4b4..47fbe9eb 100644 --- a/client/src/data/languages/tr.js +++ b/client/src/data/languages/tr.js @@ -177,6 +177,7 @@ export default { 'HOME': 'Ev', 'TICKET_NUMBER': 'Bilet numarası', 'NEXT': 'Sonraki', + 'SUBJECT': 'konu', 'SEND_EMAIL_ON_NEW_TICKET': 'Yeni biletle e-posta gönder', 'STAFF_UPDATED': 'Çalışanlar güncellendi', 'UPDATE': 'Güncelleştirme', @@ -187,6 +188,7 @@ export default { 'PRIVATE': 'gizli', 'ENABLE_USER': 'Kullanıcıyı Etkinleştir', 'DISABLE_USER': 'Kullanıcıyı Devre Dışı Bırak', + 'IMAGE_HEADER_URL': 'Resim başlığı URL\'si', 'CHART_CREATE_TICKET': 'Biletler oluşturuldu', 'CHART_CLOSE': 'Biletler kapandı', @@ -332,6 +334,7 @@ export default { 'ERRORS_FOUND': 'Hatalar bulundu', 'ERROR_IMAGE_SIZE': 'Hiçbir resmin boyutu {size} MB\'den büyük olabilir', 'USER_DISABLED': 'Bu hesap devre dışı.', + 'INVALID_SYNTAX': 'Geçersiz sözdizimi.', //MESSAGES 'SIGNUP_SUCCESS': 'Destek sistemimize başarılı bir şekilde kayıt oldunuz.', diff --git a/server/controllers/system/edit-settings.php b/server/controllers/system/edit-settings.php index 3a47a027..51157fa7 100755 --- a/server/controllers/system/edit-settings.php +++ b/server/controllers/system/edit-settings.php @@ -49,7 +49,8 @@ class EditSettingsController extends Controller { 'allow-attachments', 'max-size', 'title', - 'url' + 'url', + 'mail-template-header-image' ]; foreach($settings as $setting) { diff --git a/server/controllers/system/get-settings.php b/server/controllers/system/get-settings.php index 5dcd636b..3dcf7ca8 100755 --- a/server/controllers/system/get-settings.php +++ b/server/controllers/system/get-settings.php @@ -53,7 +53,8 @@ class GetSettingsController extends Controller { 'departments' => Department::getDepartmentNames(), 'supportedLanguages' => Language::getSupportedLanguages(), 'allowedLanguages' => Language::getAllowedLanguages(), - 'session-prefix' => Setting::getSetting('session-prefix') + 'session-prefix' => Setting::getSetting('session-prefix')->getValue(), + 'mail-template-header-image' => Setting::getSetting('mail-template-header-image')->getValue() ]; } else { $settingsList = [ @@ -70,7 +71,7 @@ class GetSettingsController extends Controller { 'supportedLanguages' => Language::getSupportedLanguages(), 'allowedLanguages' => Language::getAllowedLanguages(), 'user-system-enabled' => intval(Setting::getSetting('user-system-enabled')->getValue()), - 'session-prefix' => Setting::getSetting('session-prefix') + 'session-prefix' => Setting::getSetting('session-prefix')->getValue() ]; } } diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php index 4233d8a8..831e3751 100755 --- a/server/controllers/system/init-settings.php +++ b/server/controllers/system/init-settings.php @@ -88,7 +88,8 @@ class InitSettingsController extends Controller { 'file-gap' => Hashing::generateRandomPrime(100000, 999999), 'file-first-number' => Hashing::generateRandomNumber(100000, 999999), 'file-quantity' => 0, - 'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_' + 'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_', + 'mail-template-header-image' => 'http://opensupports.com/logo.png' ]); } diff --git a/server/data/mail-templates/ticket-closed.html b/server/data/mail-templates/ticket-closed.html index bdecca82..6bfe8dac 100755 --- a/server/data/mail-templates/ticket-closed.html +++ b/server/data/mail-templates/ticket-closed.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/ticket-created-staff.html b/server/data/mail-templates/ticket-created-staff.html index ce54e633..f6eb6a3d 100644 --- a/server/data/mail-templates/ticket-created-staff.html +++ b/server/data/mail-templates/ticket-created-staff.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/ticket-created.html b/server/data/mail-templates/ticket-created.html index 48c6b952..360c8db2 100755 --- a/server/data/mail-templates/ticket-created.html +++ b/server/data/mail-templates/ticket-created.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/ticket-responded.html b/server/data/mail-templates/ticket-responded.html index 3b3e014f..1507c06e 100755 --- a/server/data/mail-templates/ticket-responded.html +++ b/server/data/mail-templates/ticket-responded.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/user-edit-email.html b/server/data/mail-templates/user-edit-email.html index 5e275154..d50139c4 100755 --- a/server/data/mail-templates/user-edit-email.html +++ b/server/data/mail-templates/user-edit-email.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/user-edit-password.html b/server/data/mail-templates/user-edit-password.html index d96c5985..af8097c6 100755 --- a/server/data/mail-templates/user-edit-password.html +++ b/server/data/mail-templates/user-edit-password.html @@ -302,9 +302,9 @@
- - logo
+ + logo
diff --git a/server/data/mail-templates/user-password-forgot.html b/server/data/mail-templates/user-password-forgot.html index 2aa238e9..eec0f4d1 100755 --- a/server/data/mail-templates/user-password-forgot.html +++ b/server/data/mail-templates/user-password-forgot.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/user-signup.html b/server/data/mail-templates/user-signup.html index 97d3b48f..a85896cf 100755 --- a/server/data/mail-templates/user-signup.html +++ b/server/data/mail-templates/user-signup.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/user-system-disabled.html b/server/data/mail-templates/user-system-disabled.html index 2ed326a5..9abf4350 100644 --- a/server/data/mail-templates/user-system-disabled.html +++ b/server/data/mail-templates/user-system-disabled.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/data/mail-templates/user-system-enabled.html b/server/data/mail-templates/user-system-enabled.html index bb326785..3789128d 100755 --- a/server/data/mail-templates/user-system-enabled.html +++ b/server/data/mail-templates/user-system-enabled.html @@ -302,8 +302,8 @@
-
- logo + + logo
diff --git a/server/models/MailTemplate.php b/server/models/MailTemplate.php index a9f6c74f..bb9eb0b3 100755 --- a/server/models/MailTemplate.php +++ b/server/models/MailTemplate.php @@ -78,6 +78,9 @@ class MailTemplate extends DataStore { $matches[] = '{{' . $this->template . '_MATCH_' . ($key + 1) . '}}'; } + $matches[] = '{{IMAGE_HEADER_URL}}'; + $texts[] = Setting::getSetting('mail-template-header-image')->value; + $body = str_replace($matches, $texts, file_get_contents($templateFilePaths[$this->template])); return $this->compileString($body, $config); From 9d67a19c351e5038694e12a55fa0df8d0f4584a9 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Thu, 15 Nov 2018 10:39:11 -0300 Subject: [PATCH 04/10] Fix #388 email templates langauge selection --- .../panel/settings/admin-panel-email-templates.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.js b/client/src/app/admin/panel/settings/admin-panel-email-templates.js index b659510b..ad3a2eaa 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.js +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.js @@ -18,6 +18,10 @@ import SubmitButton from 'core-components/submit-button'; class AdminPanelEmailTemplates extends React.Component { + static propTypes = { + language: React.PropTypes.string, + }; + state = { headerImage: '', loadingHeaderImage: false, @@ -28,7 +32,7 @@ class AdminPanelEmailTemplates extends React.Component { selectedIndex: -1, edited: false, errors: {}, - language: 'en', + language: this.props.language, form: { subject: '', text1: '', @@ -284,4 +288,8 @@ class AdminPanelEmailTemplates extends React.Component { } } -export default AdminPanelEmailTemplates; +export default connect((store) => { + return { + language: store.config.language, + }; +})(AdminPanelEmailTemplates); From a2e505c33d4dc60d64efe80aa5bca14eb27ba883 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Thu, 15 Nov 2018 12:53:23 -0300 Subject: [PATCH 05/10] Fix custom responses #388 --- .../tickets/admin-panel-custom-responses.js | 96 ++++++++++++------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js index 25a640a4..35801d70 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js +++ b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js @@ -21,21 +21,27 @@ import TextEditor from 'core-components/text-editor'; class AdminPanelCustomResponses extends React.Component { static defaultProps = { - items: [] + items: [], }; state = { + formClicked: false, + showForm: false, formLoading: false, selectedIndex: -1, - edited: false, errors: {}, + originalForm: { + title: '', + content: TextEditor.createEmpty(), + language: this.props.language + }, form: { title: '', content: TextEditor.createEmpty(), - language: 'en' + language: this.props.language } }; - + componentDidMount() { if (!this.props.loaded) { this.retrieveCustomResponses(); @@ -57,25 +63,7 @@ class AdminPanelCustomResponses extends React.Component {
-
-
-
-
- -
-
- -
-
- -
-
- {i18n('SAVE')} -
- {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null} -
- -
+ {this.state.showForm ? this.renderForm() : null}
); } @@ -88,11 +76,35 @@ class AdminPanelCustomResponses extends React.Component { ); } + renderForm() { + return ( +
+
+
+
+ +
+
+ +
+
+ +
+
+ {i18n('SAVE')} +
+ {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null} +
+ +
+ ); + } + renderOptionalButtons() { return (
- + {this.isEdited() ? : null}
@@ -117,7 +129,8 @@ class AdminPanelCustomResponses extends React.Component { values: this.state.form, errors: this.state.errors, loading: this.state.formLoading, - onChange: (form) => {this.setState({form, edited: true})}, + onClick: () => this.setState({formClicked: true}), + onChange: (form) => this.setState({form}), onValidateErrors: (errors) => {this.setState({errors})}, onSubmit: this.onFormSubmit.bind(this) } @@ -139,7 +152,7 @@ class AdminPanelCustomResponses extends React.Component { } onItemChange(index) { - if(this.state.edited) { + if(this.isEdited()) { AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index)); } else { this.updateForm(index); @@ -147,28 +160,30 @@ class AdminPanelCustomResponses extends React.Component { } onFormSubmit(form) { + const {items, allowedLanguages} = this.props; this.setState({formLoading: true}); if(this.state.selectedIndex !== -1) { API.call({ path: '/ticket/edit-custom-response', data: { - id: this.props.items[this.state.selectedIndex].id, - name: form.name, + id: items[this.state.selectedIndex].id, + name: form.title, content: form.content, - language: form.language + language: _.includes(allowedLanguages, form.language) ? form.language : allowedLanguages[0] } }).then(() => { - this.setState({formLoading: false}); + this.setState({formLoading: false, originalForm: form}); this.retrieveCustomResponses(); }).catch(this.onItemChange.bind(this, -1)); } else { + this.setState({form, originalForm: form}); API.call({ path: '/ticket/add-custom-response', data: { name: form.title, content: form.content, - language: form.language + language: _.includes(allowedLanguages, form.language) ? form.language : allowedLanguages[0] } }).then(() => { this.retrieveCustomResponses(); @@ -204,12 +219,14 @@ class AdminPanelCustomResponses extends React.Component { form.title = (this.props.items[index] && this.props.items[index].name) || ''; form.content = TextEditor.getEditorStateFromHTML((this.props.items[index] && this.props.items[index].content) || ''); - form.language = (this.props.items[index] && this.props.items[index].language) || 'en'; + form.language = (this.props.items[index] && this.props.items[index].language) || this.props.language; this.setState({ + formClicked: false, + showForm: true, selectedIndex: index, - edited: false, formLoading: false, + originalForm: form, form: form, errors: {} }); @@ -217,14 +234,21 @@ class AdminPanelCustomResponses extends React.Component { retrieveCustomResponses() { this.props.dispatch(AdminDataActions.retrieveCustomResponses()); - this.setState({ - edited: false - }); + } + + isEdited() { + return this.state.form.title && this.state.formClicked && ( + this.state.form.title != this.state.originalForm.title || + this.state.form.content != this.state.originalForm.content || + this.state.form.language != this.state.originalForm.language + ); } } export default connect((store) => { return { + allowedLanguages: store.config.allowedLanguages, + language: store.config.language, loaded: store.adminData.customResponsesLoaded, items: store.adminData.customResponses }; From aa86fd976305b5c89e1c83e16c5796ca9585801e Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Thu, 15 Nov 2018 16:11:28 -0300 Subject: [PATCH 06/10] Retrieve tickets individually for users --- client/src/app-components/ticket-info.scss | 3 +- .../dashboard-create-ticket-page.js | 1 - .../dashboard-list-tickets-page.js | 10 +++ .../dashboard-ticket/dashboard-ticket-page.js | 83 ++++++++++++------- .../dashboard-ticket-page.scss | 6 +- server/controllers/user/get.php | 6 +- server/models/Ticket.php | 6 +- 7 files changed, 76 insertions(+), 39 deletions(-) diff --git a/client/src/app-components/ticket-info.scss b/client/src/app-components/ticket-info.scss index 4ee52a3f..f719f36b 100644 --- a/client/src/app-components/ticket-info.scss +++ b/client/src/app-components/ticket-info.scss @@ -3,6 +3,7 @@ .ticket-info { width: 300px; font-weight: normal; + text-align: left; &__title { color: $primary-black; @@ -86,4 +87,4 @@ } } } -} \ No newline at end of file +} diff --git a/client/src/app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page.js b/client/src/app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page.js index 54378546..57e50d6c 100644 --- a/client/src/app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page.js +++ b/client/src/app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page.js @@ -34,7 +34,6 @@ class DashboardCreateTicketPage extends React.Component { onCreateTicketSuccess() { if((this.props.location.pathname !== '/create-ticket')) { - this.props.dispatch(SessionActions.getUserData()); setTimeout(() => {history.push('/dashboard')}, 2000); } else { setTimeout(() => {history.push('/check-ticket/' + result.data.ticketNumber + '/' + email)}, 1000); diff --git a/client/src/app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page.js b/client/src/app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page.js index 1623df49..352dbe40 100644 --- a/client/src/app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page.js +++ b/client/src/app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page.js @@ -1,6 +1,8 @@ import React from 'react'; import {connect} from 'react-redux'; +import SessionActions from 'actions/session-actions'; + import i18n from 'lib-app/i18n'; import Header from 'core-components/header'; @@ -15,6 +17,10 @@ class DashboardListTicketsPage extends React.Component { tickets: [] }; + componentDidMount() { + this.retrieveUserData(); + } + render() { return (
@@ -23,6 +29,10 @@ class DashboardListTicketsPage extends React.Component {
); } + + retrieveUserData() { + this.props.dispatch(SessionActions.getUserData()); + } } diff --git a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js index 4f30814d..1af40be3 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js +++ b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js @@ -1,59 +1,82 @@ import React from 'react'; import _ from 'lodash'; -import {connect} from 'react-redux'; + +import store from 'app/store'; +import SessionActions from 'actions/session-actions'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; -import SessionActions from 'actions/session-actions'; import TicketViewer from 'app-components/ticket-viewer'; +import Loading from 'core-components/loading'; +import Message from 'core-components/message'; class DashboardTicketPage extends React.Component { - static propTypes = { - tickets: React.PropTypes.array + state = { + error: null, + ticket: null, }; componentDidMount() { - let ticket = this.getTicketData(); - - if(ticket.unread) { - API.call({ - path: '/ticket/seen', - data: { - ticketNumber: ticket.ticketNumber - } - }).then(() => { - this.retrieveUserData(); - }); - } + this.retrieveTicketData(); } render() { - let ticketView = i18n('NO_PERMISSION'); - - if(!_.isEmpty(this.getTicketData())) { - ticketView = ; - } + const {ticket, error} = this.state; return (
- {ticketView} + {(ticket || error) ? this.renderContent() : }
); } - getTicketData() { - return _.find(this.props.tickets, {ticketNumber: this.props.params.ticketNumber}) || {}; + renderContent() { + const {ticket, error} = this.state; + + if(error) { + return ( + + {i18n(error)} + + ); + } else { + return ( + + ); + } + + } + + retrieveTicketData() { + API.call({ + path: '/ticket/get', + data: { + ticketNumber: this.props.params.ticketNumber, + } + }) + .then(result => { + const ticket = result.data + this.setState({ticket, error: null}) + + if(ticket.unread) { + API.call({ + path: '/ticket/seen', + data: { + ticketNumber: ticket.ticketNumber + } + }).then(() => { + this.retrieveUserData(); + }); + } + }) + .catch(result => this.setState({error: result.message})); } retrieveUserData() { - this.props.dispatch(SessionActions.getUserData()); + store.dispatch(SessionActions.getUserData()); } } -export default connect((store) => { - return { - tickets: store.session.userTickets - }; -})(DashboardTicketPage); +export default DashboardTicketPage; diff --git a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.scss b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.scss index 4caad9b2..3a16b2c2 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.scss +++ b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.scss @@ -1,3 +1,7 @@ .dashboard-ticket-page { padding: 0 10px; -} \ No newline at end of file + + &__loading { + min-height: 300px; + } +} diff --git a/server/controllers/user/get.php b/server/controllers/user/get.php index f871a870..a7f8126f 100755 --- a/server/controllers/user/get.php +++ b/server/controllers/user/get.php @@ -18,7 +18,7 @@ DataValidator::with('CustomValidations', true); * @apiUse INVALID_CREDENTIALS * * @apiSuccess {Object} data Information about an user - * @apiSuccess {String} data.name Name of the user + * @apiSuccess {String} data.name Name of the user * @apiSuccess {String} data.email Email of the user * @apiSuccess {Boolean} data.verified Indicates if the user is verified * @apiSuccess {Object} data Information about an user @@ -48,7 +48,7 @@ class GetUserController extends Controller { $ticketList = $user->sharedTicketList; foreach($ticketList as $ticket) { - $parsedTicketList[] = $ticket->toArray(); + $parsedTicketList[] = $ticket->toArray(true); } Response::respondSuccess([ @@ -58,4 +58,4 @@ class GetUserController extends Controller { 'tickets' => $parsedTicketList ]); } -} \ No newline at end of file +} diff --git a/server/models/Ticket.php b/server/models/Ticket.php index 282bd54e..10f5c0d2 100755 --- a/server/models/Ticket.php +++ b/server/models/Ticket.php @@ -106,11 +106,11 @@ class Ticket extends DataStore { return $ticketNumber; } - public function toArray() { + public function toArray($minimized = false) { return [ 'ticketNumber' => $this->ticketNumber, 'title' => $this->title, - 'content' => $this->content, + 'content' => $minimized ? strip_tags($this->content) : $this->content, 'department' => [ 'id' => $this->department->id, 'name' => $this->department->name @@ -124,7 +124,7 @@ class Ticket extends DataStore { 'priority' => $this->priority, 'author' => $this->authorToArray(), 'owner' => $this->ownerToArray(), - 'events' => $this->eventsToArray() + 'events' => $minimized ? [] : $this->eventsToArray() ]; } From e8848d898eb4ba3f01311389dcf41ce352411c0b Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Thu, 15 Nov 2018 20:33:08 -0300 Subject: [PATCH 07/10] Paginate all ticket list request, avoid returting too much data --- client/src/actions/admin-data-actions.js | 8 ++--- .../panel/tickets/admin-panel-all-tickets.js | 6 ++-- .../panel/tickets/admin-panel-my-tickets.js | 25 +++++++++----- .../panel/tickets/admin-panel-new-tickets.js | 13 +++++-- client/src/reducers/admin-data-reducer.js | 17 ++++++++-- server/controllers/staff/get-all-tickets.php | 11 ++++-- server/controllers/staff/get-new-tickets.php | 34 +++++++++++++++---- server/controllers/staff/get-tickets.php | 31 ++++++++++++++--- server/libs/DataStoreList.php | 18 +++++----- server/models/DataStore.php | 12 ++++--- tests/staff/get-new-tickets.rb | 5 +-- tests/staff/get-tickets.rb | 5 ++- 12 files changed, 135 insertions(+), 50 deletions(-) diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js index 8926b1f4..b1cccc20 100644 --- a/client/src/actions/admin-data-actions.js +++ b/client/src/actions/admin-data-actions.js @@ -12,22 +12,22 @@ export default { }; }, - retrieveMyTickets(closed = 0) { + retrieveMyTickets(page, closed = 0) { return { type: 'MY_TICKETS', payload: API.call({ path: '/staff/get-tickets', - data: {closed} + data: {page, closed} }) }; }, - retrieveNewTickets() { + retrieveNewTickets(page = 1) { return { type: 'NEW_TICKETS', payload: API.call({ path: '/staff/get-new-tickets', - data: {} + data: {page} }) }; }, diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js index bbc7ef70..736bc3ae 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js @@ -21,7 +21,7 @@ class AdminPanelAllTickets extends React.Component { state = { page: 1, query: '', - closedTicketsShown: false + closedTicketsShown: 0 }; componentDidMount() { @@ -46,7 +46,7 @@ class AdminPanelAllTickets extends React.Component { this.props.dispatch(AdminDataAction.retrieveAllTickets( this.state.page, this.state.query, - this.state.closedTicketsShown*1 + this.state.closedTicketsShown * 1 )); } @@ -63,7 +63,7 @@ class AdminPanelAllTickets extends React.Component { page: this.state.page, pages: this.props.pages, closedTicketsShown: this.state.closedTicketsShown, - onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this) + onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this) }; } diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index a5f827ac..8a07c702 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -18,15 +18,17 @@ class AdminPanelMyTickets extends React.Component { static defaultProps = { userId: 0, departments: [], - tickets: [] + tickets: [], + page: 1, + pages: 0, }; state = { - closedTicketsShown: false + closedTicketsShown: false, }; componentDidMount() { - this.props.dispatch(AdminDataAction.retrieveMyTickets()); + this.retrieveMyTickets() } render() { @@ -52,7 +54,10 @@ class AdminPanelMyTickets extends React.Component { loading: this.props.loading, ticketPath: '/admin/panel/tickets/view-ticket/', closedTicketsShown: this.state.closedTicketsShown, - onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this) + onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this), + pages: this.props.pages, + page: this.props.page, + onPageChange: event => this.retrieveMyTickets(event.target.value) }; } @@ -61,9 +66,7 @@ class AdminPanelMyTickets extends React.Component { return { closedTicketsShown: !state.closedTicketsShown }; - }, () => { - this.props.dispatch(AdminDataAction.retrieveMyTickets(this.state.closedTicketsShown * 1)); - }); + }, () => this.retrieveMyTickets()); } onCreateTicket() { @@ -79,7 +82,11 @@ class AdminPanelMyTickets extends React.Component { onCreateTicketSuccess() { ModalContainer.closeModal(); - this.props.dispatch(AdminDataAction.retrieveMyTickets()); + this.retrieveMyTickets(); + } + + retrieveMyTickets(page = this.props.page, closed = this.state.closedTicketsShown) { + this.props.dispatch(AdminDataAction.retrieveMyTickets(page, closed * 1)); } } @@ -88,6 +95,8 @@ export default connect((store) => { userId: store.session.userId, departments: store.session.userDepartments, tickets: store.adminData.myTickets, + page: store.adminData.myTicketsPage, + pages: store.adminData.myTicketsPages, loading: !store.adminData.myTicketsLoaded, error: store.adminData.myTicketsError }; diff --git a/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js index 86b5e5be..6955905e 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js @@ -18,7 +18,7 @@ class AdminPanelNewTickets extends React.Component { }; componentDidMount() { - this.props.dispatch(AdminDataAction.retrieveNewTickets()); + this.retrieveNewTickets() } render() { @@ -39,9 +39,16 @@ class AdminPanelNewTickets extends React.Component { tickets: this.props.tickets, type: 'secondary', loading: this.props.loading, - ticketPath: '/admin/panel/tickets/view-ticket/' + ticketPath: '/admin/panel/tickets/view-ticket/', + page: this.props.page, + pages: this.props.pages, + onPageChange: event => this.retrieveNewTickets(event.target.value) }; } + + retrieveNewTickets(page = this.props.page) { + this.props.dispatch(AdminDataAction.retrieveNewTickets(page)); + } } export default connect((store) => { @@ -49,6 +56,8 @@ export default connect((store) => { userId: store.session.userId, departments: store.session.userDepartments, tickets: store.adminData.newTickets, + page: store.adminData.newTicketsPage, + pages: store.adminData.newTicketsPages, loading: !store.adminData.newTicketsLoaded, error: store.adminData.newTicketsError }; diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index 5aa12b2d..abb70499 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -11,14 +11,20 @@ class AdminDataReducer extends Reducer { customResponsesLoaded: false, myTickets: [], + myTicketsPage: 1, + myTicketsPages: 1, myTicketsLoaded: false, myTicketsError: false, newTickets: [], + newTicketsPage: 1, + newTicketsPages: 1, newTicketsLoaded: false, newTicketsError: false, allTickets: [], + allTicketsPage: 1, + allTicketsPages: 1, allTicketsLoaded: false, allTicketsError: false, @@ -61,7 +67,9 @@ class AdminDataReducer extends Reducer { onMyTicketsRetrieved(state, payload) { return _.extend({}, state, { - myTickets: payload.data, + myTickets: payload.data.tickets, + myTicketsPage: payload.data.page * 1, + myTicketsPages: payload.data.pages * 1, myTicketsLoaded: true }); } @@ -82,7 +90,9 @@ class AdminDataReducer extends Reducer { onNewTicketsRetrieved(state, payload) { return _.extend({}, state, { - newTickets: payload.data, + newTickets: payload.data.tickets, + newTicketsPage: payload.data.page * 1, + newTicketsPages: payload.data.pages * 1, newTicketsLoaded: true }); } @@ -104,7 +114,8 @@ class AdminDataReducer extends Reducer { onAllTicketsRetrieved(state, payload) { return _.extend({}, state, { allTickets: payload.data.tickets, - allTicketsPages: payload.data.pages, + allTicketsPage: payload.data.page * 1, + allTicketsPages: payload.data.pages * 1, allTicketsLoaded: true }); } diff --git a/server/controllers/staff/get-all-tickets.php b/server/controllers/staff/get-all-tickets.php index 7c38a489..17b6be71 100755 --- a/server/controllers/staff/get-all-tickets.php +++ b/server/controllers/staff/get-all-tickets.php @@ -52,7 +52,7 @@ class GetAllTicketsStaffController extends Controller { } Response::respondSuccess([ - 'tickets' => $this->getTicketList()->toArray(), + 'tickets' => $this->getTicketList()->toArray(true), 'pages' => $this->getTotalPages() ]); } @@ -81,9 +81,14 @@ class GetAllTicketsStaffController extends Controller { } private function getTotalPages() { - $query = $this->getStaffDepartmentsQueryFilter(); + $query = $this->getSearchQuery(); + $query .= $this->getStaffDepartmentsQueryFilter(); + $query .= $this->getClosedFilter(); - return ceil(Ticket::count($query) / 10); + return ceil(Ticket::count($query, [ + Controller::request('query') . '%', + '%' . Controller::request('query') . '%' + ]) / 10); } private function getStaffDepartmentsQueryFilter() { diff --git a/server/controllers/staff/get-new-tickets.php b/server/controllers/staff/get-new-tickets.php index c342ac11..381ca2a3 100755 --- a/server/controllers/staff/get-new-tickets.php +++ b/server/controllers/staff/get-new-tickets.php @@ -14,9 +14,15 @@ use Respect\Validation\Validator as DataValidator; * * @apiPermission staff1 * - * @apiUse NO_PERMISSION + * @apiParam {Number} page The page number. * - * @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data Array of new tickets. + * @apiUse NO_PERMISSION + * @apiUse INVALID_PAGE + * + * @apiSuccess {Object} data Information about a tickets and quantity of pages. + * @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data.tickets Array of new tickets of the current page. + * @apiSuccess {Number} data.page Number of current page. + * @apiSuccess {Number} data.pages Quantity of pages. * */ @@ -27,7 +33,12 @@ class GetNewTicketsStaffController extends Controller { public function validations() { return[ 'permission' => 'staff_1', - 'requestData' => [] + 'requestData' => [ + 'page' => [ + 'validation' => DataValidator::numeric(), + 'error' => ERRORS::INVALID_PAGE + ] + ] ]; } public function handler() { @@ -37,6 +48,8 @@ class GetNewTicketsStaffController extends Controller { } $user = Controller::getLoggedUser(); + $page = Controller::request('page'); + $query = ' ('; foreach ($user->sharedDepartmentList as $department) { $query .= 'department_id=' . $department->id . ' OR '; @@ -45,13 +58,22 @@ class GetNewTicketsStaffController extends Controller { $ownerExists = RedBean::exec('SHOW COLUMNS FROM ticket LIKE \'owner_id\''); if($ownerExists != 0) { - $query .= 'FALSE) AND owner_id IS NULL'; + $query .= 'FALSE) AND closed = 0 AND owner_id IS NULL'; } else { - $query .= 'FALSE)'; + $query .= 'FALSE) AND closed = 0'; } + $countTotal = Ticket::count($query); + + $query .= ' ORDER BY unread_staff DESC'; + $query .= ' LIMIT 10 OFFSET ' . ($page-1)*10; + $ticketList = Ticket::find($query); - Response::respondSuccess($ticketList->toArray()); + Response::respondSuccess([ + 'tickets' => $ticketList->toArray(true), + 'page' => $page, + 'pages' => ceil($countTotal / 10) + ]); } } diff --git a/server/controllers/staff/get-tickets.php b/server/controllers/staff/get-tickets.php index 137cb7eb..e5393ca9 100755 --- a/server/controllers/staff/get-tickets.php +++ b/server/controllers/staff/get-tickets.php @@ -13,11 +13,16 @@ use Respect\Validation\Validator as DataValidator; * * @apiPermission staff1 * + * @apiParam {Number} page The page number. * @apiParam {bool} closed Include closed tickets in the response. * * @apiUse NO_PERMISSION - * - * @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data Array of tickets assigned to the staff + * @apiUse INVALID_PAGE + * + * @apiSuccess {Object} data Information about a tickets and quantity of pages. + * @apiSuccess {[Ticket](#api-Data_Structures-ObjectTicket)[]} data.tickets Array of tickets assigned to the staff of the current page. + * @apiSuccess {Number} data.page Number of current page. + * @apiSuccess {Number} data.pages Quantity of pages. * */ @@ -28,17 +33,33 @@ class GetTicketStaffController extends Controller { public function validations() { return [ 'permission' => 'staff_1', - 'requestData' => [] + 'requestData' => [ + 'page' => [ + 'validation' => DataValidator::numeric(), + 'error' => ERRORS::INVALID_PAGE + ] + ] ]; } public function handler() { $user = Controller::getLoggedUser(); $closed = Controller::request('closed'); + $page = Controller::request('page'); + $offset = ($page-1)*10; + if ($closed) { - Response::respondSuccess($user->sharedTicketList->toArray()); + $tickets = $user->withCondition(' TRUE LIMIT 10 OFFSET ?', [$offset])->sharedTicketList->toArray(true); + $countTotal = $user->countShared('ticket'); } else { - Response::respondSuccess($user->withCondition('closed = ?', ['0'])->sharedTicketList->toArray()); + $tickets = $user->withCondition(' closed = ? LIMIT 10 OFFSET ?', ['0', $offset])->sharedTicketList->toArray(true); + $countTotal = $user->withCondition(' closed = ?', ['0'])->countShared('ticket'); } + + Response::respondSuccess([ + 'tickets' => $tickets, + 'page' => $page, + 'pages' => ceil($countTotal / 10) + ]); } } diff --git a/server/libs/DataStoreList.php b/server/libs/DataStoreList.php index da995595..6c666931 100755 --- a/server/libs/DataStoreList.php +++ b/server/libs/DataStoreList.php @@ -3,14 +3,14 @@ require_once 'models/DataStore.php'; class DataStoreList implements IteratorAggregate { private $list = []; - + public static function getList($type, $beanList) { $dataStoreList = new DataStoreList(); - + foreach ($beanList as $bean) { $dataStoreList->add(new $type($bean)); } - + return $dataStoreList; } @@ -51,21 +51,21 @@ class DataStoreList implements IteratorAggregate { public function toBeanList() { $beanList = []; - + foreach($this->list as $item) { $item->updateBeanProperties(); $beanList[] = $item->getBeanInstance(); } - + return $beanList; } - - public function toArray() { + + public function toArray($minimized = false) { $array = []; foreach($this->list as $item) { $item->updateBeanProperties(); - $array[] = $item->toArray(); + $array[] = $item->toArray($minimized); } return $array; @@ -80,4 +80,4 @@ class DataStoreList implements IteratorAggregate { return -1; } -} \ No newline at end of file +} diff --git a/server/models/DataStore.php b/server/models/DataStore.php index d4310fdc..b13f7294 100755 --- a/server/models/DataStore.php +++ b/server/models/DataStore.php @@ -33,13 +33,13 @@ abstract class DataStore { } public static function find($query = '', $matches = []) { $beanList = RedBean::find(static::TABLE, $query, $matches); - + return DataStoreList::getList(ucfirst(static::TABLE), $beanList); } - + public static function findOne($query = '', $matches = []) { $bean = RedBean::findOne(static::TABLE, $query, $matches); - + return ($bean) ? new static($bean) : new NullDataStore(); } @@ -151,7 +151,11 @@ abstract class DataStore { } public function withCondition($condition, $values) { - return new static($this->_bean->withCondition($condition, $values)); + return new static($this->_bean->withCondition($condition, $values)); + } + + public function countShared($shared) { + return $this->_bean->countShared($shared); } private function updateBeanProp($key, $value) { diff --git a/tests/staff/get-new-tickets.rb b/tests/staff/get-new-tickets.rb index 7561aa1b..bb3a94da 100644 --- a/tests/staff/get-new-tickets.rb +++ b/tests/staff/get-new-tickets.rb @@ -2,13 +2,14 @@ describe '/staff/get-new-tickets' do request('/user/logout') Scripts.login($staff[:email], $staff[:password], true) - it 'should get news tickets' do + it 'should get new tickets' do result = request('/staff/get-new-tickets', { + page: 1, csrf_userid: $csrf_userid, csrf_token: $csrf_token }) (result['status']).should.equal('success') - (result['data'].size).should.equal(9) + (result['data']['tickets'].size).should.equal(8) end end diff --git a/tests/staff/get-tickets.rb b/tests/staff/get-tickets.rb index af0bce51..7e7e9642 100644 --- a/tests/staff/get-tickets.rb +++ b/tests/staff/get-tickets.rb @@ -7,21 +7,24 @@ describe '/staff/get-tickets' do ticket = $database.getRow('ticket', 1 , 'id') request('/staff/assign-ticket', { ticketNumber: ticket['ticket_number'], + page: 1, csrf_userid: $csrf_userid, csrf_token: $csrf_token }) ticket = $database.getRow('ticket', 2 , 'id') request('/staff/assign-ticket', { ticketNumber: ticket['ticket_number'], + page: 1, csrf_userid: $csrf_userid, csrf_token: $csrf_token }) result = request('/staff/get-tickets', { + page: 1, csrf_userid: $csrf_userid, csrf_token: $csrf_token }) (result['status']).should.equal('success') - (result['data'].size).should.equal(5) + (result['data']['tickets'].size).should.equal(5) end end From a756ac72105dd4cb1a73bf3a07b07865e10399ae Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Fri, 16 Nov 2018 15:12:15 -0300 Subject: [PATCH 08/10] Remove LCG from file uploading --- .../settings/admin-panel-system-preferences.js | 2 +- client/src/data/languages/br.js | 2 +- client/src/data/languages/cn.js | 2 +- client/src/data/languages/de.js | 2 +- client/src/data/languages/en.js | 2 +- client/src/data/languages/es.js | 2 +- client/src/data/languages/fr.js | 2 +- client/src/data/languages/gr.js | 2 +- client/src/data/languages/in.js | 2 +- client/src/data/languages/it.js | 2 +- client/src/data/languages/jp.js | 2 +- client/src/data/languages/nl.js | 2 +- client/src/data/languages/pt.js | 2 +- client/src/data/languages/ru.js | 2 +- client/src/data/languages/tr.js | 2 +- server/controllers/staff/get-all-tickets.php | 2 +- server/controllers/system/init-settings.php | 3 --- server/libs/Controller.php | 12 ------------ server/libs/FileUploader.php | 18 +++--------------- 19 files changed, 19 insertions(+), 46 deletions(-) diff --git a/client/src/app/admin/panel/settings/admin-panel-system-preferences.js b/client/src/app/admin/panel/settings/admin-panel-system-preferences.js index 825fc06f..14d4ad84 100644 --- a/client/src/app/admin/panel/settings/admin-panel-system-preferences.js +++ b/client/src/app/admin/panel/settings/admin-panel-system-preferences.js @@ -112,7 +112,7 @@ class AdminPanelSystemPreferences extends React.Component {
- {i18n('MAX_SIZE_KB')} + {i18n('MAX_SIZE_MB')}
diff --git a/client/src/data/languages/br.js b/client/src/data/languages/br.js index f3a89d5b..4d77900a 100644 --- a/client/src/data/languages/br.js +++ b/client/src/data/languages/br.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Chave Pública do Recaptcha', 'RECAPTCHA_PRIVATE_KEY': 'Private Key do Recaptcha', 'ALLOW_FILE_ATTACHMENTS': 'Permitir anexar arquivos', - 'MAX_SIZE_KB': 'Tamanho máximo (KB)', + 'MAX_SIZE_MB': 'Tamanho máximo (MB)', 'UPDATE_SETTINGS': 'Atualizar configurações', 'DEFAULT_LANGUAGE': 'Idioma padrão', 'SUPPORTED_LANGUAGES': 'Idiomas suportados', diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js index 0b62cb42..c0fa15ef 100644 --- a/client/src/data/languages/cn.js +++ b/client/src/data/languages/cn.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha公鑰', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha私人鑰匙', 'ALLOW_FILE_ATTACHMENTS': '允許文件附件', - 'MAX_SIZE_KB': '最大尺寸(KB)', + 'MAX_SIZE_MB': '最大尺寸(KB)', 'UPDATE_SETTINGS': '更新設置', 'DEFAULT_LANGUAGE': '默認語言', 'SUPPORTED_LANGUAGES': '支持的語言', diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js index e7ec08a6..9c92e990 100644 --- a/client/src/data/languages/de.js +++ b/client/src/data/languages/de.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha - Öffentlicher Schlüssel', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha - Privater Schlüssel', 'ALLOW_FILE_ATTACHMENTS': 'Dateianlagen zulassen', - 'MAX_SIZE_KB': 'Max. Größe (KB)', + 'MAX_SIZE_MB': 'Max. Größe (MB)', 'UPDATE_SETTINGS': 'Einstellungen aktualisieren', 'DEFAULT_LANGUAGE': 'Standardsprache', 'SUPPORTED_LANGUAGES': 'Unterstützte Sprachen', diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index e5d90c44..02a11596 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Public Key', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key', 'ALLOW_FILE_ATTACHMENTS': 'Allow file attachments', - 'MAX_SIZE_KB': 'Max Size (KB)', + 'MAX_SIZE_MB': 'Max Size (MB)', 'UPDATE_SETTINGS': 'Update settings', 'DEFAULT_LANGUAGE': 'Default Language', 'SUPPORTED_LANGUAGES': 'Supported Languages', diff --git a/client/src/data/languages/es.js b/client/src/data/languages/es.js index d86b7ee5..4b9c5ef4 100644 --- a/client/src/data/languages/es.js +++ b/client/src/data/languages/es.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha clave pública', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha clave privada', 'ALLOW_FILE_ATTACHMENTS': 'Permitir archivos adjuntos', - 'MAX_SIZE_KB': 'Tamaño máximo (KB)', + 'MAX_SIZE_MB': 'Tamaño máximo (MB)', 'UPDATE_SETTINGS': 'Actualizar Configuraciones', 'DEFAULT_LANGUAGE': 'Idioma predeterminado', 'SUPPORTED_LANGUAGES': 'Idiomas Soportados', diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js index eb71b3ef..a6eb93f5 100644 --- a/client/src/data/languages/fr.js +++ b/client/src/data/languages/fr.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Clé publique Recaptcha', 'RECAPTCHA_PRIVATE_KEY': 'Clé privée Recaptcha', 'ALLOW_FILE_ATTACHMENTS': 'Autoriser les pièces jointes', - 'MAX_SIZE_KB': 'Taille Maximale (Ko)', + 'MAX_SIZE_MB': 'Taille Maximale (Ko)', 'UPDATE_SETTINGS': 'Mettre à jour les paramètres', 'DEFAULT_LANGUAGE': 'Langue par défaut', 'SUPPORTED_LANGUAGES': 'Langues prises en charges', diff --git a/client/src/data/languages/gr.js b/client/src/data/languages/gr.js index 0cf8a74c..eaf61c54 100644 --- a/client/src/data/languages/gr.js +++ b/client/src/data/languages/gr.js @@ -145,7 +145,7 @@ 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Δημοσίου Κλειδιού', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Ιδιωτικού Κλειδιού', 'ALLOW_FILE_ATTACHMENTS': 'Επιτρέπονται Συνημμένα Αρχεία', - 'MAX_SIZE_KB': 'Μέγιστο Μέγεθος (KB)', + 'MAX_SIZE_MB': 'Μέγιστο Μέγεθος (MB)', 'UPDATE_SETTINGS': 'Ενημέρωση Ρυθμίσεων', 'DEFAULT_LANGUAGE': 'Προεπιλεγμένες Γλώσσες', 'SUPPORTED_LANGUAGES': 'Υποστηριζόμενες Γλώσσες', diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js index b5957e12..25da03ee 100644 --- a/client/src/data/languages/in.js +++ b/client/src/data/languages/in.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha सार्वजनिक कुंजी', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha निजी कुंजी', 'ALLOW_FILE_ATTACHMENTS': 'फ़ाइल अनुलग्नकों की अनुमति दें', - 'MAX_SIZE_KB': 'अधिकतम आकार (KB)', + 'MAX_SIZE_MB': 'अधिकतम आकार (MB)', 'UPDATE_SETTINGS': 'सेटिंग अपडेट करें', 'DEFAULT_LANGUAGE': 'डिफ़ॉल्ट भाषा', 'SUPPORTED_LANGUAGES': 'समर्थित भाषाएँ', diff --git a/client/src/data/languages/it.js b/client/src/data/languages/it.js index ecf97745..c7ca1d7e 100644 --- a/client/src/data/languages/it.js +++ b/client/src/data/languages/it.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Public Key', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key', 'ALLOW_FILE_ATTACHMENTS': 'Consenti di allegare file', - 'MAX_SIZE_KB': 'Dimensione massima (KB)', + 'MAX_SIZE_MB': 'Dimensione massima (MB)', 'UPDATE_SETTINGS': 'Aggiorna modifiche', 'DEFAULT_LANGUAGE': 'Lingua predefinita', 'SUPPORTED_LANGUAGES': 'Lingue supportate', diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js index 868c6606..7c9e63b3 100644 --- a/client/src/data/languages/jp.js +++ b/client/src/data/languages/jp.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha公開鍵', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha秘密鍵', 'ALLOW_FILE_ATTACHMENTS': '添付ファイルを許可する', - 'MAX_SIZE_KB': '最大サイズ(KB)', + 'MAX_SIZE_MB': '最大サイズ(KB)', 'UPDATE_SETTINGS': '設定を更新する', 'DEFAULT_LANGUAGE': '既定の言語', 'SUPPORTED_LANGUAGES': 'サポートされている言語', diff --git a/client/src/data/languages/nl.js b/client/src/data/languages/nl.js index 37fe968a..87bff429 100644 --- a/client/src/data/languages/nl.js +++ b/client/src/data/languages/nl.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Publieke Sleutel', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Prive Sleutel', 'ALLOW_FILE_ATTACHMENTS': 'Sta bijlage(s) toe', - 'MAX_SIZE_KB': 'Max grootte (KB)', + 'MAX_SIZE_MB': 'Max grootte (MB)', 'UPDATE_SETTINGS': 'Update instellingen', 'DEFAULT_LANGUAGE': 'Standaard Taal', 'SUPPORTED_LANGUAGES': 'Talen die zijn ondersteund', diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js index 462f65fb..a4d6aeac 100644 --- a/client/src/data/languages/pt.js +++ b/client/src/data/languages/pt.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Chave Pública', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key', 'ALLOW_FILE_ATTACHMENTS': 'Permitir anexos de arquivo', - 'MAX_SIZE_KB': 'Tamanho máximo (KB)', + 'MAX_SIZE_MB': 'Tamanho máximo (MB)', 'UPDATE_SETTINGS': 'Atualizar configurações', 'DEFAULT_LANGUAGE': 'Idioma padrão', 'SUPPORTED_LANGUAGES': 'Idiomas suportados', diff --git a/client/src/data/languages/ru.js b/client/src/data/languages/ru.js index 325859b1..33331250 100644 --- a/client/src/data/languages/ru.js +++ b/client/src/data/languages/ru.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Открытый ключ', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Секретный ключ', 'ALLOW_FILE_ATTACHMENTS': 'Разрешить файловые вложения', - 'MAX_SIZE_KB': 'Максимальный размер (КБ)', + 'MAX_SIZE_MB': 'Максимальный размер (КБ)', 'UPDATE_SETTINGS': 'Обновить настройки', 'DEFAULT_LANGUAGE': 'Язык по умолчанию', 'SUPPORTED_LANGUAGES': 'Поддерживаемые Языки', diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js index c0b01802..16ea1543 100644 --- a/client/src/data/languages/tr.js +++ b/client/src/data/languages/tr.js @@ -145,7 +145,7 @@ export default { 'RECAPTCHA_PUBLIC_KEY': 'Hızlı Erişim Anahtarı', 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Özel Anahtar', 'ALLOW_FILE_ATTACHMENTS': 'Dosya eklerine izin ver', - 'MAX_SIZE_KB': 'Maksimum Boyut (KB)', + 'MAX_SIZE_MB': 'Maksimum Boyut (MB)', 'UPDATE_SETTINGS': 'Ayarları güncelle', 'DEFAULT_LANGUAGE': 'Varsayılan dil', 'SUPPORTED_LANGUAGES': 'Desteklenen Diller', diff --git a/server/controllers/staff/get-all-tickets.php b/server/controllers/staff/get-all-tickets.php index 17b6be71..da6dda2b 100755 --- a/server/controllers/staff/get-all-tickets.php +++ b/server/controllers/staff/get-all-tickets.php @@ -31,7 +31,7 @@ class GetAllTicketsStaffController extends Controller { const METHOD = 'POST'; public function validations() { - return[ + return [ 'permission' => 'staff_1', 'requestData' => [ 'page' => [ diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php index 831e3751..a0d468cb 100755 --- a/server/controllers/system/init-settings.php +++ b/server/controllers/system/init-settings.php @@ -85,9 +85,6 @@ class InitSettingsController extends Controller { 'last-stat-day' => date('YmdHi', strtotime(' -12 day ')), 'ticket-gap' => Hashing::generateRandomPrime(100000, 999999), 'ticket-first-number' => Hashing::generateRandomNumber(100000, 999999), - 'file-gap' => Hashing::generateRandomPrime(100000, 999999), - 'file-first-number' => Hashing::generateRandomNumber(100000, 999999), - 'file-quantity' => 0, 'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_', 'mail-template-header-image' => 'http://opensupports.com/logo.png' ]); diff --git a/server/libs/Controller.php b/server/libs/Controller.php index 246e3e6f..661356af 100755 --- a/server/libs/Controller.php +++ b/server/libs/Controller.php @@ -103,9 +103,6 @@ abstract class Controller { if(!$totalImages) return []; $maxSize = Setting::getSetting('max-size')->getValue(); - $fileGap = Setting::getSetting('file-gap')->getValue(); - $fileFirst = Setting::getSetting('file-first-number')->getValue(); - $fileQuantity = Setting::getSetting('file-quantity'); $fileUploader = FileUploader::getInstance(); $fileUploader->setMaxSize($maxSize); @@ -121,13 +118,10 @@ abstract class Controller { $imagePaths = []; $url = Setting::getSetting('url')->getValue(); for($i=0;$i<$totalImages;$i++) { - $fileUploader->setGeneratorValues($fileGap, $fileFirst, $fileQuantity->getValue()); $fileUploader->upload("image_$i"); $imagePaths[] = $url . '/api/system/download?file=' . $fileUploader->getFileName(); - $fileQuantity->value++; } - $fileQuantity->store(); return $imagePaths; } @@ -138,17 +132,11 @@ abstract class Controller { if(!isset($_FILES['file'])) return ''; $maxSize = Setting::getSetting('max-size')->getValue(); - $fileGap = Setting::getSetting('file-gap')->getValue(); - $fileFirst = Setting::getSetting('file-first-number')->getValue(); - $fileQuantity = Setting::getSetting('file-quantity'); $fileUploader = FileUploader::getInstance(); $fileUploader->setMaxSize($maxSize); - $fileUploader->setGeneratorValues($fileGap, $fileFirst, $fileQuantity->getValue()); if($fileUploader->upload('file')) { - $fileQuantity->value++; - $fileQuantity->store(); return $fileUploader; } else { diff --git a/server/libs/FileUploader.php b/server/libs/FileUploader.php index c2eb6417..4a9442a0 100755 --- a/server/libs/FileUploader.php +++ b/server/libs/FileUploader.php @@ -2,8 +2,6 @@ class FileUploader extends FileManager { private $maxSize = 1; - private $linearCongruentialGenerator; - private $linearCongruentialGeneratorOffset; private $fileName; private $permission; private $storage; @@ -71,12 +69,10 @@ class FileUploader extends FileManager { $newName = preg_replace('/[^a-zA-Z0-9\d\.\-]/', '_', $newName); $result = ""; - if ($this->linearCongruentialGenerator instanceof LinearCongruentialGenerator) { - if($this->permission) $result = $this->permission . '_'; - else $result = ''; + if($this->permission) $result = $this->permission . '_'; + else $result = ''; - $result .= $this->linearCongruentialGenerator->generate($this->linearCongruentialGeneratorOffset) . '_' . $newName; - } + $result .= substr(Hashing::generateRandomToken(), 0, 6) . '_' . $newName; return $result; } @@ -92,14 +88,6 @@ class FileUploader extends FileManager { else $this->permission = ''; } - public function setGeneratorValues($gap, $first, $offset) { - $this->linearCongruentialGenerator = new LinearCongruentialGenerator(); - $this->linearCongruentialGeneratorOffset = $offset; - - $this->linearCongruentialGenerator->setGap($gap); - $this->linearCongruentialGenerator->setFirst($first); - } - public function setMaxSize($maxSize) { $this->maxSize = $maxSize; } From 85eced56ffd2f4c25b0cceeedd7d692f65bc294d Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Fri, 16 Nov 2018 17:24:43 -0300 Subject: [PATCH 09/10] Fix mailtemplate tests --- server/tests/libs/HashingTest.php | 3 +-- server/tests/models/MailTemplateTest.php | 28 +++++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/server/tests/libs/HashingTest.php b/server/tests/libs/HashingTest.php index 966be913..4d8de399 100644 --- a/server/tests/libs/HashingTest.php +++ b/server/tests/libs/HashingTest.php @@ -51,7 +51,7 @@ class HashingTest extends TestCase { foreach($nonPrimes as $number) $this->assertFalse(Hashing::isPrime($number)); } - public function testShouldGenerateRandsomPrime() { + public function testShouldGenerateRandomPrime() { $TEST_TIMES = 10; for ($i = 0; $i < $TEST_TIMES; $i++) { @@ -63,7 +63,6 @@ class HashingTest extends TestCase { $this->assertTrue($min < $number1 && $number1 < $max); $this->assertTrue($min < $number2 && $number2 < $max); - $this->assertNotEquals($number1, $number2); $this->assertTrue(Hashing::isPrime($number1)); $this->assertTrue(Hashing::isPrime($number2)); } diff --git a/server/tests/models/MailTemplateTest.php b/server/tests/models/MailTemplateTest.php index 8c0ea0a3..b68fbf7b 100755 --- a/server/tests/models/MailTemplateTest.php +++ b/server/tests/models/MailTemplateTest.php @@ -19,11 +19,11 @@ class MailTemplateTest extends TestCase { } public function testGetTemplateShouldReturnSpecifiedTemplate() { - $mailTemplate = MailTemplate::getTemplate(MailTemplate::USER_SIGNUP); + $mailTemplate = MailTemplate::getMailTemplate(MailTemplate::USER_SIGNUP); - $this->assertEquals('TEST_TYPE', $mailTemplate->type); - $this->assertTrue(Redbean::get('findOne')->hasBeenCalledWithArgs('mailtemplate', 'type = :type AND language = :language', array( - ':type' => 'USER_SIGNUP', + $this->assertEquals('USER_SIGNUP', $mailTemplate->type); + $this->assertTrue(Redbean::get('findOne')->hasBeenCalledWithArgs('mailtemplate', 'template = :template AND language = :language', array( + ':template' => 'USER_SIGNUP', ':language' => 'MOCK_SETTING_VALUE' ))); } @@ -31,23 +31,31 @@ class MailTemplateTest extends TestCase { public function testCompilation() { $mailTemplate = new MailTemplate(); $mailTemplate->setProperties([ + 'template' => 'USER_SIGNUP', 'subject' => 'Welcoming to {{to}}', - 'body' => 'Welcome, {{userName}} to our team' + 'text1' => 'Welcome, {{userName}} to our team' ]); - $result = $mailTemplate->compile([ + $resultSubject = $mailTemplate->getSubject([ 'to' => 'cersei@opensupports.com', 'userName' => 'Cersei Lannister', ]); - $this->assertEquals($result['subject'], 'Welcoming to cersei@opensupports.com'); - $this->assertEquals($result['body'], 'Welcome, Cersei Lannister to our team'); + $resultBody = $mailTemplate->getBody([ + 'to' => 'cersei@opensupports.com', + 'userName' => 'Cersei Lannister', + ]); + + $this->assertEquals($resultSubject, 'Welcoming to cersei@opensupports.com'); + $this->assertContains('Welcome, Cersei Lannister to our team', $resultBody); } private function getMockTemplateBean() { $mailTemplateBean = new BeanMock(); - $mailTemplateBean->type = 'TEST_TYPE'; - $mailTemplateBean->body = 'Some body'; + $mailTemplateBean->type = 'USER_SIGNUP'; + $mailTemplateBean->text1 = 'Text1'; + $mailTemplateBean->text2 = 'Text1'; + $mailTemplateBean->text3 = 'Text1'; $mailTemplateBean->subject = 'Some subject'; $mailTemplateBean->language = 'en'; From 048d18e3cbddc574a7a870244328061f88d325cd Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Fri, 16 Nov 2018 17:44:44 -0300 Subject: [PATCH 10/10] Add php7.2 to travis ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2cd3045f..33223a61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ php: - '5.6' - '7.0' - '7.1' + - '7.2' services: - mysql