From 48e2b984fb2b472fad8a90d70934777f75628fdc Mon Sep 17 00:00:00 2001 From: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com> Date: Wed, 17 Aug 2022 11:51:02 -0500 Subject: [PATCH] DEV: Filter topics by tag for categories (#17953) * DEV: Filter topics by tag for categories and children --- app/controllers/categories_controller.rb | 3 +- app/models/category_list.rb | 7 ++- spec/requests/categories_controller_spec.rb | 65 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 7ece89fa45b..2ac24151601 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -30,7 +30,8 @@ class CategoriesController < ApplicationController is_homepage: current_homepage == "categories", parent_category_id: params[:parent_category_id], include_topics: include_topics(parent_category), - include_subcategories: include_subcategories + include_subcategories: include_subcategories, + tag: params[:tag] } @category_list = CategoryList.new(guardian, category_options) diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 2ed506273a3..743a4cc4466 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -64,17 +64,18 @@ class CategoryList @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id)).includes(:shared_draft, :category) + @all_topics = @all_topics.joins(:tags).where(tags: { name: @options[:tag] }) if @options[:tag].present? + if @guardian.authenticated? @all_topics = @all_topics .joins("LEFT JOIN topic_users tu ON topics.id = tu.topic_id AND tu.user_id = #{@guardian.user.id.to_i}") .where('COALESCE(tu.notification_level,1) > :muted', muted: TopicUser.notification_levels[:muted]) end - @all_topics = TopicQuery.remove_muted_tags(@all_topics, @guardian.user) - @all_topics = @all_topics.includes(:last_poster) if @options[:include_topics] + @all_topics = TopicQuery.remove_muted_tags(@all_topics, @guardian.user).includes(:last_poster) @all_topics.each do |t| # hint for the serializer - t.include_last_poster = true if @options[:include_topics] + t.include_last_poster = true t.dismissed = dismissed_topic?(t) @topics_by_id[t.id] = t end diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb index 3fa4a8d7435..c7dd184f741 100644 --- a/spec/requests/categories_controller_spec.rb +++ b/spec/requests/categories_controller_spec.rb @@ -139,6 +139,71 @@ RSpec.describe CategoriesController do expect(subsubcategory_response["topics"].map { |c| c['id'] }).to contain_exactly(topic3.id) end + describe 'topics filtered by tag for categories when requested' do + fab!(:tag) { Fabricate(:tag, name: "test-tag") } + fab!(:tag_2) { Fabricate(:tag, name: "second-test-tag") } + let(:topics_with_filter_tag) { [] } + + before do + SiteSetting.max_category_nesting = 3 + end + + it 'includes filtered topics for categories' do + 2.times do |i| + topics_with_filter_tag << Fabricate(:topic, category: category, tags: [tag]) + Fabricate(:topic, category: category, tags: [tag_2]) + end + CategoryFeaturedTopic.feature_topics + + get "/categories.json?tag=#{tag.name}&include_topics=true" + expect(response.status).to eq(200) + + category_list = response.parsed_body["category_list"] + category_response = category_list["categories"].find { |c| c["id"] == category.id } + + expect(category_response["topics"].map { |c| c['id'] }).to contain_exactly(*topics_with_filter_tag.map(&:id)) + end + + it 'includes filtered topics for subcategories' do + subcategory = Fabricate(:category, user: admin, parent_category: category) + + 2.times do |i| + topics_with_filter_tag << Fabricate(:topic, category: subcategory, tags: [tag]) + Fabricate(:topic, category: subcategory, tags: [tag_2]) + end + CategoryFeaturedTopic.feature_topics + + get "/categories.json?tag=#{tag.name}&include_subcategories=true&include_topics=true" + expect(response.status).to eq(200) + + category_list = response.parsed_body["category_list"] + category_response = category_list["categories"].find { |c| c["id"] == category.id } + subcategory_response = category_response["subcategory_list"][0] + + expect(subcategory_response["topics"].map { |c| c['id'] }).to contain_exactly(*topics_with_filter_tag.map(&:id)) + end + + it 'includes filtered topics for subsubcategories' do + subcategory = Fabricate(:category, user: admin, parent_category: category) + subsubcategory = Fabricate(:category, user: admin, parent_category: subcategory) + + 2.times do |i| + topics_with_filter_tag << Fabricate(:topic, category: subsubcategory, tags: [tag]) + Fabricate(:topic, category: subsubcategory, tags: [tag_2]) + end + CategoryFeaturedTopic.feature_topics + + get "/categories.json?tag=#{tag.name}&include_subcategories=true&include_topics=true" + expect(response.status).to eq(200) + + category_list = response.parsed_body["category_list"] + category_response = category_list["categories"].find { |c| c["id"] == category.id } + subsubcategory_response = category_response["subcategory_list"][0]["subcategory_list"][0] + + expect(subsubcategory_response["topics"].map { |c| c['id'] }).to contain_exactly(*topics_with_filter_tag.map(&:id)) + end + end + describe 'categories and latest topics - ordered by created date' do fab!(:category) { Fabricate(:category) } fab!(:topic1) { Fabricate(:topic, category: category, created_at: 5.days.ago, updated_at: Time.now, bumped_at: Time.now) }