Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎁 1019 batch email notifications #2200

Merged
merged 18 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,6 @@ GIT
nokogiri (~> 1.5)
omniauth (>= 1.2, < 3)

GIT
remote: https://github.com/tubbo/activejob-scheduler.git
revision: efe54965e08252da5232412df5bae98732cd045c
specs:
activejob-scheduler (1.0.0.pre)
actionmailer (> 5, < 7)
activejob (> 5, < 7)
activesupport (> 5, < 7)
fugit (~> 1.3)
travis-release (~> 0)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -982,7 +971,6 @@ GEM
openseadragon (0.6.0)
rails (> 3.2.0)
optimist (3.1.0)
options (2.3.2)
order_already (0.3.1)
rails-html-sanitizer (~> 1.4)
orm_adapter (0.5.0)
Expand All @@ -1000,9 +988,6 @@ GEM
addressable (>= 2.4.0)
nokogiri (>= 1.8.0)
public_suffix (>= 4.0.0, < 5)
progress_bar (1.3.3)
highline (>= 1.6, < 3)
options (~> 2.3.0)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
Expand Down Expand Up @@ -1359,9 +1344,6 @@ GEM
tinymce-rails (5.10.9)
railties (>= 3.1.1)
trailblazer-option (0.1.2)
travis-release (0.0.4)
bundler
rake
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
Expand Down Expand Up @@ -1447,7 +1429,6 @@ PLATFORMS
DEPENDENCIES
active-fedora (~> 14.0)
active_elastic_job!
activejob-scheduler!
activerecord-nulldb-adapter
addressable (= 2.8.1)
apartment!
Expand Down Expand Up @@ -1505,7 +1486,6 @@ DEPENDENCIES
parser (>= 3.1.0.0)
pg
postrank-uri (>= 1.0.24)
progress_bar
pry-byebug
puma (~> 5.6)
rack-test (= 0.7.0)
Expand Down
57 changes: 57 additions & 0 deletions app/jobs/batch_email_notification_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

class BatchEmailNotificationJob < ApplicationJob
non_tenant_job
after_perform do |job|
reenqueue(job.arguments.first)
end

def perform(account)
Apartment::Tenant.switch(account.tenant) do
# Query for all users that have email_frequency not set to "off"
users = User.where.not(batch_email_frequency: "off")
users.each do |user|
# Find all undelivered messages within the frequency range of a user and any emails that haven't been sent
undelivered_messages =
Mailboxer::Message.joins(:receipts)
.where(mailboxer_receipts: { receiver_id: user.id, receiver_type: 'User', is_delivered: false })
.where('mailboxer_notifications.created_at >= ?', frequency_date(user.batch_email_frequency))
.select('mailboxer_notifications.*')
.distinct
.to_a

next if undelivered_messages.blank?
send_email(user, undelivered_messages)

# Mark the as read
undelivered_messages.each do |message|
message.receipts.each do |receipt|
receipt.update(is_delivered: true)
end
end
end
end
end

private

def reenqueue(account)
BatchEmailNotificationJob.set(wait_until: Date.tomorrow.midnight).perform_later(account)
end

def frequency_date(frequency)
case frequency
when "daily"
1.day.ago
when "weekly"
1.week.ago
when "monthly"
1.month.ago
end
end

def send_email(user, undelivered_messages)
mailer = HykuMailer.new
mailer.summary_email(user, undelivered_messages)
end
end
22 changes: 21 additions & 1 deletion app/mailers/hyku_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,29 @@ def default_url_options
{ host: host_for_tenant }
end

def summary_email(user, messages)
@user = user
@messages = messages || []
@url = notifications_url

mail(to: @user.email,
subject: "You have #{messages.count} new message(s)",
from: current_tenant.contact_email,
template_path: 'hyku_mailer',
template_name: 'summary_email')
end

private

def host_for_tenant
Account.find_by(tenant: Apartment::Tenant.current)&.cname || Account.admin_host
current_tenant&.cname || Account.admin_host
end

