adds email digest for proposal notifications

This commit is contained in:
rgarcia
2016-06-14 17:53:36 +02:00
parent 0fba15b1e5
commit 6e800c5120
13 changed files with 199 additions and 38 deletions

View File

@@ -59,6 +59,14 @@ class Mailer < ApplicationMailer
end end
end end
def proposal_notification_digest(user)
@notifications = user.notifications.where(notifiable_type: "ProposalNotification")
with_user(user) do
mail(to: user.email, subject: "Email digest")
end
end
private private
def with_user(user, &block) def with_user(user, &block)

View File

@@ -51,6 +51,7 @@ class User < ActiveRecord::Base
scope :officials, -> { where("official_level > 0") } scope :officials, -> { where("official_level > 0") }
scope :for_render, -> { includes(:organization) } scope :for_render, -> { includes(:organization) }
scope :by_document, -> (document_type, document_number) { where(document_type: document_type, document_number: document_number) } scope :by_document, -> (document_type, document_number) { where(document_type: document_type, document_number: document_number) }
scope :email_digest, -> { where(email_digest: true) }
before_validation :clean_document_number before_validation :clean_document_number

View File

@@ -11,31 +11,33 @@
</tbody> </tbody>
</table> </table>
<!-- EACH PROPOSAL NOTIFICATION DO --> <%= @notifications.each do |notification| %>
<table style="width: 100%; border-top: 1px solid #DEE0E3; padding-top: 12px;"> <table style="width: 100%; border-top: 1px solid #DEE0E3; padding-top: 12px;">
<tbody> <tbody>
<tr> <tr>
<td style="padding-bottom: 20px; padding-left: 10px;"> <td style="padding-bottom: 20px; padding-left: 10px;">
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 20px;font-weight: bold;line-height: 24px; margin: 0;"> <p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 20px;font-weight: bold;line-height: 24px; margin: 0;">
<%= @notification.title %> <%= link_to notification.notifiable.title, notification_url(notification) %>
</p> </p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px; margin-top: 0; color: #cccccc;"> <p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px; margin-top: 0; color: #cccccc;">
<%= @notification.proposal.title %>&nbsp;&bull;&nbsp;<%= @notification.proposal.created_at.to_date %>&nbsp;&bull;&nbsp;<%= @notification.proposal.author.name %> <%= notification.notifiable.proposal.title %>&nbsp;&bull;&nbsp;
<%= notification.notifiable.proposal.created_at.to_date %>&nbsp;&bull;&nbsp;
<%= notification.notifiable.proposal.author.name %>
</p> </p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;"> <p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= @notification.body %> <%= notification.notifiable.body %>
</p> </p>
<table style="width: 100%;"> <table style="width: 100%;">
<tbody> <tbody>
<tr> <tr>
<td style="padding-bottom: 12px;"> <td style="padding-bottom: 12px;">
<%= link_to "#comments", style: "font-family: 'Open Sans','Helvetica Neue',arial,sans-serif; background: #f7f5f2; border-radius: 6px; color: #3d3d66!important; font-weight: bold; margin: 0px; padding: 10px 15px; text-align: center; text-decoration: none; min-width: 160px; display: inline-block;" do %> <%= link_to proposal_url(notification.notifiable.proposal, anchor: "comments"), style: "font-family: 'Open Sans','Helvetica Neue',arial,sans-serif; background: #f7f5f2; border-radius: 6px; color: #3d3d66!important; font-weight: bold; margin: 0px; padding: 10px 15px; text-align: center; text-decoration: none; min-width: 160px; display: inline-block;" do %>
<%= image_tag('icon_mailer_share.png', style: "border: 0; display: inline-block; width: 100%; max-width: 16px", alt: "") %> <%= image_tag('icon_mailer_share.png', style: "border: 0; display: inline-block; width: 100%; max-width: 16px", alt: "") %>
<%= t('mailers.proposal_notification_digest.share') %> <%= t('mailers.proposal_notification_digest.share') %>
<% end %> <% end %>
<%= link_to "#social-share", style: "font-family: 'Open Sans','Helvetica Neue',arial,sans-serif; background: #f7f5f2; border-radius: 6px; color: #3d3d66!important; font-weight: bold; margin: 0px; padding: 10px 15px; text-align: center; text-decoration: none; min-width: 160px; display: inline-block; margin-left: 12px;" do %> <%= link_to proposal_url(notification.notifiable.proposal, anchor: "social-share"), style: "font-family: 'Open Sans','Helvetica Neue',arial,sans-serif; background: #f7f5f2; border-radius: 6px; color: #3d3d66!important; font-weight: bold; margin: 0px; padding: 10px 15px; text-align: center; text-decoration: none; min-width: 160px; display: inline-block; margin-left: 12px;" do %>
<%= image_tag('icon_mailer_comment.png', style: "border: 0; display: inline-block; width: 100%; max-width: 16px; vertical-align: middle;", alt: "") %> <%= image_tag('icon_mailer_comment.png', style: "border: 0; display: inline-block; width: 100%; max-width: 16px; vertical-align: middle;", alt: "") %>
<%= t('mailers.proposal_notification_digest.comment') %> <%= t('mailers.proposal_notification_digest.comment') %>
<% end %> <% end %>
@@ -47,5 +49,5 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<!-- END --> <% end %>
</td> </td>

