Skip to content

Commit 57108c2

Browse files
author
Kirk Wang
authored
Merge pull request #2200 from samvera/i1019-batch-email-notifications
🎁 1019 batch email notifications
2 parents 26c993c + f3740c6 commit 57108c2

38 files changed

+787
-36
lines changed

app/controllers/hyrax/dashboard/profiles_controller_decorator.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# frozen_string_literal: true
2+
23
# OVERRIDE FILE from Hyrax v5.0.0
4+
# - Modify params to allow editing of additional User columns
5+
# - Ensure the current user matches the requested URL.
6+
module Hyrax
7+
module Dashboard
8+
module ProfilesControllerDecorator
9+
EMAIL_OPTIONS = ['never', 'daily', 'weekly', 'monthly'].freeze
10+
11+
def frequency_options
12+
EMAIL_OPTIONS.map do |item|
13+
[I18n.t("hyrax.user_profile.email_frequency.#{item}"), item]
14+
end
15+
end
16+
17+
private
18+
19+
def user_params
20+
params.require(:user).permit(:batch_email_frequency, :avatar, :facebook_handle, :twitter_handle,
21+
:googleplus_handle, :linkedin_handle, :remove_avatar, :orcid)
22+
end
23+
end
24+
end
25+
end
26+
27+
Hyrax::Dashboard::ProfilesController.prepend(Hyrax::Dashboard::ProfilesControllerDecorator)
328

429
##
530
# Ensure the current user matches the requested URL.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# frozen_string_literal: true
2+
3+
class BatchEmailNotificationJob < ApplicationJob
4+
non_tenant_job
5+
after_perform do |job|
6+
reenqueue(job.arguments.first)
7+
end
8+
9+
def perform(account)
10+
Apartment::Tenant.switch(account.tenant) do
11+
# Query for all users that have email_frequency turned off
12+
users = User.where.not(batch_email_frequency: "never")
13+
users.each do |user|
14+
next unless send_email_today?(user)
15+
# Find all undelivered messages within the frequency range of a user and any emails that haven't been sent
16+
undelivered_messages =
17+
Mailboxer::Message.joins(:receipts)
18+
.where(mailboxer_receipts: { receiver_id: user.id, receiver_type: 'User', is_delivered: false })
19+
.where('mailboxer_notifications.created_at >= ?', frequency_date(user.batch_email_frequency))
20+
.select('mailboxer_notifications.*')
21+
.distinct
22+
.to_a
23+
24+
next if undelivered_messages.blank?
25+
send_email(user, undelivered_messages, account)
26+
27+
# Mark the as read
28+
undelivered_messages.each do |message|
29+
message.receipts.each do |receipt|
30+
receipt.update(is_delivered: true)
31+
end
32+
end
33+
34+
user.update(last_emailed_at: Time.current)
35+
end
36+
end
37+
end
38+
39+
private
40+
41+
def reenqueue(account)
42+
BatchEmailNotificationJob.set(wait_until: Date.tomorrow.midnight).perform_later(account)
43+
end
44+
45+
def send_email_today?(user)
46+
return true if user.last_emailed_at.nil?
47+
48+
next_email_date = case user.batch_email_frequency
49+
when "daily"
50+
user.last_emailed_at + 1.day
51+
when "weekly"
52+
user.last_emailed_at + 1.week
53+
when "monthly"
54+
user.last_emailed_at + 1.month
55+
end
56+
57+
Time.current >= next_email_date
58+
end
59+
60+
def frequency_date(frequency)
61+
case frequency
62+
when "daily"
63+
1.day.ago
64+
when "weekly"
65+
1.week.ago
66+
when "monthly"
67+
1.month.ago
68+
end
69+
end
70+
71+
def send_email(user, undelivered_messages, account)
72+
HykuMailer.summary_email(user, undelivered_messages, account).deliver_now
73+
end
74+
end

app/mailers/hyku_mailer.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,27 @@ def default_url_options
66
{ host: host_for_tenant }
77
end
88

9+
def summary_email(user, messages, account)
10+
@user = user
11+
@messages = messages || []
12+
@account = account
13+
@url = notifications_url_for(@account)
14+
@application_name = account.sites.application_name
15+
16+
mail(to: @user.email,
17+
subject: "You have #{@messages.count} new message(s) on #{@application_name}",
18+
from: @account.contact_email,
19+
template_path: 'hyku_mailer',
20+
template_name: 'summary_email')
21+
end
22+
923
private
1024

1125
def host_for_tenant
1226
Account.find_by(tenant: Apartment::Tenant.current)&.cname || Account.admin_host
1327
end
28+
29+
def notifications_url_for(account)
30+
"https://#{account.cname}/notifications"
31+
end
1432
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
# OVERRIDE: Mailboxer v0.15.1 to mark receipts as delivered for users that
4+
# set their `batch_email_frequency` to 'never'
5+
6+
module Mailboxer
7+
module ReceiptDecorator
8+
extend ActiveSupport::Concern
9+
10+
prepended do
11+
after_create :mark_as_delivered
12+
end
13+
14+
def mark_as_delivered
15+
user = User.find_by(id: receiver_id)
16+
return unless user&.batch_email_frequency == 'never'
17+
18+
update(is_delivered: true)
19+
end
20+
end
21+
end
22+
23+
Mailboxer::Receipt.prepend(Mailboxer::ReceiptDecorator)

