FEATURE: Allow selective dismissal of new and unread topics (#12976)

This PR improves the UI of bulk select so that its context is applied to the Dismiss Unread and Dismiss New buttons. Regular users (not just staff) are now able to use topic bulk selection on the /new and /unread routes to perform these dismiss actions more selectively.

For Dismiss Unread, there is a new count in the text of the button and in the modal when one or more topic is selected with the bulk select checkboxes.

For Dismiss New, there is a count in the button text, and we have added functionality to the server side to accept an array of topic ids to dismiss new for, instead of always having to dismiss all new, the same as the bulk dismiss unread functionality. To clean things up, the `DismissTopics` service has been rolled into the `TopicsBulkAction` service.

We now also show the top Dismiss/Dismiss New button based on whether the bottom one is in the viewport, not just based on the topic count.
This commit is contained in:
Martin Brennan
2021-05-26 09:38:46 +10:00
committed by GitHub
parent de0f2b9546
commit 7a79bd7da3
22 changed files with 399 additions and 292 deletions

View File

@ -2801,6 +2801,17 @@ RSpec.describe TopicsController do
}
end
it "raises an error if topic_ids is provided and it is not an array" do
put "/topics/bulk.json", params: {
topic_ids: "1", operation: operation
}
expect(response.parsed_body["errors"].first).to match(/Expecting topic_ids to contain a list/)
put "/topics/bulk.json", params: {
topic_ids: [1], operation: operation
}
expect(response.parsed_body["errors"]).to eq(nil)
end
it "respects the tracked parameter" do
# untracked topic
CategoryUser.set_notification_level_for_category(user,
@ -2975,7 +2986,7 @@ RSpec.describe TopicsController do
it 'dismisses topics for main category and subcategories' do
sign_in(user)
TopicTrackingState.expects(:publish_dismiss_new).with(user.id, topic_ids: [subcategory_topic.id, category_topic.id])
TopicTrackingState.expects(:publish_dismiss_new).with(user.id, topic_ids: [category_topic.id, subcategory_topic.id])
put "/topics/reset-new.json?category_id=#{category.id}&include_subcategories=true"
@ -3011,6 +3022,69 @@ RSpec.describe TopicsController do
expect(DismissedTopicUser.where(user_id: user.id).pluck(:topic_id)).to eq([tag_and_category_topic.id])
end
end
context "specific topics" do
fab!(:topic2) { Fabricate(:topic) }
fab!(:topic3) { Fabricate(:topic) }
it "updates the `new_since` date" do
sign_in(user)
old_date = 2.years.ago
user.user_stat.update_column(:new_since, old_date)
user.update_column(:created_at, old_date)
TopicTrackingState.expects(:publish_dismiss_new).with(user.id, topic_ids: [topic2.id, topic3.id]).at_least_once
put "/topics/reset-new.json", { params: { topic_ids: [topic2.id, topic3.id] } }
expect(response.status).to eq(200)
user.reload
expect(user.user_stat.new_since.to_date).not_to eq(old_date.to_date)
expect(DismissedTopicUser.where(user_id: user.id).pluck(:topic_id)).to match_array([topic2.id, topic3.id])
end
it "raises an error if topic_ids is provided and it is not an array" do
sign_in(user)
put "/topics/reset-new.json", params: { topic_ids: topic2.id }
expect(response.parsed_body["errors"].first).to match(/Expecting topic_ids to contain a list/)
put "/topics/reset-new.json", params: { topic_ids: [topic2.id] }
expect(response.parsed_body["errors"]).to eq(nil)
end
describe "when tracked param is true" do
it "does not update user_stat.new_since and does not dismiss untracked topics" do
sign_in(user)
old_date = 2.years.ago
user.user_stat.update_column(:new_since, old_date)
put "/topics/reset-new.json?tracked=true", { params: { topic_ids: [topic2.id, topic3.id] } }
expect(response.status).to eq(200)
user.reload
expect(user.user_stat.new_since.to_date).to eq(old_date.to_date)
expect(DismissedTopicUser.where(user_id: user.id).pluck(:topic_id)).to be_empty
end
it "creates topic user records for each unread topic" do
sign_in(user)
user.user_stat.update_column(:new_since, 2.years.ago)
tracked_category = Fabricate(:category)
CategoryUser.set_notification_level_for_category(user,
NotificationLevels.all[:tracking],
tracked_category.id)
tracked_topic = create_post.topic
tracked_topic.update!(category_id: tracked_category.id)
topic2.update!(category_id: tracked_category.id)
create_post # This is a new post, but is not tracked so a record will not be created for it
expect do
put "/topics/reset-new.json?tracked=true", { params: { topic_ids: [tracked_topic.id, topic2.id, topic3.id] } }
end.to change { DismissedTopicUser.where(user_id: user.id).count }.by(2)
expect(DismissedTopicUser.where(user_id: user.id).pluck(:topic_id)).to match_array([tracked_topic.id, topic2.id])
end
end
end
end
describe '#feature_stats' do