mirror of
https://github.com/discourse/discourse.git
synced 2024-11-27 09:50:23 +08:00
FIX: if user undos like, and relikes notify
FEATURE: roll up likes for notify on all likes
This commit is contained in:
parent
71911a4c67
commit
8b1772ac0f
|
@ -1,3 +1,4 @@
|
||||||
|
const LIKED_TYPE = 5;
|
||||||
const INVITED_TYPE = 8;
|
const INVITED_TYPE = 8;
|
||||||
const GROUP_SUMMARY_TYPE = 16;
|
const GROUP_SUMMARY_TYPE = 16;
|
||||||
|
|
||||||
|
@ -80,7 +81,16 @@ export default Ember.Component.extend({
|
||||||
const count = notification.get('data.inbox_count');
|
const count = notification.get('data.inbox_count');
|
||||||
const group_name = notification.get('data.group_name');
|
const group_name = notification.get('data.group_name');
|
||||||
text = I18n.t(this.get('scope'), {count, group_name});
|
text = I18n.t(this.get('scope'), {count, group_name});
|
||||||
} else {
|
} else if (notification.get('notification_type') === LIKED_TYPE && notification.get("data.count") > 1) {
|
||||||
|
const count = notification.get('data.count') - 2;
|
||||||
|
const username2 = notification.get('data.username2');
|
||||||
|
if (count===0) {
|
||||||
|
text = I18n.t('notifications.liked_2', {description, username, username2});
|
||||||
|
} else {
|
||||||
|
text = I18n.t('notifications.liked_many', {description, username, username2, count});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
text = I18n.t(this.get('scope'), {description, username});
|
text = I18n.t(this.get('scope'), {description, username});
|
||||||
}
|
}
|
||||||
text = Discourse.Emoji.unescape(text);
|
text = Discourse.Emoji.unescape(text);
|
||||||
|
|
|
@ -147,10 +147,10 @@ SQL
|
||||||
# so callback is called
|
# so callback is called
|
||||||
action.save
|
action.save
|
||||||
action.add_moderator_post_if_needed(moderator, :agreed, delete_post)
|
action.add_moderator_post_if_needed(moderator, :agreed, delete_post)
|
||||||
@trigger_spam = true if action.post_action_type_id == PostActionType.types[:spam]
|
trigger_spam = true if action.post_action_type_id == PostActionType.types[:spam]
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscourseEvent.trigger(:confirmed_spam_post, post) if @trigger_spam
|
DiscourseEvent.trigger(:confirmed_spam_post, post) if trigger_spam
|
||||||
|
|
||||||
update_flagged_posts_count
|
update_flagged_posts_count
|
||||||
end
|
end
|
||||||
|
@ -272,6 +272,7 @@ SQL
|
||||||
post_action.recover!
|
post_action.recover!
|
||||||
action_attrs.each { |attr, val| post_action.send("#{attr}=", val) }
|
action_attrs.each { |attr, val| post_action.send("#{attr}=", val) }
|
||||||
post_action.save
|
post_action.save
|
||||||
|
PostAlertObserver.after_create_post_action(post_action)
|
||||||
else
|
else
|
||||||
post_action = create(where_attrs.merge(action_attrs))
|
post_action = create(where_attrs.merge(action_attrs))
|
||||||
if post_action && post_action.errors.count == 0
|
if post_action && post_action.errors.count == 0
|
||||||
|
@ -480,7 +481,7 @@ SQL
|
||||||
elsif PostActionType.auto_action_flag_types.include?(post_action_type) &&
|
elsif PostActionType.auto_action_flag_types.include?(post_action_type) &&
|
||||||
SiteSetting.flags_required_to_hide_post > 0
|
SiteSetting.flags_required_to_hide_post > 0
|
||||||
|
|
||||||
old_flags, new_flags = PostAction.flag_counts_for(post.id)
|
_old_flags, new_flags = PostAction.flag_counts_for(post.id)
|
||||||
|
|
||||||
if new_flags >= SiteSetting.flags_required_to_hide_post
|
if new_flags >= SiteSetting.flags_required_to_hide_post
|
||||||
hide_post!(post, post_action_type, guess_hide_reason(post))
|
hide_post!(post, post_action_type, guess_hide_reason(post))
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
class PostAlertObserver < ActiveRecord::Observer
|
class PostAlertObserver < ActiveRecord::Observer
|
||||||
observe :post_action, :post_revision
|
observe :post_action, :post_revision
|
||||||
|
|
||||||
def alerter
|
def self.alerter
|
||||||
@alerter ||= PostAlerter.new
|
@alerter ||= PostAlerter.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def alerter
|
||||||
|
self.class.alerter
|
||||||
|
end
|
||||||
|
|
||||||
# Dispatch to an after_save_#{class_name} method
|
# Dispatch to an after_save_#{class_name} method
|
||||||
def after_save(model)
|
def after_save(model)
|
||||||
method_name = callback_for('after_save', model)
|
method_name = callback_for('after_save', model)
|
||||||
|
@ -17,13 +21,60 @@ class PostAlertObserver < ActiveRecord::Observer
|
||||||
send(method_name, model) if respond_to?(method_name)
|
send(method_name, model) if respond_to?(method_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def refresh_like_notification(post, read)
|
||||||
|
return unless post && post.user_id
|
||||||
|
|
||||||
|
usernames = post.post_actions.where(post_action_type_id: PostActionType.types[:like])
|
||||||
|
.joins(:user)
|
||||||
|
.order('post_actions.created_at desc')
|
||||||
|
.where('post_actions.created_at > ?', 1.day.ago)
|
||||||
|
.pluck(:username)
|
||||||
|
|
||||||
|
if usernames.length > 0
|
||||||
|
data = {
|
||||||
|
topic_title: post.topic.title,
|
||||||
|
username: usernames[0],
|
||||||
|
display_username: usernames[0],
|
||||||
|
username2: usernames[1],
|
||||||
|
count: usernames.length
|
||||||
|
}
|
||||||
|
Notification.create(
|
||||||
|
notification_type: Notification.types[:liked],
|
||||||
|
topic_id: post.topic_id,
|
||||||
|
post_number: post.post_number,
|
||||||
|
user_id: post.user_id,
|
||||||
|
read: read,
|
||||||
|
data: data.to_json
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def after_save_post_action(post_action)
|
def after_save_post_action(post_action)
|
||||||
# We only care about deleting post actions for now
|
# We only care about deleting post actions for now
|
||||||
return if post_action.deleted_at.blank?
|
return if post_action.deleted_at.blank?
|
||||||
Notification.where(post_action_id: post_action.id).each(&:destroy)
|
|
||||||
|
if post_action.post_action_type_id == PostActionType.types[:like] && post_action.post
|
||||||
|
|
||||||
|
read = true
|
||||||
|
|
||||||
|
Notification.where(
|
||||||
|
topic_id: post_action.post.topic_id,
|
||||||
|
user_id: post_action.post.user_id,
|
||||||
|
post_number: post_action.post.post_number,
|
||||||
|
notification_type: Notification.types[:liked]
|
||||||
|
).each do |notification|
|
||||||
|
read = false unless notification.read
|
||||||
|
notification.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
refresh_like_notification(post_action.post, read)
|
||||||
|
else
|
||||||
|
# not using destroy_all cause we want stuff to trigger
|
||||||
|
Notification.where(post_action_id: post_action.id).each(&:destroy)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_create_post_action(post_action)
|
def self.after_create_post_action(post_action)
|
||||||
# We only notify on likes for now
|
# We only notify on likes for now
|
||||||
return unless post_action.is_like?
|
return unless post_action.is_like?
|
||||||
|
|
||||||
|
@ -40,6 +91,10 @@ class PostAlertObserver < ActiveRecord::Observer
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_create_post_action(post_action)
|
||||||
|
self.class.after_create_post_action(post_action)
|
||||||
|
end
|
||||||
|
|
||||||
def after_create_post_revision(post_revision)
|
def after_create_post_revision(post_revision)
|
||||||
post = post_revision.post
|
post = post_revision.post
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,19 @@ class PostAlerter
|
||||||
|
|
||||||
return if existing_notification && !should_notify_previous?(user, existing_notification, opts)
|
return if existing_notification && !should_notify_previous?(user, existing_notification, opts)
|
||||||
|
|
||||||
|
notification_data = {}
|
||||||
|
|
||||||
|
if existing_notification &&
|
||||||
|
existing_notification.created_at > 1.day.ago &&
|
||||||
|
user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:always]
|
||||||
|
|
||||||
|
data = existing_notification.data_hash
|
||||||
|
notification_data["username2"] = data["display_username"]
|
||||||
|
notification_data["count"] = (data["count"] || 1).to_i + 1
|
||||||
|
# don't use destroy so we don't trigger a notification count refresh
|
||||||
|
Notification.where(id: existing_notification.id).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
collapsed = false
|
collapsed = false
|
||||||
|
|
||||||
if type == Notification.types[:replied] || type == Notification.types[:posted]
|
if type == Notification.types[:replied] || type == Notification.types[:posted]
|
||||||
|
@ -287,13 +300,13 @@ class PostAlerter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
notification_data = {
|
notification_data.merge!({
|
||||||
topic_title: topic_title,
|
topic_title: topic_title,
|
||||||
original_post_id: original_post.id,
|
original_post_id: original_post.id,
|
||||||
original_post_type: original_post.post_type,
|
original_post_type: original_post.post_type,
|
||||||
original_username: original_username,
|
original_username: original_username,
|
||||||
display_username: opts[:display_username] || post.user.username
|
display_username: opts[:display_username] || post.user.username
|
||||||
}
|
})
|
||||||
|
|
||||||
if group = opts[:group]
|
if group = opts[:group]
|
||||||
notification_data[:group_id] = group.id
|
notification_data[:group_id] = group.id
|
||||||
|
|
|
@ -1014,6 +1014,10 @@ en:
|
||||||
posted: "<i title='replied' class='fa fa-reply'></i><p><span>{{username}}</span> {{description}}</p>"
|
posted: "<i title='replied' class='fa fa-reply'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
edited: "<i title='edited' class='fa fa-pencil'></i><p><span>{{username}}</span> {{description}}</p>"
|
edited: "<i title='edited' class='fa fa-pencil'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
liked: "<i title='liked' class='fa fa-heart'></i><p><span>{{username}}</span> {{description}}</p>"
|
liked: "<i title='liked' class='fa fa-heart'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
|
liked_2: "<i title='liked' class='fa fa-heart'></i><p><span>{{username}}, {{username2}}</span> {{description}}</p>"
|
||||||
|
liked_many:
|
||||||
|
one: "<i title='liked' class='fa fa-heart'></i><p><span>{{username}}, {{username2}} and 1 other</span> {{description}}</p>"
|
||||||
|
other: "<i title='liked' class='fa fa-heart'></i><p><span>{{username}}, {{username2}} and {{count}} others</span> {{description}}</p>"
|
||||||
private_message: "<i title='private message' class='fa fa-envelope-o'></i><p><span>{{username}}</span> {{description}}</p>"
|
private_message: "<i title='private message' class='fa fa-envelope-o'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
invited_to_private_message: "<i title='private message' class='fa fa-envelope-o'></i><p><span>{{username}}</span> {{description}}</p>"
|
invited_to_private_message: "<i title='private message' class='fa fa-envelope-o'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
invited_to_topic: "<i title='invited to topic' class='fa fa-hand-o-right'></i><p><span>{{username}}</span> {{description}}</p>"
|
invited_to_topic: "<i title='invited to topic' class='fa fa-hand-o-right'></i><p><span>{{username}}</span> {{description}}</p>"
|
||||||
|
|
|
@ -21,11 +21,8 @@ describe PostAlertObserver do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when removing a liked post' do
|
context 'when removing a liked post' do
|
||||||
before do
|
|
||||||
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes a notification' do
|
it 'removes a notification' do
|
||||||
|
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
||||||
expect {
|
expect {
|
||||||
PostAction.remove_act(evil_trout, post, PostActionType.types[:like])
|
PostAction.remove_act(evil_trout, post, PostActionType.types[:like])
|
||||||
}.to change(Notification, :count).by(-1)
|
}.to change(Notification, :count).by(-1)
|
||||||
|
|
|
@ -50,12 +50,27 @@ describe PostAlerter do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'likes' do
|
context 'likes' do
|
||||||
|
|
||||||
|
it 'notifies on likes after an undo' do
|
||||||
|
ActiveRecord::Base.observers.enable :all
|
||||||
|
|
||||||
|
post = Fabricate(:post, raw: 'I love waffles')
|
||||||
|
|
||||||
|
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
||||||
|
PostAction.remove_act(evil_trout, post, PostActionType.types[:like])
|
||||||
|
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
||||||
|
|
||||||
|
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
it 'notifies on likes correctly' do
|
it 'notifies on likes correctly' do
|
||||||
ActiveRecord::Base.observers.enable :all
|
ActiveRecord::Base.observers.enable :all
|
||||||
|
|
||||||
post = Fabricate(:post, raw: 'I love waffles')
|
post = Fabricate(:post, raw: 'I love waffles')
|
||||||
|
|
||||||
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
PostAction.act(evil_trout, post, PostActionType.types[:like])
|
||||||
PostAction.act(Fabricate(:admin), post, PostActionType.types[:like])
|
admin = Fabricate(:admin)
|
||||||
|
PostAction.act(admin, post, PostActionType.types[:like])
|
||||||
|
|
||||||
# one like
|
# one like
|
||||||
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(1)
|
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(1)
|
||||||
|
@ -66,8 +81,28 @@ describe PostAlerter do
|
||||||
|
|
||||||
admin2 = Fabricate(:admin)
|
admin2 = Fabricate(:admin)
|
||||||
PostAction.act(admin2, post, PostActionType.types[:like])
|
PostAction.act(admin2, post, PostActionType.types[:like])
|
||||||
# two likes one edit
|
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(1)
|
||||||
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(2)
|
|
||||||
|
# adds info to the notification
|
||||||
|
notification = Notification.find_by(post_number: 1,
|
||||||
|
topic_id: post.topic_id)
|
||||||
|
|
||||||
|
|
||||||
|
expect(notification.data_hash["count"].to_i).to eq(2)
|
||||||
|
expect(notification.data_hash["username2"]).to eq(evil_trout.username)
|
||||||
|
|
||||||
|
# this is a tricky thing ... removing a like should fix up the notifications
|
||||||
|
PostAction.remove_act(evil_trout, post, PostActionType.types[:like])
|
||||||
|
|
||||||
|
# rebuilds the missing notification
|
||||||
|
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(1)
|
||||||
|
notification = Notification.find_by(post_number: 1,
|
||||||
|
topic_id: post.topic_id)
|
||||||
|
|
||||||
|
expect(notification.data_hash["count"]).to eq(2)
|
||||||
|
expect(notification.data_hash["username"]).to eq(admin2.username)
|
||||||
|
expect(notification.data_hash["username2"]).to eq(admin.username)
|
||||||
|
|
||||||
|
|
||||||
post.user.user_option.update_columns(like_notification_frequency:
|
post.user.user_option.update_columns(like_notification_frequency:
|
||||||
UserOption.like_notification_frequency_type[:first_time_and_daily])
|
UserOption.like_notification_frequency_type[:first_time_and_daily])
|
||||||
|
@ -82,7 +117,7 @@ describe PostAlerter do
|
||||||
end
|
end
|
||||||
|
|
||||||
# first happend within the same day, no need to notify
|
# first happend within the same day, no need to notify
|
||||||
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(3)
|
expect(Notification.count(post_number: 1, topic_id: post.topic_id)).to eq(2)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user