app/models/user.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class User < ApplicationRecord
1616
devise(*Hyku::Application.user_devise_parameters)
1717

1818
after_create :add_default_group_membership!
19+
after_update :mark_all_undelivered_messages_as_delivered!, if: -> { batch_email_frequency == 'never' }
1920

2021
# set default scope to exclude guest users
2122
def self.default_scope
@@ -163,4 +164,12 @@ def add_default_group_membership!
163164

164165
Hyrax::Group.find_or_create_by!(name: Ability.registered_group_name).add_members_by_id(id)
165166
end
167+
168+
# When the user sets their batch email frequency to 'never' then we want to mark all the messages
169+
# (really the receipts of the messages) to is_delivered tru
170+
def mark_all_undelivered_messages_as_delivered!
171+
mailbox.receipts.where(is_delivered: false).find_each do |receipt|
172+
receipt.update(is_delivered: true)
173+
end
174+
end
166175
end

app/services/create_account.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def schedule_recurring_jobs
8686

8787
EmbargoAutoExpiryJob.perform_later(account)
8888
LeaseAutoExpiryJob.perform_later(account)
89+
BatchEmailNotificationJob.perform_later(account)
8990
end
9091

9192
private
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Notifications</title>
7+
<style>
8+
table {
9+
width: 100%;
10+
border-collapse: collapse;
11+
margin-bottom: 20px;
12+
}
13+
th, td {
14+
border: 1px solid #ddd;
15+
padding: 8px;
16+
text-align: left;
17+
}
18+
th {
19+
background-color: #f2f2f2;
20+
}
21+
</style>
22+
</head>
23+
<body>
24+
<h2>Hello, <%= @user.name %></h2>
25+
<p>You have the following notifications:</p>
26+
<p>Click <a href="<%= @url %>">here</a> to view them on <%= @application_name %>.</p>
27+
<table>
28+
<tr>
29+
<th>Date</th>
30+
<th>Subject</th>
31+
<th>Message</th>
32+
</tr>
33+
<% @messages.each do |message| %>
34+
<tr>
35+
<td><%= message.created_at.to_date %></td>
36+
<td><%= message.subject %></td>
37+
<td><%= message.body.gsub('href="', "href=\"#{URI(@url).origin}").html_safe %></td>
38+
</tr>
39+
<% end %>
40+
</table>
41+
</body>
42+
</html>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!-- OVERRIDE Hyrax 5.0: Add batch email frequency to User edit -->
2+
3+
<%= form_for @user,
4+
url: hyrax.dashboard_profile_path(@user.to_param),
5+
html: { multipart: true } do |f| %>
6+
<div class="form-group row">
7+
<%= f.label :avatar, t(".change_picture").html_safe, class: "col-4 col-form-label" %>
8+
<div class="col-8">
9+
<%= image_tag @user.avatar.url(:thumb) if @user.avatar? %>
10+
<%= f.file_field :avatar %>
11+
<%= f.hidden_field :avatar_cache %>
12+
<span class="form-text"><%= t('.help_change_picture_type') %></span>
13+
14+
<div class="form-check">
15+
<%= f.label :remove_avatar, class: 'form-check-label' do %>
16+
<%= f.check_box :remove_avatar, class: 'form-check-input' %>
17+
<%= t(".delete_picture") %>
18+
<a href="#" id="delete_picture_help" data-toggle="popover" data-content="<%= t('.delete_picture_data_content') %>" data-original-title="<%= t('.delete_picture_data_original_title') %>"><i class="fa fa-question"></i></a>
19+
<% end %>
20+
</div>
21+
</div>
22+
</div><!-- .form-group -->
23+
24+
<% if Hyrax.config.arkivo_api? %>
25+
<%= render partial: 'zotero', locals: { f: f, user: @user } %>
26+
<% end %>
27+
28+
<div class="form-group row">
29+
<%= f.label :orcid, class: 'col-4 col-form-label' do %>
30+
<%= orcid_label %>
31+
<% end %>
32+
<div class="col-8">
33+
<%= f.text_field :orcid, class: "form-control" %>
34+
</div>
35+
</div><!-- .form-group -->
36+
37+
<div class="form-group row">
38+
<%= f.label :twitter_handle, t(".twitter_handle").html_safe, class: 'col-4 col-form-label' %>
39+
<div class="col-8">
40+
<%= f.text_field :twitter_handle, class: "form-control" %>
41+
</div>
42+
</div><!-- .form-group -->
43+
44+
<div class="form-group row">
45+
<%= f.label :facebook_handle, t(".facebook_handle").html_safe, class: 'col-4 col-form-label' %>
46+
<div class="col-8">
47+
<%= f.text_field :facebook_handle, class: "form-control" %>
48+
</div>
49+
</div><!-- .form-group -->
50+
51+
<div class="form-group row">
52+
<%= f.label :googleplus_handle, t(".google_handle").html_safe, class: 'col-4 col-form-label' %>
53+
<div class="col-8">
54+
<%= f.text_field :googleplus_handle, class: "form-control" %>
55+
</div>
56+
</div><!-- .form-group -->
57+
58+
<!-- OVERRIDE: Add batch email frequency to edit -->
59+
<div class="form-group row">
60+
<%= f.label :batch_email_frequency, t("hyrax.user_profile.email_frequency.label").html_safe, class: 'col-4 col-form-label' %>
61+
<div class="col-8">
62+
<%= f.select :batch_email_frequency, controller.frequency_options, {}, { class: "form-control" } %>
63+
</div>
64+
</div><!-- .form-group -->
65+
66+
<%= render 'trophy_edit', trophies: @trophies %>
67+
68+
<%= f.button t(".save_profile").html_safe, type: 'submit', class: "btn btn-primary" %>
69+
<% end %>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!-- OVERRIDE Hyrax 5.0: Display batch email frequency -->
2+
3+
<dl id="user_info">
4+
5+
<% if user.orcid.present? %>
6+
<dt><%= orcid_label('profile') %></dt>
7+
<dd><%= link_to user.orcid, user.orcid, { target: '_blank' } %></dd>
8+
<% end %>
9+
10+
<% if Hyrax.config.arkivo_api? && user.zotero_userid.present? %>
11+
<dt><%= zotero_label(html_class: 'profile') %></dt>
12+
<dd><%= link_to zotero_profile_url(user.zotero_userid), zotero_profile_url(user.zotero_userid), { target: '_blank' } %></dd>
13+
<% end %>
14+
15+
<% if user.facebook_handle.present? %>
16+
<dt><span class="fa fa-facebook" aria-hidden="true"></span> Facebook Handle</dt>
17+
<dd><%= link_to user.facebook_handle, "http://facebook.com/#{user.facebook_handle}", {target:'_blank'} %></dd>
18+
<% end %>
19+
20+
<% if user.twitter_handle.present? %>
21+
<dt><span class="fa fa-twitter" aria-hidden="true"></span> Twitter Handle</dt>
22+
<dd><%= link_to user.twitter_handle, "http://twitter.com/#{user.twitter_handle}", {target:'_blank'} %></dd>
23+
<% end %>
24+
25+
<% if user.googleplus_handle.present? %>
26+
<dt><span class="fa fa-google-plus" aria-hidden="true"></span> Google+ Handle</dt>
27+
<dd><%= link_to user.googleplus_handle, "http://google.com/+#{user.googleplus_handle}", {target:'_blank'} %></dd>
28+
<% end %>
29+
30+
<% if user.linkedin_handle.present? %>
31+
<dt><span class="fa fa-linkedin" aria-hidden="true"></span> LinkedIn</dt>
32+
<dd><%= link_to "#{@linkedInUrl}", "#{@linkedInUrl}", { target: '_blank' } %></dd>
33+
<% end %>
34+
35+
<dt><span class="fa fa-envelope" aria-hidden="true"></span> Email</dt>
36+
<dd><%= mail_to user.email %></dd>
37+
38+
<% if user.chat_id %>
39+
<dt><span class="fa fa-bullhorn" aria-hidden="true"></span> Chat ID</dt>
40+
<dd><%= user.chat_id %></dd>
41+
<% end %>
42+
43+
<% if user.website %>
44+
<dt><span class="fa fa-globe" aria-hidden="true"></span> Website(s)</dt>
45+
<dd><%= iconify_auto_link(user.website) %></dd>
46+
<% end %>
47+
48+
<% if user.title %>
49+
<dt>Title</dt>
50+
<dd><%= user.title %></dd>
51+
<% end %>
52+
53+
<% if user.admin_area %>
54+
<dt>Administrative Area</dt>
55+
<dd><%= user.admin_area %></dd>
56+
<% end %>
57+
58+
<% if user.department %>
59+
<dt>Department</dt>
60+
<dd><%= user.department %></dd>
61+
<% end %>
62+
63+
<% if user.office %>
64+
<dt>Office</dt>
65+
<dd><%= user.office %></dd>
66+
<% end %>
67+
68+
<% if user.address %>
69+
<dt><span class="fa fa-map-marker" aria-hidden="true"></span> Address</dt>
70+
<dd><%= user.address %></dd>
71+
<% end %>
72+
73+
<% if user.affiliation %>
74+
<dt>Affiliation</dt>
75+
<dd><%= user.affiliation %></dd>
76+
<% end %>
77+
78+
<% if user.telephone %>
79+
<dt><span class="fa fa-phone" aria-hidden="true"></span> Telephone</dt>
80+
<dd><%= link_to_telephone(user) %></dd>
81+
<% end %>
82+
83+
<!-- OVERRIDE Hyrax 5.0: Display batch email frequency -->
84+
<dt><%= t("hyrax.user_profile.email_frequency.label").html_safe %></dt>
85+
<% frequency = user.batch_email_frequency || 'not_set' %>
86+
<dd><%= t("hyrax.user_profile.email_frequency.#{frequency}") %></dd>
87+
</dl>

0 commit comments

Comments
 (0)