Fix /connect bug and add email-if-inactive functionality (#482)
* Add basic functionality for connect message emails * Fix lint * Add connect messages email permission
This commit is contained in:
parent
cea3fc7f26
commit
01e43a99e7
16 changed files with 123 additions and 8 deletions
|
|
@ -20,6 +20,7 @@ class EmailSubscriptionsController < ApplicationController
|
|||
email_comment_notifications: "comment notifications",
|
||||
email_follower_notifications: "follower notifications",
|
||||
email_mention_notifications: "mention notifications",
|
||||
email_connect_messages: "connect messages",
|
||||
email_unread_notifications: "unread notifications",
|
||||
}
|
||||
emails_type[given_email_type]
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class UsersController < ApplicationController
|
|||
@tab_list = @user.settings_tab_list
|
||||
@tab = params["user"]["tab"] || "profile"
|
||||
authorize @user
|
||||
# raise permitted_attributes(@user).to_s
|
||||
if @user.update(permitted_attributes(@user))
|
||||
RssReader.new.delay.fetch_user(@user) if @user.feed_url.present?
|
||||
notice = "Your profile was successfully updated."
|
||||
|
|
|
|||
|
|
@ -55,6 +55,13 @@ class NotifyMailer < ApplicationMailer
|
|||
mail(to: @user.email, subject: "Thank you for your report")
|
||||
end
|
||||
|
||||
def new_message_email(message)
|
||||
@message = message
|
||||
@user = message.direct_receiver
|
||||
subject = "#{message.user.name} just messaged you"
|
||||
mail(to: @user.email, subject: subject)
|
||||
end
|
||||
|
||||
def reporter_resolution_email(report)
|
||||
@feedback_message = report
|
||||
@user = report.reporter
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@ class ChatChannel < ApplicationRecord
|
|||
channel_type == "open"
|
||||
end
|
||||
|
||||
def direct?
|
||||
channel_type == "direct"
|
||||
end
|
||||
|
||||
def invite_only?
|
||||
channel_type == "invite_only"
|
||||
end
|
||||
|
||||
def clear_channel
|
||||
messages.each(&:destroy!)
|
||||
Pusher.trigger(pusher_channels, "channel-cleared", { chat_channel_id: id }.to_json)
|
||||
|
|
@ -84,9 +92,9 @@ class ChatChannel < ApplicationRecord
|
|||
end
|
||||
|
||||
def pusher_channels
|
||||
if channel_type == "invite_only"
|
||||
if invite_only?
|
||||
"presence-channel-#{id}"
|
||||
elsif channel_type == "open"
|
||||
elsif open?
|
||||
"open-channel-#{id}"
|
||||
else
|
||||
chat_channel_memberships.pluck(:user_id).map { |id| "private-message-notifications-#{id}" }
|
||||
|
|
@ -95,7 +103,7 @@ class ChatChannel < ApplicationRecord
|
|||
|
||||
def adjusted_slug(user = nil, caller_type = "reciever")
|
||||
user ||= current_user
|
||||
if channel_type == "direct" && caller_type == "reciever"
|
||||
if direct? && caller_type == "reciever"
|
||||
"@" + slug.gsub("/#{user.username}", "").gsub("#{user.username}/", "")
|
||||
elsif caller_type == "sender"
|
||||
"@" + user.username
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class ChatChannelMembership < ApplicationRecord
|
|||
private
|
||||
|
||||
def permission
|
||||
if chat_channel.channel_type == "direct" && chat_channel.slug.split("/").exclude?(user.username)
|
||||
if chat_channel.direct? && chat_channel.slug.split("/").exclude?(user.username)
|
||||
errors.add(:user_id, "is not allowed in chat")
|
||||
end
|
||||
# To be possibly implemented in future
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ class Message < ApplicationRecord
|
|||
|
||||
before_save :determine_user_validity
|
||||
before_validation :evaluate_markdown
|
||||
after_create :send_email_if_appropriate
|
||||
after_create :update_chat_channel_last_message_at
|
||||
after_create :update_all_has_unopened_messages_statuses
|
||||
|
||||
|
|
@ -40,6 +41,11 @@ class Message < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def direct_receiver
|
||||
return if chat_channel.channel_type != "direct"
|
||||
chat_channel.users.where.not(id: user.id).first
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_chat_channel_last_message_at
|
||||
|
|
@ -67,7 +73,7 @@ class Message < ApplicationRecord
|
|||
doc = Nokogiri::HTML(html)
|
||||
rich_style = "border: 1px solid #0a0a0a; border-radius: 3px; padding: 8px;"
|
||||
doc.css("a").each do |a|
|
||||
if a["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/") && article = Article.find_by_slug(a["href"].split("/")[4].split("?")[0])
|
||||
if article = rich_link_article(a)
|
||||
html = html + "<a style='color: #0a0a0a' href='#{article.path}'
|
||||
target='_blank' data-content='articles/#{article.id}'>
|
||||
<h1 style='#{rich_style}' data-content='articles/#{article.id}'>
|
||||
|
|
@ -94,4 +100,22 @@ class Message < ApplicationRecord
|
|||
membership = sub.user.chat_channel_memberships.order("last_opened_at DESC").first
|
||||
membership.last_opened_at > 40.seconds.ago
|
||||
end
|
||||
|
||||
def rich_link_article(a)
|
||||
if a["href"].include?("//#{ApplicationConfig['APP_DOMAIN']}/") && a["href"].split("/")[4]
|
||||
Article.find_by_slug(a["href"].split("/")[4].split("?")[0])
|
||||
end
|
||||
end
|
||||
|
||||
def send_email_if_appropriate
|
||||
recipient = direct_receiver
|
||||
return if !chat_channel.direct? ||
|
||||
recipient.updated_at > 2.hours.ago ||
|
||||
recipient.chat_channel_memberships.order("last_opened_at DESC").
|
||||
first.last_opened_at > 18.hours.ago ||
|
||||
chat_channel.last_message_at > 45.minutes.ago ||
|
||||
recipient.email_connect_messages == false
|
||||
|
||||
NotifyMailer.new_message_email(self).deliver
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class UserPolicy < ApplicationPolicy
|
|||
email_follower_notifications
|
||||
email_membership_newsletter
|
||||
email_mention_notifications
|
||||
email_connect_messages
|
||||
email_newsletter
|
||||
email_public
|
||||
email_unread_notifications
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
</td></tr><tr><td style='padding:20px;padding-bottom:30px;border-radius:3px;font-size:19px;background:#f4f4f4'>
|
||||
<%= @mentionable.processed_html.html_safe %>
|
||||
<a style="background:#3c7dc1;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@mention.mentionable.path%>'>read & reply</a>
|
||||
<a style="background:#3c7dc1;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@mention.mentionable.path%>'>view on dev.to</a>
|
||||
</td></tr></table>
|
||||
|
|
|
|||
10
app/views/mailers/notify_mailer/new_message_email.html.erb
Normal file
10
app/views/mailers/notify_mailer/new_message_email.html.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<h2 style="font-size:25px;"><%= link_to(@message.user.name, "https://dev.to/#{@message.user.username}") %> sent you a message on DEV Connect</h2>
|
||||
<table><tr><td style='color:#c3c3c3;font-size:14px;padding-bottom:8px'>
|
||||
</td></tr><tr><td style='padding:20px;padding-bottom:30px;border-radius:3px;font-size:19px;background:#f4f4f4'>
|
||||
<%= @message.message_html %>
|
||||
<br/><br/>
|
||||
<a style="background:#3c7dc1;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to/connect/@<%= @message.user.username %>'>view on dev.to</a>
|
||||
</td></tr></table>
|
||||
<br/>
|
||||
|
||||
<em>You only get emails like this if you have not been active on <a href="https://dev.to/connect">dev.to/connect</a> in the past day. You may disable this type of email in your settings.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<%= ActionController::Base.helpers.strip_tags(@message.message_html.html_safe) %>
|
||||
|
||||
View now: https://dev.to/connect/@<%= @message.user.username %>
|
||||
|
|
@ -6,5 +6,5 @@
|
|||
</td></tr><tr><td style='padding:20px;padding-bottom:30px;border-radius:3px;font-size:19px;background:#f4f4f4'>
|
||||
<h2 style="font-size:22px;color:rgb(107, 107, 107)">re: <em><%= @comment.commentable.title %></em></h2>
|
||||
<%= @comment.processed_html.html_safe %>
|
||||
<a style="background:#3c7dc1;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@comment.path%>'>read & reply</a> <a style="background:#1f1f1f;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@comment.commentable.path%>'>read original post</a>
|
||||
<a style="background:#3c7dc1;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@comment.path%>'>view on dev.to</a> <a style="background:#1f1f1f;color:white;padding:5px 14px;border-radius:3px;text-decoration:none;display:inline-block;margin-top:4px;" href='https://dev.to<%=@comment.commentable.path%>'>read original post</a>
|
||||
</td></tr></table>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
<%= f.check_box :email_badge_notifications %>
|
||||
<%= f.label :email_badge_notifications, "Send me an email when I receive a badge" %>
|
||||
</div>
|
||||
<div class="sub-field">
|
||||
<%= f.check_box :email_connect_messages %>
|
||||
<%= f.label :email_connect_messages, "Send me an email when I receive a direct message (while inactive)" %>
|
||||
</div>
|
||||
<div class="sub-field">
|
||||
<%= f.check_box :email_unread_notifications %>
|
||||
<%= f.label :email_unread_notifications, "Send me occasional reminders that I have unread notifications on dev.to" %>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
class AddEmailUnreadMessagesToUsers < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
add_column :users, :email_connect_messages, :boolean, default:true
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20180806142338) do
|
||||
ActiveRecord::Schema.define(version: 20180826174411) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
|
|
@ -378,6 +378,10 @@ ActiveRecord::Schema.define(version: 20180806142338) do
|
|||
create_table "messages", force: :cascade do |t|
|
||||
t.bigint "chat_channel_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.text "encrypted_message_html"
|
||||
t.text "encrypted_message_html_iv"
|
||||
t.text "encrypted_message_markdown"
|
||||
t.text "encrypted_message_markdown_iv"
|
||||
t.string "message_html", null: false
|
||||
t.string "message_markdown", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
|
|
@ -632,6 +636,7 @@ ActiveRecord::Schema.define(version: 20180806142338) do
|
|||
t.string "email", default: "", null: false
|
||||
t.boolean "email_badge_notifications", default: true
|
||||
t.boolean "email_comment_notifications", default: true
|
||||
t.boolean "email_connect_messages", default: true
|
||||
t.boolean "email_digest_periodic", default: true, null: false
|
||||
t.boolean "email_follower_notifications", default: true
|
||||
t.boolean "email_membership_newsletter", default: false
|
||||
|
|
|
|||
|
|
@ -27,4 +27,8 @@ class NotifyMailerPreview < ActionMailer::Preview
|
|||
def new_report_email
|
||||
NotifyMailer.new_report_email(FeedbackMessage.first)
|
||||
end
|
||||
|
||||
def new_message_email
|
||||
NotifyMailer.new_message_email(Message.last)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -38,4 +38,46 @@ RSpec.describe Message, type: :model do
|
|||
message_markdown: "hello")
|
||||
expect(message).to be_valid
|
||||
end
|
||||
|
||||
it "creates rich link in connect with proper link" do
|
||||
article = create(:article)
|
||||
message = create(:message, chat_channel_id: chat_channel.id, user_id: user.id,
|
||||
message_markdown: "hello http://#{ApplicationConfig['APP_DOMAIN']}#{article.path}")
|
||||
expect(message.message_html).to include(article.title)
|
||||
expect(message.message_html).to include("data-content")
|
||||
end
|
||||
|
||||
it "creates rich link in connect with non-rich link" do
|
||||
message = create(:message, chat_channel_id: chat_channel.id, user_id: user.id,
|
||||
message_markdown: "hello http://#{ApplicationConfig['APP_DOMAIN']}/report-abuse")
|
||||
expect(message.message_html).not_to include("data-content")
|
||||
end
|
||||
|
||||
it "sends email if user not recently active on /connect" do
|
||||
chat_channel.add_users([user, user2])
|
||||
chat_channel.update_column(:channel_type, "direct")
|
||||
user2.update_column(:updated_at, 1.day.ago)
|
||||
user2.chat_channel_memberships.last.update_column(:last_opened_at, 2.days.ago)
|
||||
create(:message, chat_channel_id: chat_channel.id, user_id: user.id,
|
||||
message_markdown: "hello http://#{ApplicationConfig['APP_DOMAIN']}/report-abuse")
|
||||
expect(EmailMessage.last.subject).to start_with("#{user.name} just messaged you")
|
||||
end
|
||||
|
||||
it "does not send email if user has been recently active" do
|
||||
chat_channel.add_users([user, user2])
|
||||
create(:message, chat_channel_id: chat_channel.id, user_id: user.id,
|
||||
message_markdown: "hello http://#{ApplicationConfig['APP_DOMAIN']}/report-abuse")
|
||||
expect(EmailMessage.all.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not send email if user has email_messages turned off" do
|
||||
chat_channel.add_users([user, user2])
|
||||
chat_channel.update_column(:channel_type, "direct")
|
||||
user2.update_column(:updated_at, 1.day.ago)
|
||||
user2.update_column(:email_connect_messages, false)
|
||||
user2.chat_channel_memberships.last.update_column(:last_opened_at, 2.days.ago)
|
||||
create(:message, chat_channel_id: chat_channel.id, user_id: user.id,
|
||||
message_markdown: "hello http://#{ApplicationConfig['APP_DOMAIN']}/report-abuse")
|
||||
expect(EmailMessage.all.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue