Add billboards to digest emails (#20862)

* Initial bb work

* Add billboards to digest

* Clean up tests and formatting

* Clean up tests and formatting
This commit is contained in:
Ben Halpern 2024-04-15 12:01:00 -04:00 committed by GitHub
parent 9b15329110
commit cbae624b5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 87 additions and 7 deletions

View file

@ -151,6 +151,8 @@ document.ready.then(() => {
'feed_first',
'feed_second',
'feed_third',
'digest_first',
'digest_second',
];
if (targetedTagPlacements.includes(select.value)) {

View file

@ -4,6 +4,7 @@ class DigestMailer < ApplicationMailer
def digest_email
@user = params[:user]
@articles = params[:articles]
@billboards = params[:billboards]
@unsubscribe = generate_unsubscribe_token(@user.id, :email_digest_periodic)
subject = generate_title

View file

@ -11,13 +11,16 @@ class Billboard < ApplicationRecord
sidebar_right
sidebar_right_second
sidebar_right_third
feed_first feed_second
feed_first
feed_second
feed_third
home_hero
page_fixed_bottom
post_fixed_bottom
post_sidebar
post_comments].freeze
post_comments
digest_first
digest_second].freeze
ALLOWED_PLACEMENT_AREAS_HUMAN_READABLE = ["Sidebar Left (First Position)",
"Sidebar Left (Second Position)",
"Sidebar Right (Home first position)",
@ -30,7 +33,9 @@ class Billboard < ApplicationRecord
"Fixed Bottom (Page)",
"Fixed Bottom (Individual Post)",
"Sidebar Right (Individual Post)",
"Below the comment section"].freeze
"Below the comment section",
"Digest Email First",
"Digest Email Second"].freeze
HOME_FEED_PLACEMENTS = %w[feed_first feed_second feed_third].freeze

View file

@ -16,10 +16,27 @@
</td>
</tr>
<% if @billboards&.first&.present? %>
<tr>
<td bgcolor="#FFFFFF" style="padding: 16px 0 4px;">
<hr style="border-top: 3px solid #0a0a0a;"/>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" style="padding: 20px 0 12px;">
<%= @billboards.first.processed_html.html_safe %>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" style="padding: 12px 0 8px;">
<hr style="border-top: 3px solid #0a0a0a;"/>
</td>
</tr>
<% end %>
<!-- Articles List -->
<% @articles.each_with_index do |article, i| %>
<tr>
<td bgcolor="#FFFFFF" style="padding: <%= i == 0 ? "27" : "17" %>px 0px 0px; text-align: left;">
<td bgcolor="#FFFFFF" style="padding: <%= i == 0 ? "27" : "17" %>px 2px 0px; text-align: left;">
<a href="<%= article_url(article) %>?context=digest" style="font-weight: bold; color:#0a0a0a; font-size: 16px;display:block;"><%= article.title.strip %></a>
<p style="margin-top: 5px; font-size: 14px; color: #808080;">
<%= truncate(article.description, length: 180) %>
@ -42,6 +59,19 @@
</td>
</tr>
<% if @billboards&.second&.present? %>
<tr>
<td bgcolor="#FFFFFF" style="padding: 8px 0 16px;">
<%= @billboards.second.processed_html.html_safe %>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" style="padding: 12px 0 8px;">
<hr style="border-top: 3px solid #0a0a0a;"/>
</td>
</tr>
<% end %>
<!-- Footer -->
<tr>
<td bgcolor="#FFFFFF" style="padding: 15px 0; font-size: 16px;">

View file

@ -9,10 +9,20 @@ module Emails
return unless user&.notification_setting&.email_digest_periodic? && user&.registered?
articles = EmailDigestArticleCollector.new(user).articles_to_send
tags = user.cached_followed_tag_names&.first(12)
first_billboard = Billboard.for_display(area: "digest_first",
user_id: user.id,
user_tags: tags,
user_signed_in: true)
second_billboard = Billboard.for_display(area: "digest_second",
user_id: user.id,
user_tags: tags,
user_signed_in: true)
return unless articles.any?
begin
DigestMailer.with(user: user, articles: articles.to_a).digest_email.deliver_now
DigestMailer.with(user: user, articles: articles.to_a, billboards: [first_billboard, second_billboard])
.digest_email.deliver_now
rescue StandardError => e
Honeybadger.context({ user_id: user.id, article_ids: articles.map(&:id) })
Honeybadger.notify(e)

View file

@ -33,5 +33,15 @@ RSpec.describe DigestMailer do
expect(smtpapi_header).to have_key("category")
expect(smtpapi_header["category"]).to include("Digest Email")
end
it "includes billboard html in body" do
bb_1 = create(:billboard, placement_area: "digest_first", published: true, approved: true)
bb_2 = create(:billboard, placement_area: "digest_second", published: true, approved: true)
email = described_class.with(user: user, articles: [article], billboards: [bb_1, bb_2]).digest_email
expect(email.body.encoded).to include(bb_1.processed_html)
expect(email.body.encoded).to include(bb_2.processed_html)
end
end
end

View file

@ -1,6 +1,16 @@
# Preview all emails at http://localhost:3000/rails/mailers/digest_mailer
class DigestMailerPreview < ActionMailer::Preview
def digest_email
DigestMailer.with(user: User.last, articles: Article.all).digest_email
user = User.last
tags = user.cached_followed_tag_names&.first(12)
first_billboard = Billboard.for_display(area: "digest_first",
user_id: user.id,
user_tags: tags,
user_signed_in: true)
second_billboard = Billboard.for_display(area: "digest_second",
user_id: user.id,
user_tags: tags,
user_signed_in: true)
DigestMailer.with(user: user, articles: Article.all, billboards: [first_billboard, second_billboard]).digest_email
end
end

View file

@ -28,7 +28,7 @@ RSpec.describe Emails::SendUserDigestWorker, type: :worker do
worker.perform(user.id)
expect(DigestMailer).to have_received(:with).with(user: user, articles: Array)
expect(DigestMailer).to have_received(:with).with(user: user, articles: Array, billboards: Array)
expect(mailer).to have_received(:digest_email)
expect(message_delivery).to have_received(:deliver_now)
end
@ -48,6 +48,18 @@ RSpec.describe Emails::SendUserDigestWorker, type: :worker do
expect(DigestMailer).not_to have_received(:with)
end
it "includes billboards" do
create_list(:article, 3, user_id: author.id, public_reactions_count: 20, score: 20)
bb_1 = create(:billboard, placement_area: "digest_first", published: true, approved: true)
bb_2 = create(:billboard, placement_area: "digest_second", published: true, approved: true)
worker.perform(user.id)
expect(DigestMailer).to have_received(:with) do |args|
expect(args[:billboards]).to contain_exactly(bb_1, bb_2)
end
end
end
end
end