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:
parent
5e6c63901f
commit
c95ffb98ef
|
@ -5,6 +5,7 @@ import { isEmpty } from "@ember/utils";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import RestModel from "discourse/models/rest";
|
import RestModel from "discourse/models/rest";
|
||||||
|
import Site from "discourse/models/site";
|
||||||
import User from "discourse/models/user";
|
import User from "discourse/models/user";
|
||||||
import deprecated from "discourse-common/lib/deprecated";
|
import deprecated from "discourse-common/lib/deprecated";
|
||||||
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
|
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
|
||||||
|
@ -168,6 +169,12 @@ TopicList.reopenClass({
|
||||||
const users = extractByKey(result.users, User);
|
const users = extractByKey(result.users, User);
|
||||||
const groups = extractByKey(result.primary_groups, EmberObject);
|
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) => {
|
return result.topic_list[listKey].map((t) => {
|
||||||
t.posters.forEach((p) => {
|
t.posters.forEach((p) => {
|
||||||
p.user = users[p.user_id];
|
p.user = users[p.user_id];
|
||||||
|
|
|
@ -76,6 +76,10 @@ class TopicList
|
||||||
@topics ||= load_topics
|
@topics ||= load_topics
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def categories
|
||||||
|
@categories ||= topics.map { |t| [t.category, t.category.parent_category] }.uniq.flatten.compact
|
||||||
|
end
|
||||||
|
|
||||||
def load_topics
|
def load_topics
|
||||||
@topics = @topics_input
|
@topics = @topics_input
|
||||||
|
|
||||||
|
@ -128,7 +132,12 @@ class TopicList
|
||||||
ft.topic_list = self
|
ft.topic_list = self
|
||||||
end
|
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)
|
topic_preloader_associations.concat(DiscoursePluginRegistry.topic_preloader_associations.to_a)
|
||||||
|
|
||||||
ActiveRecord::Associations::Preloader.new(
|
ActiveRecord::Associations::Preloader.new(
|
||||||
|
|
|
@ -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
|
|
@ -12,6 +12,7 @@ class TopicListSerializer < ApplicationSerializer
|
||||||
has_many :topics, serializer: TopicListItemSerializer, embed: :objects
|
has_many :topics, serializer: TopicListItemSerializer, embed: :objects
|
||||||
has_many :shared_drafts, serializer: TopicListItemSerializer, embed: :objects
|
has_many :shared_drafts, serializer: TopicListItemSerializer, embed: :objects
|
||||||
has_many :tags, serializer: TagSerializer, embed: :objects
|
has_many :tags, serializer: TagSerializer, embed: :objects
|
||||||
|
has_many :categories, serializer: TopicCategorySerializer, embed: :objects
|
||||||
|
|
||||||
def can_create_topic
|
def can_create_topic
|
||||||
scope.can_create?(Topic)
|
scope.can_create?(Topic)
|
||||||
|
@ -36,4 +37,8 @@ class TopicListSerializer < ApplicationSerializer
|
||||||
def include_tags?
|
def include_tags?
|
||||||
SiteSetting.tagging_enabled && object.tags.present?
|
SiteSetting.tagging_enabled && object.tags.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include_categories?
|
||||||
|
SiteSetting.lazy_load_categories
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2174,6 +2174,9 @@ developer:
|
||||||
instrument_gc_stat_per_request:
|
instrument_gc_stat_per_request:
|
||||||
default: false
|
default: false
|
||||||
hidden: true
|
hidden: true
|
||||||
|
lazy_load_categories:
|
||||||
|
default: false
|
||||||
|
hidden: true
|
||||||
|
|
||||||
navigation:
|
navigation:
|
||||||
navigation_menu:
|
navigation_menu:
|
||||||
|
|
|
@ -223,6 +223,38 @@ RSpec.describe ListController do
|
||||||
expect(response.body).not_to include(restricted_tag.name)
|
expect(response.body).not_to include(restricted_tag.name)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
describe "categories and X" do
|
describe "categories and X" do
|
||||||
|
|
Loading…
Reference in New Issue