FEATURE: Create notifications on wiki edits for watching users.

* Moves creation of notification into background job.
This commit is contained in:
Guo Xiang Tan 2019-05-08 15:18:56 +08:00
parent 46ea69a73c
commit 405ba00c08
5 changed files with 127 additions and 13 deletions

View File

@ -0,0 +1,20 @@
module Jobs
class NotifyPostRevision < Jobs::Base
def execute(args)
user = User.find_by(id: args[:user_id])
raise Discourse::InvalidParameters.new(:user_id) unless user
post_revision = PostRevision.find_by(id: args[:post_revision_id])
raise Discourse::InvalidParameters.new(:post_revision_id) unless post_revision
PostActionNotifier.alerter.create_notification(
user,
Notification.types[:edited],
post_revision.post,
display_username: post_revision.user.username,
acting_user_id: post_revision.try(:user_id),
revision_number: post_revision.number
)
end
end
end

View File

@ -7,11 +7,19 @@ class TopicUser < ActiveRecord::Base
# used for serialization
attr_accessor :post_action_data
scope :tracking, lambda { |topic_id|
scope :level, lambda { |topic_id, level|
where(topic_id: topic_id)
.where("COALESCE(topic_users.notification_level, :regular) >= :tracking",
.where("COALESCE(topic_users.notification_level, :regular) >= :level",
regular: TopicUser.notification_levels[:regular],
tracking: TopicUser.notification_levels[:tracking])
level: TopicUser.notification_levels[level])
}
scope :tracking, lambda { |topic_id|
level(topic_id, :tracking)
}
scope :watching, lambda { |topic_id|
level(topic_id, :watching)
}
# Class methods

View File

@ -93,21 +93,31 @@ class PostActionNotifier
return unless post
return if post_revision.user.blank?
return if post_revision.user_id == post.user_id
return if post.topic.blank?
return if post.topic.private_message?
return if SiteSetting.disable_edit_notifications && post_revision.user_id == Discourse::SYSTEM_USER_ID
alerter.create_notification(
post.user,
Notification.types[:edited],
post,
display_username: post_revision.user.username,
acting_user_id: post_revision.try(:user_id),
revision_number: post_revision.number
if post_revision.user_id != post.user_id
Jobs.enqueue(:notify_post_revision,
user_id: post.user_id,
post_revision_id: post_revision.id
)
end
if post.wiki && post.is_first_post?
TopicUser.watching(post.topic_id)
.where.not(user_id: post_revision.user_id)
.where(topic: post.topic)
.find_each do |topic_user|
Jobs.enqueue(:notify_post_revision,
user_id: topic_user.user_id,
post_revision_id: post_revision.id
)
end
end
end
def self.after_post_unhide(post, flaggers)
return if @disabled || post.last_editor.blank? || flaggers.blank?

20
notify_post_revision.rb Normal file
View File

@ -0,0 +1,20 @@
module Jobs
class NotifyPostRevision < Jobs::Base
def execute(args)
user = User.find_by(id: args[:user_id])
raise Discourse::InvalidParameters.new(:user_id) unless user
post_revision = PostRevision.find_by(id: args[:post_revision_id])
raise Discourse::InvalidParameters.new(:post_revision_id) unless post_revision
PostActionNotifier.alerter.create_notification(
user,
Notification.types[:edited],
post_revision.post,
display_username: post_revision.user.username,
acting_user_id: post_revision&.user_id,
revision_number: post_revision.number
)
end
end
end

View File

@ -6,6 +6,7 @@ describe PostActionNotifier do
before do
PostActionNotifier.enable
Jobs.run_immediately!
end
fab!(:evil_trout) { Fabricate(:evil_trout) }
@ -15,7 +16,62 @@ describe PostActionNotifier do
it 'notifies a user of the revision' do
expect {
post.revise(evil_trout, raw: "world is the new body of the message")
}.to change(post.user.notifications, :count).by(1)
}.to change { post.reload.user.notifications.count }.by(1)
end
it 'notifies watching users of revision when post is wiki-ed and first post in topic' do
SiteSetting.editing_grace_period_max_diff = 1
post.update!(wiki: true)
user = post.user
user2 = Fabricate(:user)
user3 = Fabricate(:user)
TopicUser.change(user2.id, post.topic,
notification_level: TopicUser.notification_levels[:watching]
)
TopicUser.change(user3.id, post.topic,
notification_level: TopicUser.notification_levels[:tracking]
)
expect do
post.revise(Fabricate(:user), raw: "I made some changes to the wiki!")
end.to change { Notification.count }.by(2)
edited_notification_type = Notification.types[:edited]
expect(Notification.exists?(
user: user,
notification_type: edited_notification_type
)).to eq(true)
expect(Notification.exists?(
user: user2,
notification_type: edited_notification_type
)).to eq(true)
expect do
post.revise(user, raw: "I made some changes to the wiki again!")
end.to change {
Notification.where(notification_type: edited_notification_type).count
}.by(1)
expect(Notification.where(
user: user2,
notification_type: edited_notification_type
).count).to eq(2)
expect do
post.revise(user2, raw: "I changed the wiki totally")
end.to change {
Notification.where(notification_type: edited_notification_type).count
}.by(1)
expect(Notification.where(
user: user,
notification_type: edited_notification_type
).count).to eq(2)
end
it 'stores the revision number with the notification' do