From a024e26d2d91781c76d050dea814fa263f21641d Mon Sep 17 00:00:00 2001 From: zogstrip Date: Tue, 18 Mar 2025 16:49:27 +0100 Subject: [PATCH] FEATURE: add "assigned:" filter (in the /filter page) The "assigned:" filter was already available in the advanced search but it wasn't in the /filter page. This commit adds that filter allowing anyone to filter topics assigned to either a specific user (using their username) or to a specific group (using its name). --- plugin.rb | 58 ++++++++++++++++----------- spec/requests/list_controller_spec.rb | 38 ++++++++++++++++++ 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/plugin.rb b/plugin.rb index 8bf76ea..e87a217 100644 --- a/plugin.rb +++ b/plugin.rb @@ -887,37 +887,47 @@ after_initialize do Assignment.active_for_group(group).destroy_all end - register_search_advanced_filter(/in:assigned/) do |posts| - posts.where(<<~SQL) if @guardian.can_assign? - topics.id IN ( - SELECT a.topic_id FROM assignments a WHERE a.active - ) + add_filter_custom_filter("assigned") do |scope, filter_values| + user_or_group_name = filter_values.compact.first + + return scope if user_or_group_name.blank? + + if user_id = User.find_by_username(user_or_group_name)&.id + scope.where(<<~SQL, user_id) + topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'User' AND a.active) SQL + elsif group_id = Group.find_by(name: user_or_group_name)&.id + scope.where(<<~SQL, group_id) + topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'Group' AND a.active) + SQL + else + scope + end + end + + register_search_advanced_filter(/in:assigned/) do |posts| + return if !@guardian.can_assign? + + posts.where("topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.active)") end register_search_advanced_filter(/in:unassigned/) do |posts| - posts.where(<<~SQL) if @guardian.can_assign? - topics.id NOT IN ( - SELECT a.topic_id FROM assignments a WHERE a.active - ) - SQL + return if !@guardian.can_assign? + + posts.where("topics.id NOT IN (SELECT a.topic_id FROM assignments a WHERE a.active)") end register_search_advanced_filter(/assigned:(.+)$/) do |posts, match| - if @guardian.can_assign? - if user_id = User.find_by_username(match)&.id - posts.where(<<~SQL, user_id) - topics.id IN ( - SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'User' AND a.active - ) - SQL - elsif group_id = Group.find_by_name(match)&.id - posts.where(<<~SQL, group_id) - topics.id IN ( - SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'Group' AND a.active - ) - SQL - end + return if !@guardian.can_assign? || match.blank? + + if user_id = User.find_by_username(match)&.id + posts.where(<<~SQL, user_id) + topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'User' AND a.active) + SQL + elsif group_id = Group.find_by(name: match)&.id + posts.where(<<~SQL, group_id) + topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'Group' AND a.active) + SQL end end diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb index 319635f..d09ba19 100644 --- a/spec/requests/list_controller_spec.rb +++ b/spec/requests/list_controller_spec.rb @@ -355,4 +355,42 @@ describe ListController do expect(JSON.parse(response.body)["topic_list"]["topics"].map { |t| t["id"] }).to eq([pm.id]) end end + + describe "#filter" do + include_context "with group that is allowed to assign" + + fab!(:group) { Fabricate(:group, assignable_level: Group::ALIAS_LEVELS[:mods_and_admins]) } + + fab!(:topic_1) { Fabricate(:topic) } + fab!(:topic_2) { Fabricate(:topic) } + fab!(:topic_3) { Fabricate(:topic) } + + fab!(:post_1) { Fabricate(:post, topic: topic_1) } + fab!(:post_2) { Fabricate(:post, topic: topic_2) } + fab!(:post_3) { Fabricate(:post, topic: topic_3) } + + before do + sign_in(admin) + end + + it "filters topics by assigned user" do + add_to_assign_allowed_group(user) + + Assigner.new(topic_1, admin).assign(user) + + get "/filter", params: { q: "assigned:#{user.username_lower}", format: :json } + + expect(response.status).to eq(200) + expect(response.parsed_body.dig("topic_list", "topics").map { _1["id"] }).to contain_exactly(topic_1.id) + end + + it "filters topics by assigned group" do + Assigner.new(topic_2, admin).assign(group) + + get "/filter", params: { q: "assigned:#{group.name}", format: :json } + + expect(response.status).to eq(200) + expect(response.parsed_body.dig("topic_list", "topics").map { _1["id"] }).to contain_exactly(topic_2.id) + end + end end