diff --git a/packages/components/AWSSES-server/CHANGELOG.md b/packages/components/AWSSES-server/CHANGELOG.md deleted file mode 100644 index 243bf657cd40b558e81d62308c38ea260b752306..0000000000000000000000000000000000000000 --- a/packages/components/AWSSES-server/CHANGELOG.md +++ /dev/null @@ -1,16 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -<a name="0.1.0"></a> - -# 0.1.0 (2018-02-16) - -### Bug Fixes - -* **component:** fix tests ([bf9d13e](https://gitlab.coko.foundation/pubsweet/pubsweet/commit/bf9d13e)) - -### Features - -* **component:** add aws ses package ([2e34627](https://gitlab.coko.foundation/pubsweet/pubsweet/commit/2e34627)) diff --git a/packages/components/AWSSES-server/.gitignore b/packages/components/EmailTemplating-server/.gitignore similarity index 100% rename from packages/components/AWSSES-server/.gitignore rename to packages/components/EmailTemplating-server/.gitignore diff --git a/packages/components/EmailTemplating-server/README.md b/packages/components/EmailTemplating-server/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0ac4ef287bf0b66250343e6d8b86a1483e121f32 --- /dev/null +++ b/packages/components/EmailTemplating-server/README.md @@ -0,0 +1,100 @@ +# Email Templating + +## About + +The `email-templating` component contains an `EmailTemplate` class with one main instance method `sendEmail` for sending the email using the `send-email` component from PubSweet. + +1. `sendEmail()`: + * uses the `send-email` component from PubSweet to actually send the email based on the Email properties passed in the constructor + +The `Email` class also provides a `constructor` whose properties will be used when sending the email: + +1. `type`: a String that can be either `user` or `system` which can be used in the unsubscribe process +2. `fromEmail`: a String indicating the from name and from email address: `Coko <team@coko.foundation>` +3. `toUser`: an Object with two properties: `email` and `name`. The `name` property will be used when addressing the recipient in the email content - for example: "Dear Dr. Rachel Smith". +4. `content`: an Object which contains properties about the email: + * `subject` + * `paragraph`: the main text part of the email body which informs the recipient + * `signatureName` - the name which will appear in the signature + * `ctaLink` - the URL which will be placed in the button + * `ctaText` - the text which appears on the button + * `unsubscribeLink` + * `signatureJournal` - the journal or company name which will appear in the signature +5. `bodyProps`: + * `hasLink`: a boolean which indicates if the email body contains a CTA (big button) or not + * `hasIntro`: a boolean which indicates if the email body contains the "Dear Dr. John" introduction or not. + * `hasSignature`: a boolean which indicates if the email body contains a typical "Kind regards," signature or not + +## Usage + +1. **Config** + + In order to use this component, you need the to add the following data in your main config file: + + ```javascript + journal: { + name: 'Coko Foundation', + staffEmail: 'Coko <team@coko.foundation>', + logo: 'https://coko.foundation/wp-content/uploads/2017/11/logo-coko.png', + ctaColor: '#EE2B77', // the color of the email button + logoLink: 'https://coko.foundation/', + publisher: 'Coko Foundation', // this will appear in the email footer + privacy: '', // a text containing information about the privacy policy that will appear in the email footer + address: '2973 16th St., Suite 300, San Francisco, CA 94103', // the address in the footer + }, + ``` + +1. **Dependencies** + + * [Pubsweet's Send Email](https://www.npmjs.com/package/@pubsweet/component-send-email) + * [Configure your Node.js Applications](https://www.npmjs.com/package/config) + * [Handlebars.js](https://www.npmjs.com/package/handlebars) + +1. **Notifications** + + These are the most basic emails, which contain at least a piece of text, called a paragraph, and may or may not contain an intro, an action button and a signature. + +  + + ```javascript + const EmailTemplate = require('@pubsweet/component-email-template') + const config = require('config') + + const { name: journalName, fromEmail: staffEmail } = config.get('journal') + + const paragraph = `We are please to inform you that the manuscript has passed the technical check process and is now submitted. Please click the link below to access the manuscript.` + + const sendNotifications = ({ user, editor, collection, fragment }) => { + const email = new EmailTemplate({ + type: 'user', + fromEmail, + toUser: { + email: user.email, + name: `${user.lastName}`, + }, + content: { + ctaText: 'MANUSCRIPT DETAILS', + signatureJournal: journalName, + signatureName: `${editor.name}`, + subject: `${collection.customId}: Manuscript Update`, + paragraph, + unsubscribeLink: `http://localhost:3000/unsubscribe/${user.id}`, + ctaLink: `http://localhost:3000/projects/${collection.id}/versions/${ + fragment.id + }/details`, + }, + bodyProps: { + hasLink: true, + hasIntro: true, + hasSignature: true, + }, + }) + + return email.sendEmail() + } + ``` + +1. **Reviewer Invitation** + This email template is specific to Hindawi and it requires some data that might not be available in other PubSweet apps. + +  diff --git a/packages/components/EmailTemplating-server/index.js b/packages/components/EmailTemplating-server/index.js new file mode 100644 index 0000000000000000000000000000000000000000..3ad0f7ec71eff16f2a757a9bafaf150d0246aa44 --- /dev/null +++ b/packages/components/EmailTemplating-server/index.js @@ -0,0 +1 @@ +module.exports = require('./src/EmailTemplate') diff --git a/packages/components/EmailTemplating-server/package.json b/packages/components/EmailTemplating-server/package.json new file mode 100644 index 0000000000000000000000000000000000000000..58b04d9b843130a82bb72cc103bb01f301926dec --- /dev/null +++ b/packages/components/EmailTemplating-server/package.json @@ -0,0 +1,26 @@ +{ + "name": "@pubsweet/component-email-templating", + "version": "0.0.1", + "description": "Send journal emails using templates from xPub/PubSweet", + "license": "MIT", + "author": "Collaborative Knowledge Foundation", + "files": [ + "src" + ], + "main": "index.js", + "dependencies": { + "@pubsweet/component-send-email": "^0.2.4", + "handlebars": "^4.0.2" + }, + "peerDependencies": { + "@pubsweet/logger": "^0.0.1" + }, + "repository": { + "type": "git", + "url": "https://gitlab.coko.foundation/pubsweet/pubsweet", + "path": "EmailTemplating" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/components/EmailTemplating-server/src/EmailTemplate.js b/packages/components/EmailTemplating-server/src/EmailTemplate.js new file mode 100644 index 0000000000000000000000000000000000000000..d5f06c6d4dd976c39676c7832ce558aca04a4b5e --- /dev/null +++ b/packages/components/EmailTemplating-server/src/EmailTemplate.js @@ -0,0 +1,126 @@ +const config = require('config') +const htmlTemplateService = require('./HTMLTemplateService') +const SendEmail = require('@pubsweet/component-send-email') +const logger = require('@pubsweet/logger') + +const configData = { + logo: config.get('journal.logo'), + address: config.get('journal.address'), + privacy: config.get('journal.privacy'), + ctaColor: config.get('journal.ctaColor'), + logoLink: config.get('journal.logoLink'), + publisher: config.get('journal.publisher'), +} +class EmailTemplate { + constructor({ + type = 'system', + templateType = 'notification', + fromEmail = config.get('journal.staffEmail'), + toUser = { + id: '', + email: '', + name: '', + }, + content = { + subject: '', + ctaLink: '', + ctaText: '', + paragraph: '', + signatureName: '', + unsubscribeLink: '', + signatureJournal: '', + }, + bodyProps = { hasLink: false, hasIntro: false, hasSignature: false }, + }) { + this.type = type + this.toUser = toUser + this.content = content + this.bodyProps = bodyProps + this.fromEmail = fromEmail + this.templateType = templateType + } + + set _toUser(newToUser) { + this.toUser = newToUser + } + + set _subject(newSubject) { + this.subject = newSubject + } + + set _content(newContent) { + this.content = newContent + } + + _getInvitationBody() { + return { + html: htmlTemplateService.getCompiledInvitationBody({ + replacements: { + ...configData, + ...this.content, + ...this.bodyProps, + toEmail: this.toUser.email, + toUserName: this.toUser.name, + }, + }), + text: `${this.bodyProps.resend} ${this.bodyProps.upperContent} ${ + this.bodyProps.manuscriptText + } ${this.bodyProps.lowerContent} ${this.content.signatureName}`, + } + } + + _getNotificationBody() { + return { + html: htmlTemplateService.getCompiledNotificationBody({ + replacements: { + ...configData, + ...this.content, + ...this.bodyProps, + toEmail: this.toUser.email, + toUserName: this.toUser.name, + }, + }), + text: `${this.content.paragraph} ${this.content.ctaLink} ${ + this.content.ctaText + } ${this.content.signatureName}`, + } + } + + _getEmailTemplate() { + return this.templateType === 'notification' + ? this._getNotificationBody() + : this._getInvitationBody() + } + + async sendEmail() { + const { html, text } = this._getEmailTemplate() + + const { fromEmail: from } = this + const { email: to } = this.toUser + const { subject } = this.content + + const mailData = { + to, + text, + html, + from, + subject, + } + + try { + const email = await SendEmail.send(mailData) + logger.info( + `Sent email from: ${from} to: ${to} with subject: "${subject}"`, + ) + logger.debug( + `Sent email from: ${from} to: ${to} with subject: "${subject}"`, + ) + return email + } catch (e) { + logger.error(e) + throw new Error(e) + } + } +} + +module.exports = EmailTemplate diff --git a/packages/components/EmailTemplating-server/src/HTMLTemplateService.js b/packages/components/EmailTemplating-server/src/HTMLTemplateService.js new file mode 100644 index 0000000000000000000000000000000000000000..6dc314521e5533c7fda4166de3726ee3c5c21980 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/HTMLTemplateService.js @@ -0,0 +1,46 @@ +const fs = require('fs') +const handlebars = require('handlebars') + +const getCompiledNotificationBody = ({ replacements }) => { + handlePartial('header', replacements) + if (replacements.hasIntro) handlePartial('intro', replacements) + handlePartial('footer', replacements) + if (replacements.hasSignature) handlePartial('signature', replacements) + if (replacements.hasLink) handlePartial('button', replacements) + handlePartial('body', replacements) + + return compileBody({ fileName: 'notification', context: replacements }) +} + +const getCompiledInvitationBody = ({ replacements }) => { + handlePartial('invHeader', replacements) + handlePartial('footer', replacements) + handlePartial('invUpperContent', replacements) + handlePartial('invButtons', replacements) + handlePartial('invManuscriptData', replacements) + handlePartial('signature', replacements) + handlePartial('invLowerContent', replacements) + + return compileBody({ fileName: 'invitation', context: replacements }) +} + +const readFile = path => fs.readFileSync(path, 'utf-8') + +const handlePartial = (partialName, context = {}) => { + let partial = readFile(`${__dirname}/templates/partials/${partialName}.hbs`) + const template = handlebars.compile(partial) + partial = template(context) + handlebars.registerPartial(partialName, partial) +} + +const compileBody = ({ fileName, context }) => { + const htmlFile = readFile(`${__dirname}/templates/${fileName}.html`) + const htmlTemplate = handlebars.compile(htmlFile) + const htmlBody = htmlTemplate(context) + return htmlBody +} + +module.exports = { + getCompiledNotificationBody, + getCompiledInvitationBody, +} diff --git a/packages/components/EmailTemplating-server/src/templates/invitation.html b/packages/components/EmailTemplating-server/src/templates/invitation.html new file mode 100644 index 0000000000000000000000000000000000000000..f9d5ed18cfa96454ba3454e9555e6144a6411467 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/invitation.html @@ -0,0 +1,5 @@ +{{> invHeader }} +{{> invUpperContent }} +{{> invButtons }} +{{> invLowerContent }} +{{> footer }} \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/notification.html b/packages/components/EmailTemplating-server/src/templates/notification.html new file mode 100644 index 0000000000000000000000000000000000000000..02cbf2a6e9c1b383534faf9358c0df3cd078c534 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/notification.html @@ -0,0 +1,3 @@ +{{> header }} +{{> body }} +{{> footer}} \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/body.hbs b/packages/components/EmailTemplating-server/src/templates/partials/body.hbs new file mode 100644 index 0000000000000000000000000000000000000000..59e1230635ab84764ca255052c0952cebf6df56e --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/body.hbs @@ -0,0 +1,25 @@ +<table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="padding:30px 23px 0px 23px;background-color:#ffffff;" height="100%" valign="top" bgcolor="#ffffff"> + <div> + {{#if hasIntro}} + {{> intro}} + {{/if}} + <p> </p> + <p> + {{{paragraph}}} + </p> + <p> </p> + <p> + {{#if hasLink }} + {{> button }} + {{/if}} + </p> + {{#if hasSignature }} + {{> signature}} + {{/if}} + <p> </p> + </div> + </td> + </tr> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/button.hbs b/packages/components/EmailTemplating-server/src/templates/partials/button.hbs new file mode 100644 index 0000000000000000000000000000000000000000..95f80f2895743c1cab4eb954ffd64f22b21162f8 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/button.hbs @@ -0,0 +1,19 @@ +<table border="0" cellPadding="0" cellSpacing="0" class="module" data-role="module-button" data-type="button" role="module" + style="table-layout:fixed" width="100%"> + <tbody> + <tr> + <td align="center" bgcolor="#FFFFFF" class="outer-td" style="padding:0px 0px 30px 0px;background-color:#FFFFFF"> + <table border="0" cellPadding="0" cellSpacing="0" class="button-css__deep-table___2OZyb wrapper-mobile" style="text-align:center"> + <tbody> + <tr> + <td align="center" bgcolor="{{ctaColor}}" class="inner-td" style="border-radius:6px;font-size:16px;text-align:center;background-color:inherit"> + <a href="{{ ctaLink }}" style="background-color:{{ctaColor}};border:1px solid #333333;border-color:{{ctaColor}};border-radius:0px;border-width:1px;color:#ffffff;display:inline-block;font-family:arial,helvetica,sans-serif;font-size:16px;font-weight:normal;letter-spacing:0px;line-height:16px;padding:12px 18px 12px 18px;text-align:center;text-decoration:none" + target="_blank">{{ ctaText }}</a> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/footer.hbs b/packages/components/EmailTemplating-server/src/templates/partials/footer.hbs new file mode 100644 index 0000000000000000000000000000000000000000..13045bee06e111036a100f7e3e200d1f0e987ea4 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/footer.hbs @@ -0,0 +1,41 @@ +<div data-role="module-unsubscribe" class="module unsubscribe-css__unsubscribe___2CDlR" role="module" data-type="unsubscribe" + style="color:#444444;font-size:12px;line-height:20px;padding:16px 16px 16px 16px;text-align:center"> + <p style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:20px;text-align:left"> + This email was sent to <span class="footer-link">{{toEmail}}</span>. You have received this email in regards to the account creation, submission, or + peer review process of a paper submitted to a journal published by {{ publisher }}. + </p> + <div class="Unsubscribe--addressLine"> + <p style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:20px;text-align:left"> + {{ address }} + </p> + </div> + <p style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:20px;text-align:left"> + </p> + <p style="font-family:Arial, Helvetica, sans-serif;font-size:11px;line-height:20px;text-align:left"> + {{{ privacy }}} + </p> + <p style="font-family:Arial, Helvetica, sans-serif;font-size:12px;line-height:20px"> + <a class="Unsubscribe--unsubscribeLink" href="{{ unsubscribeLink }}">Unsubscribe</a> + </p> +</div> +</td> +</tr> +</table> +<!--[if mso]> + </td></tr></table> + </center> + <![endif]--> +</td> +</tr> +</table> +</td> +</tr> +</table> +</td> +</tr> +</table> +</div> +</center> +</body> + +</html> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/header.hbs b/packages/components/EmailTemplating-server/src/templates/partials/header.hbs new file mode 100644 index 0000000000000000000000000000000000000000..fbc2385fbfc28e37ac235a5a335a5fb3bf06d924 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/header.hbs @@ -0,0 +1,163 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" /> + <!--[if !mso]><!--> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <!--<![endif]--> + <!--[if (gte mso 9)|(IE)]> + <xml> + <o:OfficeDocumentSettings> + <o:AllowPNG/> + <o:PixelsPerInch>96</o:PixelsPerInch> + </o:OfficeDocumentSettings> + </xml> + <![endif]--> + <!--[if (gte mso 9)|(IE)]> + <style type="text/css"> + body {width: 600px;margin: 0 auto;} + table {border-collapse: collapse;} + table, td {mso-table-lspace: 0pt;mso-table-rspace: 0pt;} + img {-ms-interpolation-mode: bicubic;} + </style> + <![endif]--> + + <style type="text/css"> + body, + p, + div { + font-family: helvetica, arial, sans-serif; + font-size: 14px; + } + + body { + color: #626262; + } + + body a { + color: #0D78F2; + text-decoration: none; + } + + p { + margin: 0; + padding: 0; + } + + table.wrapper { + width: 100% !important; + table-layout: fixed; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + } + + img.max-width { + max-width: 100% !important; + } + + .column.of-2 { + width: 50%; + } + + .column.of-3 { + width: 33.333%; + } + + .column.of-4 { + width: 25%; + } + + @media screen and (max-width:480px) { + .preheader .rightColumnContent, + .footer .rightColumnContent { + text-align: left !important; + } + .preheader .rightColumnContent div, + .preheader .rightColumnContent span, + .footer .rightColumnContent div, + .footer .rightColumnContent span { + text-align: left !important; + } + .preheader .rightColumnContent, + .preheader .leftColumnContent { + font-size: 80% !important; + padding: 5px 0; + } + table.wrapper-mobile { + width: 100% !important; + table-layout: fixed; + } + img.max-width { + height: auto !important; + max-width: 480px !important; + } + a.bulletproof-button { + display: block !important; + width: auto !important; + font-size: 80%; + padding-left: 0 !important; + padding-right: 0 !important; + } + .columns { + width: 100% !important; + } + .column { + display: block !important; + width: 100% !important; + padding-left: 0 !important; + padding-right: 0 !important; + margin-left: 0 !important; + margin-right: 0 !important; + } + } + </style> + <!--user entered Head Start--> + + <!--End Head user entered--> +</head> + +<body> + <center class="wrapper" data-link-color="#0D78F2" data-body-style="font-size: 14px; font-family: helvetica,arial,sans-serif; color: #626262; background-color: #F4F4F4;"> + <div class="webkit"> + <table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#F4F4F4"> + <tr> + <td valign="top" bgcolor="#F4F4F4" width="100%"> + <table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td width="100%"> + <table width="100%" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td> + <!--[if mso]> + <center> + <table><tr><td width="600"> + <![endif]--> + <table width="100%" cellpadding="0" cellspacing="0" border="0" style="width: 100%; max-width:600px;" align="center"> + <tr> + <td role="modules-container" style="padding: 0px 0px 0px 0px; color: #626262; text-align: left;" bgcolor="#F4F4F4" width="100%" + align="left"> + + <table class="module preheader preheader-hide" role="module" data-type="preheader" border="0" cellpadding="0" cellspacing="0" + width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;"> + <tr> + <td role="module-content"> + <p>you have a new notification</p> + </td> + </tr> + </table> + + <table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="font-size:6px;line-height:10px;padding:20px 0px 20px 0px;" valign="top" align="center"> + <a href="{{ logoLink }}"> + <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:10% !important;width:10%;height:auto !important;" + src="{{ logo }}" + alt="" width="60"> + </a> + </td> + </tr> + </table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/intro.hbs b/packages/components/EmailTemplating-server/src/templates/partials/intro.hbs new file mode 100644 index 0000000000000000000000000000000000000000..0ce780b6d9e09ac62aecd9ec48ef287f92184e30 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/intro.hbs @@ -0,0 +1 @@ +<p data-pm-slice="1 1 []">Dear Dr. {{toUserName}},</p> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/invButtons.hbs b/packages/components/EmailTemplating-server/src/templates/partials/invButtons.hbs new file mode 100644 index 0000000000000000000000000000000000000000..8deceffee7a2080bd626f746fc7959d815da5a67 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/invButtons.hbs @@ -0,0 +1,102 @@ +<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" role="module" data-type="columns" + data-version="2" style="padding:0px 0px 0px 0px;box-sizing:border-box;" bgcolor=""> + <tr role='module-content'> + <td height="100%" valign="top"> + <!--[if (gte mso 9)|(IE)]> + <center> + <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-spacing:0;border-collapse:collapse;table-layout: fixed;" > + <tr> + <![endif]--> + + <!--[if (gte mso 9)|(IE)]> + <td width="300.000px" valign="top" style="padding: 0px 0px 0px 0px;border-collapse: collapse;" > + <![endif]--> + + <table width="300.000" style="width:'50%';border-spacing:0;border-collapse:collapse;margin:0px 0px 0px 0px;" + cellpadding="0" cellspacing="0" align="left" border="0" bgcolor="" class="column column-0 of-2 + empty"> + <tr> + <td style="padding:0px;margin:0px;border-spacing:0;"> + <table border="0" cellPadding="0" cellSpacing="0" class="module" data-role="module-button" data-type="button" + role="module" style="table-layout:fixed" width="100%"> + <tbody> + <tr> + <td align="center" class="outer-td padding-decline"> + <table border="0" cellPadding="0" cellSpacing="0" class="button-css__deep-table___2OZyb wrapper-mobile" + style="text-align:center"> + <tbody> + <tr> + <td align="center" bgcolor="#f6f6f6" class="inner-td" style="border-radius:6px;font-size:16px;text-align:center;background-color:inherit"><a + style="background-color:#f6f6f6;border:1px solid #333333;border-color:#586971;border-radius:5px;border-width:2px;color:#586971;display:inline-block;font-family:arial,helvetica,sans-serif;font-size:14px;font-weight:bold;letter-spacing:0px;line-height:15px;padding:12px 18px 12px 18px;text-align:center;text-decoration:none;width:172px" + href="{{ declineLink }} " target="_blank">DECLINE</a></td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </table> + + <!--[if (gte mso 9)|(IE)]> + </td> + <![endif]--> + <!--[if (gte mso 9)|(IE)]> + <td width="300.000px" valign="top" style="padding: 0px 0px 0px 0px;border-collapse: collapse;" > + <![endif]--> + + <table width="300.000" style="width:'50%';border-spacing:0;border-collapse:collapse;margin:0px 0px 0px 0px;" + cellpadding="0" cellspacing="0" align="left" border="0" bgcolor="" class="column column-1 of-2 + empty"> + <tr> + <td style="padding:0px;margin:0px;border-spacing:0;"> + <table border="0" cellPadding="0" cellSpacing="0" class="module" data-role="module-button" data-type="button" + role="module" style="table-layout:fixed" width="100%"> + <tbody> + <tr> + <td align="center" class="outer-td padding-agree"> + <table border="0" cellPadding="0" cellSpacing="0" class="button-css__deep-table___2OZyb wrapper-mobile" + style="text-align:center"> + <tbody> + <tr> + <td align="center" bgcolor="#63a945" class="inner-td" style="border-radius:6px;font-size:16px;text-align:center;background-color:inherit"><a + style="background-color:#63a945;border:1px solid #333333;border-color:#63A945;border-radius:5px;border-width:2px;color:#f6f6f6;display:inline-block;font-family:arial,helvetica,sans-serif;font-size:14px;font-weight:bold;letter-spacing:0px;line-height:15px;padding:12px 18px 12px 18px;text-align:center;text-decoration:none;width:172px" + href="{{ agreeLink }}" target="_blank">AGREE</a></td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </table> + + <!--[if (gte mso 9)|(IE)]> + </td> + <![endif]--> + <!--[if (gte mso 9)|(IE)]> + <tr> + </table> + </center> + <![endif]--> + </td> + </tr> +</table> + +<table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="padding:8px 50px 32px 50px;line-height:20px;text-align:inherit;" height="100%" valign="top" bgcolor=""> + <div> + <div> + <div> + <div style="text-align: center;" tabindex="1"><span style="font-size:12px;">{{ subText }}</span></div> + </div> + </div> + </div> + </td> + </tr> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/invHeader.hbs b/packages/components/EmailTemplating-server/src/templates/partials/invHeader.hbs new file mode 100644 index 0000000000000000000000000000000000000000..473d7b913b24bea5163c4e73aada31056acf8fe3 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/invHeader.hbs @@ -0,0 +1,186 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" /> + <!--[if !mso]><!--> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <!--<![endif]--> + <!--[if (gte mso 9)|(IE)]> + <xml> + <o:OfficeDocumentSettings> + <o:AllowPNG/> + <o:PixelsPerInch>96</o:PixelsPerInch> + </o:OfficeDocumentSettings> + </xml> + <![endif]--> + <!--[if (gte mso 9)|(IE)]> + <style type="text/css"> + body {width: 600px;margin: 0 auto;} + table {border-collapse: collapse;} + table, td {mso-table-lspace: 0pt;mso-table-rspace: 0pt;} + img {-ms-interpolation-mode: bicubic;} + </style> + <![endif]--> + + <style type="text/css"> + body, + p, + div { + font-family: helvetica, arial, sans-serif; + font-size: 14px; + } + + body { + color: #626262; + } + + body a { + color: #007e92; + text-decoration: none; + } + + p { + margin: 0; + padding: 0; + } + + table.wrapper { + width: 100% !important; + table-layout: fixed; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + } + + img.max-width { + max-width: 100% !important; + } + + .column.of-2 { + width: 50%; + } + + .column.of-3 { + width: 33.333%; + } + + .column.of-4 { + width: 25%; + } + + .footer-link a { + color: #444444; + text-decoration: none; + } + + .padding-decline { + padding:0px 0px 0px 50px; + } + + .padding-agree { + padding:0px 50px 0px 0px; + } + + @media screen and (max-width:480px) { + + .preheader .rightColumnContent, + .footer .rightColumnContent { + text-align: left !important; + } + + .preheader .rightColumnContent div, + .preheader .rightColumnContent span, + .footer .rightColumnContent div, + .footer .rightColumnContent span { + text-align: left !important; + } + + .preheader .rightColumnContent, + .preheader .leftColumnContent { + font-size: 80% !important; + padding: 5px 0; + } + + table.wrapper-mobile { + width: 100% !important; + table-layout: fixed; + } + + img.max-width { + height: auto !important; + max-width: 480px !important; + } + + a.bulletproof-button { + display: block !important; + width: auto !important; + font-size: 80%; + padding-left: 0 !important; + padding-right: 0 !important; + } + + .columns { + width: 100% !important; + } + + .column { + display: block !important; + width: 100% !important; + padding-left: 0 !important; + padding-right: 0 !important; + margin-left: 0 !important; + margin-right: 0 !important; + } + + .padding-decline { + padding: 0px; + } + + .padding-agree { + padding: 10px 0px 0px 0px; + } + } + </style> + <!--user entered Head Start--> + + <!--End Head user entered--> +</head> + +<body> + <center class="wrapper" data-link-color="#0D78F2" data-body-style="font-size: 14px; font-family: helvetica,arial,sans-serif; color: #626262; background-color: #F4F4F4;"> + <div class="webkit"> + <table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#F4F4F4"> + <tr> + <td valign="top" bgcolor="#F4F4F4" width="100%"> + <table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" + border="0"> + <tr> + <td width="100%"> + <table width="100%" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td> + <!--[if mso]> + <center> + <table><tr><td width="600"> + <![endif]--> + <table width="100%" cellpadding="0" cellspacing="0" border="0" style="width: 100%; max-width:600px;" + align="center"> + <tr> + <td role="modules-container" style="padding: 0px 0px 0px 0px; color: #626262; text-align: left;" + bgcolor="#F4F4F4" width="100%" align="left"> + + <table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" + cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="font-size:6px;line-height:10px;padding:32px 0px 24px 0px;" valign="top" + align="center"> + <a href="{{ logoLink }}"> + <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:10% !important;width:10%;height:auto !important;" + src="{{ logo }}" alt="Hindawi Logo" width="60"> + </a> + </td> + </tr> + </table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/invLowerContent.hbs b/packages/components/EmailTemplating-server/src/templates/partials/invLowerContent.hbs new file mode 100644 index 0000000000000000000000000000000000000000..285fed1eec228b0e279e265666c6e2f81d604a7b --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/invLowerContent.hbs @@ -0,0 +1,20 @@ +{{#unless resend }} +{{> invManuscriptData }} +{{/unless}} + +<table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="padding:0px 50px 0px 50px;line-height:18px;text-align:inherit;" height="100%" valign="top" bgcolor=""> + <div> + <span style="font-size:14px;"> + <span style="color:#242424;"> + {{{ lowerContent }}} + {{ lowerContentLink }} + </span> + </span> + </div> + <div> </div> + {{> signature}} + </td> + </tr> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/invManuscriptData.hbs b/packages/components/EmailTemplating-server/src/templates/partials/invManuscriptData.hbs new file mode 100644 index 0000000000000000000000000000000000000000..5df28e45b5d75ace4217faa4e43b38074ed445c0 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/invManuscriptData.hbs @@ -0,0 +1,62 @@ +<table border="0" cellpadding="0" cellspacing="0" align="center" width="100%" role="module" data-type="columns" + data-version="2" style="padding:0px 34px 17px 34px;box-sizing:border-box;" bgcolor=""> + <tr role='module-content'> + <td height="100%" valign="top"> + <!--[if (gte mso 9)|(IE)]> + <center> + <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-spacing:0;border-collapse:collapse;table-layout: fixed;" > + <tr> + <![endif]--> + + <!--[if (gte mso 9)|(IE)]> + <td width="532.000px" valign="top" style="padding: 0px 0px 0px 0px;border-collapse: collapse;" > + <![endif]--> + + <table width="532.000" style="width:532.000px;border-spacing:0;border-collapse:collapse;margin:0px 0px 0px 0px;" + cellpadding="0" cellspacing="0" align="left" border="0" bgcolor="" class="column column-0 of-1 + empty"> + <tr> + <td style="padding:0px;margin:0px;border-spacing:0;"> + + <table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" + style="table-layout: fixed;"> + <tr> + <td style="box-shadow: 0px 1px 2px 1px #dbdbdb;background-color:#ffffff;padding:16px 16px 16px 16px;line-height:20px;text-align:inherit;border-radius:3px;" + height="100%" valign="top" bgcolor="#ffffff"> + <div><span style="font-size:18px;font-weight:600;"><span style="color:#007e92;">{{ title }}</span></span></div> + + <div> </div> + + <div> + <div> + <div> + <div> + <p tabindex="1"><span style="color:#242424;"><span style="font-size:14px;">{{ authorsList }}</span></span></p> + + <p tabindex="1"> </p> + + <p tabindex="1"><span style="color:#242424;"><span style="font-size:14px;">{{ abstract }}</span></span></p> + </div> + </div> + </div> + </div> + + </td> + </tr> + </table> + + </td> + </tr> + </table> + + <!--[if (gte mso 9)|(IE)]> + </td> + <![endif]--> + <!--[if (gte mso 9)|(IE)]> + <tr> + </table> + </center> + <![endif]--> + </td> + </tr> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/invUpperContent.hbs b/packages/components/EmailTemplating-server/src/templates/partials/invUpperContent.hbs new file mode 100644 index 0000000000000000000000000000000000000000..eb2df55d33e780cd4e899d1fe18bde78db05e9be --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/invUpperContent.hbs @@ -0,0 +1,21 @@ +<table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;"> + <tr> + <td style="padding:0px 50px 32px 50px;line-height:18px;" height="100%" valign="top" bgcolor=""> + <div> + <div data-pm-slice="1 1 []"><span style="color:#242424;"><span style="font-size:14px;"> + Dear Dr. {{ toUserName}},<br> + + <div data-pm-slice="1 1 []"> </div> + + <div data-pm-slice="1 1 []"> + <span style="color:#242424;"> + <span style="font-size:14px;"> + {{{ upperContent }}} + {{{ manuscriptText }}} + </span> + </span> + </div> + </div> + </td> + </tr> +</table> \ No newline at end of file diff --git a/packages/components/EmailTemplating-server/src/templates/partials/signature.hbs b/packages/components/EmailTemplating-server/src/templates/partials/signature.hbs new file mode 100644 index 0000000000000000000000000000000000000000..4f618fdf6dec8e467624c1255a5b93c874295c48 --- /dev/null +++ b/packages/components/EmailTemplating-server/src/templates/partials/signature.hbs @@ -0,0 +1,5 @@ +<div><span style="font-size:14px;"><span style="color:#242424;">Kind regards,</span></span></div> + +<div><span style="font-size:14px;"><span style="color:#242424;">{{ signatureName }}</span></span></div> + +<div><span style="font-size:14px;"><span style="color:#242424;">{{ signatureJournal }}</span></span></div> \ No newline at end of file diff --git a/packages/components/config/default.js b/packages/components/config/default.js index c3188aeefa62becac6157bef2aef81b08d9a40f8..aa754b0eab4b1a967f85c1184ea3bca18fb71f2d 100644 --- a/packages/components/config/default.js +++ b/packages/components/config/default.js @@ -20,8 +20,19 @@ module.exports = { }, mailer: { from: 'nobody@example.com', + path: path.join(__dirname, 'mailer'), }, 'pubsweet-client': { 'login-redirect': '/testRedirect', }, + journal: { + name: 'Coko Foundation', + staffEmail: 'Coko <team@coko.foundation>', + logo: 'https://coko.foundation/wp-content/uploads/2017/11/logo-coko.png', + ctaColor: '#EE2B77', + logoLink: 'https://coko.foundation/', + publisher: 'Coko Foundation', + privacy: '', + address: '2973 16th St., Suite 300, San Francisco, CA 94103', + }, } diff --git a/yarn.lock b/yarn.lock index e244c5666c98b2bc5e375a67a8c8696f9b223978..58b72c1e892b6e1ad81c1879907a6933227746c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -419,6 +419,27 @@ mkdirp "^0.5.1" rimraf "^2.5.2" +"@pubsweet/coko-theme@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@pubsweet/coko-theme/-/coko-theme-4.1.0.tgz#c163c20f50990d0aa9bf9455418fe1f368465f9a" + integrity sha512-7tE0ERvkgxyA/ZrXHczqoCy5JGFLcpRCfdp5vwtbQfD7dVvg8kuKP5+SPV3Dw1oF6aym+eoXLdl8IRx7gCcUWA== + dependencies: + "@pubsweet/ui-toolkit" "^1.2.0" + cokourier-prime-sans "git+https://gitlab.coko.foundation/julientaq/cokourier-sans-prime.git" + styled-components "^3.2.5" + typeface-fira-sans-condensed "^0.0.54" + typeface-vollkorn "^0.0.54" + +"@pubsweet/default-theme@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@pubsweet/default-theme/-/default-theme-3.0.0.tgz#7760c88b63fba45b41ad3f6019f54dd0d06e1dfc" + integrity sha512-XEg3nWXs1807ZmxsSv4FJa0VYtWhjXWR0dmxhL2vp3FAPvc9t97Pl1vcseky5I7MN5icwNeF7wLeF2tABmuiPQ== + dependencies: + styled-components "^3.2.5" + typeface-noto-sans "^0.0.54" + typeface-noto-serif "^0.0.54" + typeface-ubuntu-mono "^0.0.54" + "@pubsweet/starter@git+https://gitlab.coko.foundation/pubsweet/pubsweet-starter.git": version "1.0.0-alpha.1" resolved "git+https://gitlab.coko.foundation/pubsweet/pubsweet-starter.git#aa768ddf88dceb1966e94acca34b3f3870d1b700" @@ -449,6 +470,40 @@ pubsweet-theme-plugin "^0.0.3" react-router-redux next +"@pubsweet/ui-toolkit@^1.1.2", "@pubsweet/ui-toolkit@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@pubsweet/ui-toolkit/-/ui-toolkit-1.2.0.tgz#5531149fa2229acc06e76e964b8a412bf503c4ce" + integrity sha512-HwnFt4eES5RopLLY7ajb//UvaCLXS29XCWOOB5cs90DkwysVZaH/GM5HB/QtClQ5tuXiR3BqfjLy2mHMA0Z+PQ== + dependencies: + color "^3.0.0" + lodash "^4.17.4" + styled-components "^3.2.5" + +"@pubsweet/ui@^8.7.0", "@pubsweet/ui@^8.8.0": + version "8.8.0" + resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.8.0.tgz#d6a845cd6d0d51c1c14956dccc11900fb87d2178" + integrity sha512-Ypr86pfeysF90upV7Ybk5vTr3uCnR0WWlfQZyXsmGn8jFyTlkHMJDNMw1XggfKxdmefyk5hkpcV4YiKklZ0+PA== + dependencies: + "@pubsweet/ui-toolkit" "^1.2.0" + babel-jest "^21.2.0" + classnames "^2.2.5" + enzyme "^3.7.0" + enzyme-adapter-react-16 "^1.1.1" + invariant "^2.2.3" + lodash "^4.17.4" + moment "^2.22.1" + prop-types "^15.5.10" + react "^16.2.0" + react-dom "^16.2.0" + react-feather "^1.0.8" + react-redux "^5.0.2" + react-router-dom "^4.2.2" + react-tag-autocomplete "^5.5.0" + recompose "^0.26.0" + redux "^3.6.0" + redux-form "^7.0.3" + styled-components "^3.2.5" + "@types/async@2.0.49": version "2.0.49" resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0" @@ -11751,6 +11806,44 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" +pubsweet-client@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pubsweet-client/-/pubsweet-client-6.1.0.tgz#79194234f591bc515bf1802689e1291c8ae8e679" + integrity sha512-on/uWQuzkuj0XbLh10ts9IbCL3+tAdFFlODqsVSKNnqB/2QxrcmKIkW2+RI3Oy9rBHCff3HVAjzhhfaHYmb8JQ== + dependencies: + "@pubsweet/ui" "^8.8.0" + "@pubsweet/ui-toolkit" "^1.2.0" + apollo-cache-inmemory "^1.2.4" + apollo-client "^2.3.4" + apollo-link "^1.2.1" + apollo-link-context "^1.0.5" + apollo-link-http "^1.5.4" + apollo-link-ws "^1.0.8" + apollo-upload-client "^8.0.0" + authsome "^0.1.0" + config "^2.0.1" + event-source-polyfill "^0.0.10" + global "^4.3.1" + graphql "^14.0.2" + graphql-tag "^2.7.3" + isomorphic-fetch "^2.1.1" + lint-staged "^6.0.0" + lodash "^4.0.0" + prop-types "^15.5.8" + react "^16.2.0" + react-apollo "^2.1.0" + react-redux "^5.0.2" + react-router-dom "^4.2.2" + react-router-redux next + redux "^3.6.0" + redux-form "^7.0.3" + redux-logger "^3.0.1" + redux-thunk "^2.2.0" + reselect "^3.0.1" + styled-components "^3.2.5" + styled-normalize "^3.0.1" + subscriptions-transport-ws "^0.9.12" + pubsweet-component-form-group@1.1.25: version "1.1.25" resolved "https://registry.yarnpkg.com/pubsweet-component-form-group/-/pubsweet-component-form-group-1.1.25.tgz#ba93e042483ce7097f799966322940d6b67f2b11" @@ -11785,6 +11878,18 @@ pubsweet-component-medium-draft@^0.2.3: react-redux "^5.0.6" redux "^3.7.2" +pubsweet-component-password-reset-frontend@^2.0.15: + version "2.0.17" + resolved "https://registry.yarnpkg.com/pubsweet-component-password-reset-frontend/-/pubsweet-component-password-reset-frontend-2.0.17.tgz#8b1d33a66ae18704e48c29e18651288dcab98e5d" + integrity sha512-3fj63ih7yQiB308CrxwQZvPtq3NmahChiAb+86XtxHXYmPIHVOGvLo1RmZuogt6bY7EnRrGBnGVmEGjm/ph2Vg== + dependencies: + "@pubsweet/ui" "^8.8.0" + "@pubsweet/ui-toolkit" "^1.2.0" + prop-types "^15.5.10" + query-string "^5.0.0" + react-router "^4.2.0" + styled-components "^3.2.5" + pubsweet-component-pepper-theme@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/pubsweet-component-pepper-theme/-/pubsweet-component-pepper-theme-0.0.5.tgz#eb39aafbab8e1a737752b6c5ed7ef057ead414cc" @@ -14189,6 +14294,11 @@ styled-components@^4.1.1: stylis-rule-sheet "^0.0.10" supports-color "^5.5.0" +styled-normalize@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/styled-normalize/-/styled-normalize-3.0.1.tgz#217efb96598690addd04699ca71af0db3473fea2" + integrity sha512-EtTwCJDKMoJ+GU0YxklkHukltPGz7Swfq/fKyeP/WEQGF01DXGVXmuo1Rp2kMTQ9kz7o6dVBvvmT+KQyKe8Okw== + styled-normalize@^8.0.4: version "8.0.4" resolved "https://registry.yarnpkg.com/styled-normalize/-/styled-normalize-8.0.4.tgz#6a0885dc16c61d88813dab8f5137da928fe0c947"