View File

@@ -0,0 +1,5 @@
class AddEmailDigestToUsers < ActiveRecord::Migration
def change
add_column :users, :email_digest, :boolean, default: true
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160608174104) do ActiveRecord::Schema.define(version: 20160613150659) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -460,6 +460,7 @@ ActiveRecord::Schema.define(version: 20160608174104) do
t.string "gender", limit: 10 t.string "gender", limit: 10
t.datetime "date_of_birth" t.datetime "date_of_birth"
t.boolean "email_on_proposal_notification", default: true t.boolean "email_on_proposal_notification", default: true
t.boolean "email_digest", default: true
end end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree

14
lib/email_digest.rb Normal file
View File

@@ -0,0 +1,14 @@
class EmailDigest
def initialize
end
def create
User.email_digest.each do |user|
if user.notifications.where(notifiable_type: "ProposalNotification").any?
Mailer.proposal_notification_digest(user).deliver_later
end
end
end
end

9
lib/tasks/emails.rake Normal file
View File

@@ -0,0 +1,9 @@
namespace :emails do
desc "Sends email digest of proposal notifications to each user"
task digest: :environment do
email_digest = EmailDigest.new
email_digest.create
end
end

View File

@@ -136,7 +136,7 @@ FactoryGirl.define do
factory :proposal do factory :proposal do
sequence(:title) { |n| "Proposal #{n} title" } sequence(:title) { |n| "Proposal #{n} title" }
summary 'In summary, what we want is...' sequence(:summary) { |n| "In summary, what we want is... #{n}" }
description 'Proposal description' description 'Proposal description'
question 'Proposal question' question 'Proposal question'
external_url 'http://external_documention.es' external_url 'http://external_documention.es'

View File

@@ -2,7 +2,7 @@ require 'rails_helper'
feature 'Direct messages' do feature 'Direct messages' do
scenario "Create", :focus do scenario "Create" do
sender = create(:user, :level_two) sender = create(:user, :level_two)
receiver = create(:user, :level_two) receiver = create(:user, :level_two)

View File

