Refactored staff-service

This moves the shared data between all templates into a method so that
it's calculated in a single place, as well as exposing separate render
methods for HTML and Text. We've also added some new custom helpers
for use in the handlebars templates
This commit is contained in:
Fabien "egg" O'Carroll 2023-03-12 23:11:45 +07:00 committed by Rishabh Garg
parent 04efb6c177
commit 3cf3f633aa
2 changed files with 122 additions and 3 deletions

View File

@ -162,6 +162,23 @@ class StaffServiceEmails {
}
}
/**
* @param {object} recipient
* @param {string} recipient.email
* @param {string} recipient.slug
*/
async getSharedData(recipient) {
return {
siteTitle: this.settingsCache.get('title'),
siteUrl: this.urlUtils.getSiteUrl(),
siteDomain: this.siteDomain,
accentColor: this.settingsCache.get('accent_color'),
fromEmail: this.fromEmailAddress,
toEmail: recipient.email,
staffUrl: this.urlUtils.urlJoin(this.urlUtils.urlFor('admin', true), '#', `/settings/staff/${recipient.slug}`)
};
}
/**
*
* @param {object} eventData
@ -322,13 +339,53 @@ class StaffServiceEmails {
});
}
async renderEmailTemplate(templateName, data) {
async renderHTML(templateName, data) {
const htmlTemplateSource = await fs.readFile(path.join(__dirname, './email-templates/', `${templateName}.hbs`), 'utf8');
const htmlTemplate = this.Handlebars.compile(Buffer.from(htmlTemplateSource).toString());
this.Handlebars.registerHelper('eq', function (arg, value, options) {
if (arg === value) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
this.Handlebars.registerHelper('limit', function (array, limit) {
if (!Array.isArray(array)) {
return [];
}
return array.slice(0,limit);
});
let sharedData = {};
if (data.recipient) {
sharedData = await this.getSharedData(data.recipient);
}
return htmlTemplate({
...data,
...sharedData
});
}
async renderText(templateName, data) {
const textTemplate = require(`./email-templates/${templateName}.txt.js`);
const html = htmlTemplate(data);
const text = textTemplate(data);
let sharedData = {};
if (data.recipient) {
sharedData = await this.getSharedData(data.recipient);
}
return textTemplate({
...data,
...sharedData
});
}
async renderEmailTemplate(templateName, data) {
const html = await this.renderHTML(templateName, data);
const text = await this.renderText(templateName, data);
return {html, text};
}

View File

@ -4,6 +4,9 @@ const sinon = require('sinon');
const {MemberCreatedEvent, SubscriptionCancelledEvent, SubscriptionActivatedEvent} = require('@tryghost/member-events');
const {MilestoneCreatedEvent} = require('@tryghost/milestones');
// Stuff we are testing
const DomainEvents = require('@tryghost/domain-events');
require('./utils');
const StaffService = require('../index');
@ -191,6 +194,65 @@ describe('StaffService', function () {
subscribeStub.calledWith(MemberCreatedEvent).should.be.true();
subscribeStub.calledWith(MilestoneCreatedEvent).should.be.true();
});
it('listens to events', async function () {
service = new StaffService({
logging: {
info: loggingInfoStub,
warn: () => {},
error: () => {}
},
models: {
User: {
getEmailAlertUsers: getEmailAlertUsersStub
}
},
mailer: {
send: mailStub
},
DomainEvents,
settingsCache,
urlUtils,
settingsHelpers
});
service.subscribeEvents();
sinon.spy(service, 'handleEvent');
DomainEvents.dispatch(MemberCreatedEvent.create({
source: 'member',
memberId: 'member-2'
}));
await DomainEvents.allSettled();
service.handleEvent.calledWith(MemberCreatedEvent).should.be.true();
DomainEvents.dispatch(SubscriptionActivatedEvent.create({
source: 'member',
memberId: 'member-1',
subscriptionId: 'sub-1',
offerId: 'offer-1',
tierId: 'tier-1'
}));
await DomainEvents.allSettled();
service.handleEvent.calledWith(SubscriptionActivatedEvent).should.be.true();
DomainEvents.dispatch(SubscriptionCancelledEvent.create({
source: 'member',
memberId: 'member-1',
subscriptionId: 'sub-1',
tierId: 'tier-1'
}));
await DomainEvents.allSettled();
service.handleEvent.calledWith(SubscriptionCancelledEvent).should.be.true();
DomainEvents.dispatch(MilestoneCreatedEvent.create({
milestone: {
type: 'arr',
value: '100',
currency: 'usd'
}
}));
await DomainEvents.allSettled();
service.handleEvent.calledWith(MilestoneCreatedEvent).should.be.true();
});
});
describe('handleEvent', function () {