From 463f77bb2af8518c9cc44495395f9c81d3fda944 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Wed, 7 Mar 2018 16:58:56 +0800 Subject: [PATCH] FEATURE: Add live updates for "assigned" private messages. --- ...-private-messages-assigned-archived.js.es6 | 2 +- .../user-private-messages-assigned.js.es6 | 2 +- lib/topic_assigner.rb | 16 +++++ plugin.rb | 59 +++++++++++++------ spec/integration/assign_spec.rb | 50 ++++++++++++++++ spec/lib/topic_assigner_spec.rb | 25 ++++++++ 6 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 spec/lib/topic_assigner_spec.rb diff --git a/assets/javascripts/discourse-assign/routes/user-private-messages-assigned-archived.js.es6 b/assets/javascripts/discourse-assign/routes/user-private-messages-assigned-archived.js.es6 index 8b8bcdf..e08b59e 100644 --- a/assets/javascripts/discourse-assign/routes/user-private-messages-assigned-archived.js.es6 +++ b/assets/javascripts/discourse-assign/routes/user-private-messages-assigned-archived.js.es6 @@ -1,6 +1,6 @@ import createPMRoute from "discourse/routes/build-private-messages-route"; -export default createPMRoute('assigned_archived', 'private-messages-assigned').extend({ +export default createPMRoute('assigned_archived', 'private-messages-assigned', 'assigned/archive').extend({ model() { return this.store.findFiltered("topicList", { filter: `topics/private-messages-assigned/${this.modelFor("user").get("username_lower")}`, diff --git a/assets/javascripts/discourse-assign/routes/user-private-messages-assigned.js.es6 b/assets/javascripts/discourse-assign/routes/user-private-messages-assigned.js.es6 index 7d03cdf..60bd40d 100644 --- a/assets/javascripts/discourse-assign/routes/user-private-messages-assigned.js.es6 +++ b/assets/javascripts/discourse-assign/routes/user-private-messages-assigned.js.es6 @@ -1,3 +1,3 @@ import createPMRoute from "discourse/routes/build-private-messages-route"; -export default createPMRoute('assigned', 'private-messages-assigned'); +export default createPMRoute('assigned', 'private-messages-assigned', 'assigned'); diff --git a/lib/topic_assigner.rb b/lib/topic_assigner.rb index 628d1d0..0c5d60d 100644 --- a/lib/topic_assigner.rb +++ b/lib/topic_assigner.rb @@ -112,6 +112,8 @@ SQL user_ids: staff_ids ) + publish_topic_tracking_state(@topic, assign_to.id) + if SiteSetting.assign_mailer_enabled if !@topic.muted?(assign_to) message = AssignMailer.send_assignment(assign_to.email, @topic, @assigned_by) @@ -177,6 +179,8 @@ SQL user_ids: staff_ids ) + publish_topic_tracking_state(@topic, assigned_user.id) + UserAction.where( action_type: UserAction::ASSIGNED, target_post_id: post.id @@ -202,4 +206,16 @@ SQL end end end + + private + + def publish_topic_tracking_state(topic, user_id) + if topic.private_message? + MessageBus.publish( + "/private-messages/assigned", + { topic_id: topic.id }, + user_ids: [user_id] + ) + end + end end diff --git a/plugin.rb b/plugin.rb index b203a40..1081aeb 100644 --- a/plugin.rb +++ b/plugin.rb @@ -216,30 +216,51 @@ after_initialize do end end + add_class_method(:topic_tracking_state, :publish_assigned_private_message) do |topic, user_id| + return unless topic.private_message? + + assigned_channel = "/private-messages/assigned" + + [assigned_channel, "#{assigned_channel}/archive"].each do |channel| + MessageBus.publish( + channel, + { topic_id: topic.id }, + user_ids: [user_id] + ) + end + end + on(:move_to_inbox) do |info| - if SiteSetting.unassign_on_group_archive && info[:group] - if topic = info[:topic] - if user_id = topic.custom_fields["prev_assigned_to_id"] - if user = User.find_by(id: user_id.to_i) - assigner = TopicAssigner.new(topic, Discourse.system_user) - assigner.assign(user, silent: true) - end - end - end + topic = info[:topic] + + if (assigned_id = topic.custom_fields["assigned_to_id"].to_i) == info[:user]&.id + TopicTrackingState.publish_assigned_private_message(topic, assigned_id) + end + + if SiteSetting.unassign_on_group_archive && info[:group] && + user_id = topic.custom_fields["prev_assigned_to_id"].to_i && + previous_user = User.find_by(id: user_id) + + assigner = TopicAssigner.new(topic, Discourse.system_user) + assigner.assign(previous_user, silent: true) end end on(:archive_message) do |info| - if SiteSetting.unassign_on_group_archive && info[:group] - topic = info[:topic] - if user_id = topic.custom_fields["assigned_to_id"] - if user = User.find_by(id: user_id.to_i) - topic.custom_fields["prev_assigned_to_id"] = user.id - topic.save - assigner = TopicAssigner.new(topic, Discourse.system_user) - assigner.unassign(silent: true) - end - end + topic = info[:topic] + user_id = topic.custom_fields["assigned_to_id"].to_i + + if user_id == info[:user]&.id + TopicTrackingState.publish_assigned_private_message(topic, user_id) + end + + if SiteSetting.unassign_on_group_archive && info[:group] && + user_id && assigned_user = User.find_by(id: user_id) + + topic.custom_fields["prev_assigned_to_id"] = assigned_user.id + topic.save! + assigner = TopicAssigner.new(topic, Discourse.system_user) + assigner.unassign(silent: true) end end diff --git a/spec/integration/assign_spec.rb b/spec/integration/assign_spec.rb index 0eb6d18..e322cdb 100644 --- a/spec/integration/assign_spec.rb +++ b/spec/integration/assign_spec.rb @@ -1,6 +1,10 @@ require 'rails_helper' describe 'integration tests' do + before do + SiteSetting.assign_enabled = true + end + it 'preloads data in topic list' do admin = Fabricate(:admin) post = create_post @@ -8,4 +12,50 @@ describe 'integration tests' do TopicList.preload([post.topic], list) # should not explode for now end + + describe 'for a private message' do + let(:post) { Fabricate(:private_message_post) } + let(:pm) { post.topic } + let(:user) { pm.allowed_users.first } + let(:user2) { pm.allowed_users.last } + + let(:channels) do + [ + "/private-messages/assigned", + "/private-messages/assigned/archive" + ] + end + + def assert_publish_topic_state(topic, user) + messages = MessageBus.track_publish do + yield + end + + channels.each do |channel| + message = messages.find { |message| message.channel == channel } + + expect(message.data[:topic_id]).to eq(topic.id) + expect(message.user_ids).to eq([user.id]) + end + end + + it 'publishes the right message on archive and move to inbox' do + assigner = TopicAssigner.new(pm, user) + assigner.assign(user) + + assert_publish_topic_state(pm, user) do + UserArchivedMessage.archive!(user.id, pm.reload) + end + + assert_publish_topic_state(pm, user) do + UserArchivedMessage.move_to_inbox!(user.id, pm.reload) + end + + messages = MessageBus.track_publish do + UserArchivedMessage.archive!(user2.id, pm.reload) + end + + expect(channels - messages.map(&:channel)).to eq(channels) + end + end end diff --git a/spec/lib/topic_assigner_spec.rb b/spec/lib/topic_assigner_spec.rb new file mode 100644 index 0000000..7e13d3f --- /dev/null +++ b/spec/lib/topic_assigner_spec.rb @@ -0,0 +1,25 @@ +require 'rails_helper' + +RSpec.describe TopicAssigner do + let(:pm_post) { Fabricate(:private_message_post) } + let(:pm) { pm_post.topic } + + def assert_publish_topic_state(topic, user) + message = MessageBus.track_publish("/private-messages/assigned") do + yield + end.first + + expect(message.data[:topic_id]).to eq(topic.id) + expect(message.user_ids).to eq([user.id]) + end + + describe 'assigning and unassigning private message' do + it 'should publish the right message' do + user = pm.allowed_users.first + assigner = described_class.new(pm, user) + + assert_publish_topic_state(pm, user) { assigner.assign(user) } + assert_publish_topic_state(pm, user) { assigner.unassign } + end + end +end