@@ -204,4 +204,51 @@ feature 'Emails' do
end end
end end
context "Proposal notification digest" do
scenario "notifications for proposals that I have supported" do
user = create(:user, email_digest: true)
proposal1 = create(:proposal)
proposal2 = create(:proposal)
proposal3 = create(:proposal)
create(:vote, votable: proposal1, voter: user)
create(:vote, votable: proposal2, voter: user)
reset_mailer
notification1 = create_proposal_notification(proposal1)
notification2 = create_proposal_notification(proposal2)
notification3 = create_proposal_notification(proposal3)
email_digest = EmailDigest.new
email_digest.create
email = open_last_email
expect(email).to have_subject("Email digest")
expect(email).to deliver_to(user.email)
expect(email).to have_body_text(proposal1.title)
expect(email).to have_body_text(notification1.notifiable.title)
expect(email).to have_body_text(notification1.notifiable.body)
expect(email).to have_body_text(proposal1.author.name)
expect(email).to have_body_text(/#{notification_path(notification1)}/)
expect(email).to have_body_text(/#{proposal_path(proposal1, anchor: 'comments')}/)
expect(email).to have_body_text(/#{proposal_path(proposal1, anchor: 'social-share')}/)
expect(email).to have_body_text(proposal2.title)
expect(email).to have_body_text(notification2.notifiable.title)
expect(email).to have_body_text(notification2.notifiable.body)
expect(email).to have_body_text(/#{notification_path(notification2)}/)
expect(email).to have_body_text(/#{proposal_path(proposal2, anchor: 'comments')}/)
expect(email).to have_body_text(/#{proposal_path(proposal2, anchor: 'social-share')}/)
expect(email).to have_body_text(proposal2.author.name)
expect(email).to_not have_body_text(proposal3.title)
end
end
end end

View File

@@ -51,6 +51,53 @@ feature 'Proposal Notifications' do
expect(page).to have_link("the proposal's page", href: proposal_path(proposal)) expect(page).to have_link("the proposal's page", href: proposal_path(proposal))
end end
context "Receivers" do
scenario "Only send a digest to users that have the option set in their profile" do
user1 = create(:user, email_digest: true)
user2 = create(:user, email_digest: true)
user3 = create(:user, email_digest: false)
proposal = create(:proposal)
[user1, user2, user3].each do |user|
create(:vote, votable: proposal, voter: user)
end
create_proposal_notification(proposal)
reset_mailer
email_digest = EmailDigest.new
email_digest.create
expect(unread_emails_for(user1.email).size).to eql parse_email_count(1)
expect(unread_emails_for(user2.email).size).to eql parse_email_count(1)
expect(unread_emails_for(user3.email).size).to eql parse_email_count(0)
end
scenario "Only send a digest to users that have voted for a proposal" do
user1 = create(:user, email_digest: true)
user2 = create(:user, email_digest: true)
user3 = create(:user, email_digest: true)
proposal = create(:proposal)
[user1, user2].each do |user|
create(:vote, votable: proposal, voter: user)
end
create_proposal_notification(proposal)
reset_mailer
email_digest = EmailDigest.new
email_digest.create
expect(unread_emails_for(user1.email).size).to eql parse_email_count(1)
expect(unread_emails_for(user2.email).size).to eql parse_email_count(1)
expect(unread_emails_for(user3.email).size).to eql parse_email_count(0)
end
end
context "Permissions" do context "Permissions" do
scenario "Link to send the message" do scenario "Link to send the message" do

View File

@@ -0,0 +1,9 @@
require 'rails_helper'
describe EmailDigest do
describe "create" do
pending "only send unread notifications"
end
end

View File

@@ -196,4 +196,22 @@ module CommonActions
tag_cloud.tags.map(&:name) tag_cloud.tags.map(&:name)
end end
def create_proposal_notification(proposal)
login_as(proposal.author)
visit root_path
click_link "My activity"
within("#proposal_#{proposal.id}") do
click_link "Send message"
end
fill_in 'proposal_notification_title', with: "Thank you for supporting my proposal #{proposal.title}"
fill_in 'proposal_notification_body', with: "Please share it with others so we can make it happen! #{proposal.summary}"
click_button "Send message"
expect(page).to have_content "Your message has been sent correctly."
Notification.last
end
end end