DEV: Serialize categories in topic lists (#23597)

At this moment, this feature is under a site setting named
lazy_load_categories.

In the future, categories will no longer be preloaded through site data.
This commit add information about categories in topic list and ensures
that data is used to display topic list items.

Parent categories are serialized too because they are necessary to
render {{category-link}}.
This commit is contained in:
Bianca Nenciu 2023-10-17 19:06:01 +03:00 committed by GitHub
parent 5e6c63901f
commit c95ffb98ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 1 deletions

View File

@ -5,6 +5,7 @@ import { isEmpty } from "@ember/utils";
import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax";
import RestModel from "discourse/models/rest";
import Site from "discourse/models/site";
import User from "discourse/models/user";
import deprecated from "discourse-common/lib/deprecated";
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
@ -168,6 +169,12 @@ TopicList.reopenClass({
const users = extractByKey(result.users, User);
const groups = extractByKey(result.primary_groups, EmberObject);
if (result.topic_list.categories) {
result.topic_list.categories.forEach((c) => {
Site.current().updateCategory(c);
});
}
return result.topic_list[listKey].map((t) => {
t.posters.forEach((p) => {
p.user = users[p.user_id];

View File

@ -76,6 +76,10 @@ class TopicList
@topics ||= load_topics
end
def categories
@categories ||= topics.map { |t| [t.category, t.category.parent_category] }.uniq.flatten.compact
end
def load_topics
@topics = @topics_input
@ -128,7 +132,12 @@ class TopicList
ft.topic_list = self
end
topic_preloader_associations = [:image_upload, { topic_thumbnails: :optimized_image }]
topic_preloader_associations = [
:image_upload,
{ topic_thumbnails: :optimized_image },
{ category: :parent_category },
]
topic_preloader_associations.concat(DiscoursePluginRegistry.topic_preloader_associations.to_a)
ActiveRecord::Associations::Preloader.new(

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
class TopicCategorySerializer < ApplicationSerializer
attributes :id,
:name,
:color,
:text_color,
:slug,
:description_text,
:read_restricted,
:parent_category_id
def include_parent_category_id?
parent_category_id
end
def name
if object.uncategorized?
I18n.t("uncategorized_category_name", locale: SiteSetting.default_locale)
else
object.name
end
end
def description_text
if object.uncategorized?
I18n.t("category.uncategorized_description", locale: SiteSetting.default_locale)
else
object.description_text
end
end
end

View File

@ -12,6 +12,7 @@ class TopicListSerializer < ApplicationSerializer
has_many :topics, serializer: TopicListItemSerializer, embed: :objects
has_many :shared_drafts, serializer: TopicListItemSerializer, embed: :objects
has_many :tags, serializer: TagSerializer, embed: :objects
has_many :categories, serializer: TopicCategorySerializer, embed: :objects
def can_create_topic
scope.can_create?(Topic)
@ -36,4 +37,8 @@ class TopicListSerializer < ApplicationSerializer
def include_tags?
SiteSetting.tagging_enabled && object.tags.present?
end
def include_categories?
SiteSetting.lazy_load_categories
end
end

View File

@ -2174,6 +2174,9 @@ developer:
instrument_gc_stat_per_request:
default: false
hidden: true
lazy_load_categories:
default: false
hidden: true
navigation:
navigation_menu:

View File

@ -223,6 +223,38 @@ RSpec.describe ListController do
expect(response.body).not_to include(restricted_tag.name)
end
end
context "with lazy_load_categories" do
fab!(:category) { Fabricate(:category) }
fab!(:subcategory) { Fabricate(:category, parent_category: category) }
before { topic.update!(category: subcategory) }
it "returns categories and parent categories if true" do
SiteSetting.lazy_load_categories = true
get "/latest.json"
expect(response.status).to eq(200)
expect(response.parsed_body["topic_list"]["topics"].length).to eq(1)
expect(response.parsed_body["topic_list"]["topics"][0]["id"]).to eq(topic.id)
expect(response.parsed_body["topic_list"]["categories"].length).to eq(2)
expect(
response.parsed_body["topic_list"]["categories"].map { |c| c["id"] },
).to contain_exactly(category.id, subcategory.id)
end
it "does not return categories if not true" do
SiteSetting.lazy_load_categories = false
get "/latest.json"
expect(response.status).to eq(200)
expect(response.parsed_body["topic_list"]["topics"].length).to eq(1)
expect(response.parsed_body["topic_list"]["topics"][0]["id"]).to eq(topic.id)
expect(response.parsed_body["topic_list"]["categories"]).to eq(nil)
end
end
end
describe "categories and X" do