Skip to content

Commit

Permalink
Update emails to point to new Grant Details page (#2705)
Browse files Browse the repository at this point in the history
* Update emails to point to new grant detail page

* Set up env var in staging/prod

* Add tests

* Fix terraform fmt issues

* Update grant detail page URL

* Fix escaping of href attributes

* Fix to use correct notification type value

* Fix the tests that should've been a tipoff something was wrong to begin with...... :P
  • Loading branch information
jeffsmohan authored Mar 8, 2024
1 parent 63f508c commit f4c42fb
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 13 deletions.
15 changes: 15 additions & 0 deletions packages/server/__tests__/email/email.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,21 @@ describe('Email sender', () => {
expect(body).to.include(name);
expect(body).to.include(moment(openDate).format('MMMM Do YYYY'));
});
it('links to Grants.gov when Grant Details page is not live', async () => {
const agencies = await db.getAgency(fixtures.agencies.accountancy.id);
const agency = agencies[0];
agency.matched_grants = [fixtures.grants.healthAide];
const body = await email.buildDigestBody({ name: 'Saved search test', openDate: '2021-08-05', matchedGrants: agency.matched_grants });
expect(body).to.include(`https://www.grants.gov/search-results-detail/${fixtures.grants.healthAide.grant_id}`);
});
it('links to Grant Finder when Grant Details page is live', async () => {
process.env.NEW_GRANT_DETAILS_PAGE_ENABLED = 'true';
const agencies = await db.getAgency(fixtures.agencies.accountancy.id);
const agency = agencies[0];
agency.matched_grants = [fixtures.grants.healthAide];
const body = await email.buildDigestBody({ name: 'Saved search test', openDate: '2021-08-05', matchedGrants: agency.matched_grants });
expect(body).to.include(`${process.env.WEBSITE_DOMAIN}/grants/${fixtures.grants.healthAide.grant_id}`);
});
});
context('getAndSendGrantForSavedSearch', () => {
it('Sends an email for a saved search', async () => {
Expand Down
34 changes: 26 additions & 8 deletions packages/server/src/lib/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,17 @@ function sendWelcomeEmail(email, httpOrigin) {
});
}

function getGrantDetail(grant, emailNotificationType) {
const grantDetailTemplate = fileSystem.readFileSync(path.join(__dirname, '../static/email_templates/_grant_detail.html'));
function buildGrantDetailUrlSafe(grantId, emailNotificationType) {
const grantDetailUrl = new URL(process.env.WEBSITE_DOMAIN);
grantDetailUrl.pathname = `grants/${mustache.escape(grantId)}`;
grantDetailUrl.searchParams.set('utm_source', 'usdr-grants');
grantDetailUrl.searchParams.set('utm_medium', 'email');
grantDetailUrl.searchParams.set('utm_campaign', mustache.escape(emailNotificationType));
grantDetailUrl.searchParams.set('utm_content', 'grant-details');
return grantDetailUrl.toString();
}

const description = grant.description.substring(0, 380).replace(/(<([^>]+)>)/ig, '');
function buildGrantsUrlSafe(emailNotificationType) {
const grantsUrl = new URL(process.env.WEBSITE_DOMAIN);
if (emailNotificationType === notificationType.grantDigest) {
grantsUrl.pathname = 'grants';
Expand All @@ -164,7 +171,13 @@ function getGrantDetail(grant, emailNotificationType) {
}
grantsUrl.searchParams.set('utm_source', 'subscription');
grantsUrl.searchParams.set('utm_medium', 'email');
grantsUrl.searchParams.set('utm_campaign', emailNotificationType);
grantsUrl.searchParams.set('utm_campaign', mustache.escape(emailNotificationType));
return grantsUrl.toString();
}

function getGrantDetail(grant, emailNotificationType) {
const grantDetailTemplate = fileSystem.readFileSync(path.join(__dirname, '../static/email_templates/_grant_detail.html'));
const description = grant.description.substring(0, 380).replace(/(<([^>]+)>)/ig, '');
const grantDetail = mustache.render(
grantDetailTemplate.toString(), {
title: grant.title,
Expand All @@ -177,8 +190,13 @@ function getGrantDetail(grant, emailNotificationType) {
award_ceiling: grant.award_ceiling || 'Not available',
// estimated_funding: grant.estimated_funding, TODO: add once field is available in the database.
cost_sharing: grant.cost_sharing,
link_url: `https://www.grants.gov/search-results-detail/${grant.grant_id}`,
grants_url: grantsUrl.toString(),
link_url_safe: process.env.NEW_GRANT_DETAILS_PAGE_ENABLED === 'true'
? buildGrantDetailUrlSafe(grant.grant_id, emailNotificationType)
: `https://www.grants.gov/search-results-detail/${mustache.escape(grant.grant_id)}`,
link_description: process.env.NEW_GRANT_DETAILS_PAGE_ENABLED === 'true'
? 'Grant Finder'
: 'Grants.gov',
grants_url_safe: buildGrantsUrlSafe(emailNotificationType),
view_grant_label: emailNotificationType === notificationType.grantDigest ? undefined : 'View My Grants',
},
);
Expand Down Expand Up @@ -218,10 +236,10 @@ async function sendGrantAssignedNotficationForAgency(assignee_agency, grantDetai
// TODO: add plain text version of the email
const emailPlain = emailHTML.replace(/<[^>]+>/g, '');
const emailSubject = `Grant Assigned to ${assignee_agency.name}`;
const assginees = await db.getSubscribersForNotification(assignee_agency.id, notificationType.grantAssignment);
const assignees = await db.getSubscribersForNotification(assignee_agency.id, notificationType.grantAssignment);

const inputs = [];
assginees.forEach((assignee) => inputs.push(
assignees.forEach((assignee) => inputs.push(
{
toAddress: assignee.email,
emailHTML,
Expand Down
10 changes: 5 additions & 5 deletions packages/server/src/static/email_templates/_grant_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<tr style="border-collapse:collapse">
<td align="left"
style="Margin:0;padding-bottom:16px;">
<a style="text-decoration:none;" href="{{link_url}}">
<a style="text-decoration:none;" href="{{& link_url_safe }}">
<h2
style="Margin:0;line-height:30px;mso-line-height-rule:exactly;font-family:arial,'helvetica neue',helvetica,sans-serif;font-size:22px;font-style:normal;font-weight:normal;color:#0068D6">
{{title}}</h2>
Expand All @@ -31,7 +31,7 @@
style="Margin:0;padding-bottom:16px;">
<p
style="Margin:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;font-family:arial, 'helvetica neue', helvetica, sans-serif;line-height:24px;color:#000000;font-size:16px">
{{{description}}}<span>... View on <a style="color:#0068D6;text-decoration:none;" href="{{link_url}}">Grants.gov</a></span>
{{{description}}}<span>... View on <a style="color:#0068D6;text-decoration:none;" href="{{& link_url_safe }}">{{ link_description }}</a></span>
</p>
</td>
</tr>
Expand Down Expand Up @@ -60,16 +60,16 @@
<tr style="border-collapse:collapse">
<td align="center"
style="Margin:0;padding-left:10px;padding-right:10px;padding-top:15px;padding-bottom:25px">
<!--[if mso]><a href="{{grants_url}}" target="_blank" hidden>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" esdevVmlButton href="{{grants_url}}"
<!--[if mso]><a href="{{& grants_url_safe }}" target="_blank" hidden>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" esdevVmlButton href="{{& grants_url_safe }}"
style="height:49px; v-text-anchor:middle; width:131px" arcsize="50%" strokecolor="#75b6c9" strokeweight="1px" fillcolor="#007bff">
<w:anchorlock></w:anchorlock>
<center style='color:#ffffff; font-family:arial, "helvetica neue", helvetica, sans-serif; font-size:16px; font-weight:400; line-height:16px; mso-text-raise:1px'>{{view_grant_label}}</center>
</v:roundrect></a>
<![endif]-->
<!--[if !mso]><!-- --><span class="msohide es-button-border"
style="border-style:solid;border-color:#75B6C9;background:#007bff;border-width:1px;display:inline-block;border-radius:28px;width:auto;mso-hide:all"><a
href="{{grants_url}}" class="es-button" target="_blank"
href="{{& grants_url_safe }}" class="es-button" target="_blank"
utm-content="view my grants" style="mso-style-priority:100 !important;text-decoration:none;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;mso-line-height-rule:exactly;color:#FFFFFF;font-size:16px;border-style:solid;border-color:#007bff;border-width:15px 25px 15px 25px;display:inline-block;background:#007bff;border-radius:28px;font-family:arial, 'helvetica neue', helvetica, sans-serif;font-weight:normal;font-style:normal;line-height:19px;width:auto;text-align:center">{{view_grant_label}}</a></span>
<!--<![endif]-->
</td>
Expand Down
3 changes: 3 additions & 0 deletions terraform/prod.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ api_log_retention_in_days = 30
api_datadog_environment_variables = {
DD_PROFILING_ENABLED = true,
}
api_container_environment = {
NEW_GRANT_DETAILS_PAGE_ENABLED = false,
}

// Postgres
postgres_enabled = true
Expand Down
3 changes: 3 additions & 0 deletions terraform/staging.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ api_log_retention_in_days = 14
api_datadog_environment_variables = {
DD_PROFILING_ENABLED = true,
}
api_container_environment = {
NEW_GRANT_DETAILS_PAGE_ENABLED = true,
}

// Postgres
postgres_enabled = true
Expand Down

0 comments on commit f4c42fb

Please sign in to comment.