def current_tenant
Account.find_by(tenant: Apartment::Tenant.current)
end

def notifications_url
"https://#{current_tenant.cname}/notifications"
end
end
10 changes: 10 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class User < ApplicationRecord
devise(*Hyku::Application.user_devise_parameters)

after_create :add_default_group_membership!
after_update :mark_all_undelivered_messages_as_delivered!, if: -> { batch_email_frequency == 'off' }

# set default scope to exclude guest users
def self.default_scope
Expand Down Expand Up @@ -163,4 +164,13 @@ def add_default_group_membership!

Hyrax::Group.find_or_create_by!(name: Ability.registered_group_name).add_members_by_id(id)
end

# When the user sets their batch email frequency to 'off' then we want to mark all the messages
# (really the receipts of the messages) to is_delivered tru
def mark_all_undelivered_messages_as_delivered!
mailbox.receipts.where(is_delivered: false).find_each do |receipt|
receipt.is_delivered = true
receipt.save
end
end
end
1 change: 1 addition & 0 deletions app/services/create_account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def schedule_recurring_jobs

EmbargoAutoExpiryJob.perform_later(account)
LeaseAutoExpiryJob.perform_later(account)
BatchEmailNotificationJob.perform_later(account)
end

private
Expand Down
42 changes: 42 additions & 0 deletions app/views/hyku_mailer/summary_email.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Notifications</title>
<style>
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h2>Hello, <%= @user.name %></h2>
<p>You have the following notifications:</p>
<p>Click <a href="<%= @url %>">here</a> to view them in Hyku.</p>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should use the application &/or tenant name rather than "Hyku"? Not a big deal, but many of the users may not know what "Hyku" is. If the email is too generic, wouldn't they possibly just assume it's spam? Including the actual site name, a possible site logo, etc would seem more clear.

Additionally, I can see a future request might be to use i18n for the email text... just something to consider.

<table>
<tr>
<th>Date</th>
<th>Subject</th>
<th>Message</th>
</tr>
<% @messages.each do |message| %>
<tr>
<td><%= message.created_at.to_date %></td>
<td><%= message.subject %></td>
<td><%= message.body.gsub('href="', "href=\"#{URI(@url).origin}").html_safe %></td>
</tr>
<% end %>
</table>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddBatchEmailFrequencyToUsers < ActiveRecord::Migration[6.1]
def change
add_column :users, :batch_email_frequency, :string, default: 'off' unless column_exists?(:users, :batch_email_frequency)
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2024_03_07_053156) do
ActiveRecord::Schema.define(version: 2024_04_29_213539) do

# These are extensions that must be enabled in order to support this database
enable_extension "hstore"
Expand Down Expand Up @@ -914,6 +914,7 @@
t.string "preferred_locale"
t.string "provider"
t.string "uid"
t.string "batch_email_frequency", default: "off"
laritakr marked this conversation as resolved.
Show resolved Hide resolved
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["invitation_token"], name: "index_users_on_invitation_token", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
Expand Down
19 changes: 19 additions & 0 deletions spec/mailers/previews/hyku_mailer_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

# Preview all emails at /rails/mailers/hyku_mailer/summary_email
class HykuMailerPreview < ActionMailer::Preview
def summary_email
message = Struct.new(:subject, :body, :created_at)
messages = [
message.new(
'Deposit needs review ',
'"dummy work (<a href="/concern/generic_works/ab387de7-5cc3-4bee-980b-c08c24a29dfd\">ab387de7-5cc3-4bee-980b-c08c24a29dfd</a>) was deposited by admin@example.com and is awaiting approval "', 1.day.ago
),
message.new('Passing batch create ', 'The batch create for admin@example.com passed.', 2.days.ago)
]

user = Struct.new(:email, :name).new('admin@example.com', 'Admin')

HykuMailer.new.summary_email(user, messages)
end
end
Loading