FEATURE: Paginate categories when there are many (#29569)

This commit removes the new optimized category style introduced in
previous commits (d37a0d40, 9a80d718 and 430c42ac), in favour of the
existent `categories_only`.
This commit is contained in:
Bianca Nenciu 2024-11-11 17:32:45 +02:00 committed by GitHub
parent 8854a7101b
commit f1700ca589
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 23 additions and 323 deletions

View File

@ -1,112 +0,0 @@
<PluginOutlet
@name="categories-only-wrapper"
@outletArgs={{hash categories=this.categories}}
>
{{#if this.categories}}
{{#if this.filteredCategories}}
{{#if this.site.mobileView}}
<div
class="category-list optimized {{if this.showTopics 'with-topics'}}"
>
{{#each this.filteredCategories as |c|}}
<ParentCategoryRowOptimized
@category={{c}}
@showTopics={{this.showTopics}}
/>
{{/each}}
</div>
{{else}}
<table
class="category-list optimized {{if this.showTopics 'with-topics'}}"
>
<thead>
<tr>
<th class="category"><span
role="heading"
aria-level="2"
id="categories-only-category"
>{{i18n "categories.category"}}</span></th>
<th class="topics">{{i18n "categories.topics"}}</th>
{{#if this.showTopics}}
<th class="latest">{{i18n "categories.latest"}}</th>
{{/if}}
</tr>
</thead>
<tbody aria-labelledby="categories-only-category">
{{#each this.categories as |category|}}
<ParentCategoryRowOptimized
@category={{category}}
@showTopics={{this.showTopics}}
/>
{{/each}}
</tbody>
</table>
{{/if}}
{{/if}}
{{#if this.mutedCategories}}
<div class="muted-categories">
<a
href
class="muted-categories-link"
{{on "click" this.toggleShowMuted}}
>
<h3 class="muted-categories-heading">{{i18n "categories.muted"}}</h3>
{{#if this.mutedToggleIcon}}
{{d-icon this.mutedToggleIcon}}
{{/if}}
</a>
{{#if this.site.mobileView}}
<div
class="category-list optimized
{{if this.showTopics 'with-topics'}}
{{unless this.showMutedCategories 'hidden'}}"
>
{{#each this.mutedCategories as |c|}}
<ParentCategoryRowOptimized
@category={{c}}
@showTopics={{this.showTopics}}
@listType="muted"
/>
{{/each}}
</div>
{{else}}
<table
class="category-list optimized
{{if this.showTopics 'with-topics'}}
{{unless this.showMutedCategories 'hidden'}}"
>
<thead>
<tr>
<th class="category"><span
role="heading"
aria-level="2"
id="categories-only-category-muted"
>{{i18n "categories.category"}}</span></th>
<th class="topics">{{i18n "categories.topics"}}</th>
{{#if this.showTopics}}
<th class="latest">{{i18n "categories.latest"}}</th>
{{/if}}
</tr>
</thead>
<tbody aria-labelledby="categories-only-category-muted">
{{#each this.categories as |category|}}
<ParentCategoryRowOptimized
@category={{category}}
@showTopics={{this.showTopics}}
@listType="muted"
/>
{{/each}}
</tbody>
</table>
{{/if}}
</div>
{{/if}}
{{/if}}
</PluginOutlet>
<PluginOutlet
@name="below-categories-only"
@connectorTagName="div"
@outletArgs={{hash categories=this.categories showTopics=this.showTopics}}
/>

View File

@ -1,56 +0,0 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { tagName } from "@ember-decorators/component";
import discourseComputed from "discourse-common/utils/decorators";
@tagName("")
export default class CategoriesOnlyOptimized extends Component {
showMuted = false;
@discourseComputed("showMutedCategories", "filteredCategories.length")
mutedToggleIcon(showMutedCategories, filteredCategoriesLength) {
if (filteredCategoriesLength === 0) {
return;
}
if (showMutedCategories) {
return "minus";
}
return "plus";
}
@discourseComputed("showMuted", "filteredCategories.length")
showMutedCategories(showMuted, filteredCategoriesLength) {
return showMuted || filteredCategoriesLength === 0;
}
@discourseComputed("categories", "categories.length")
filteredCategories(categories, categoriesLength) {
if (!categories || categoriesLength === 0) {
return [];
}
return categories.filter((cat) => !cat.isHidden);
}
@discourseComputed("categories", "categories.length")
mutedCategories(categories, categoriesLength) {
if (!categories || categoriesLength === 0) {
return [];
}
// hide in single category pages
if (categories.firstObject.parent_category_id) {
return [];
}
return categories.filterBy("hasMuted");
}
@action
toggleShowMuted(event) {
event?.preventDefault();
this.toggleProperty("showMuted");
}
}

View File

@ -6,7 +6,6 @@ import CategoriesAndTopTopics from "discourse/components/categories-and-top-topi
import CategoriesBoxes from "discourse/components/categories-boxes"; import CategoriesBoxes from "discourse/components/categories-boxes";
import CategoriesBoxesWithTopics from "discourse/components/categories-boxes-with-topics"; import CategoriesBoxesWithTopics from "discourse/components/categories-boxes-with-topics";
import CategoriesOnly from "discourse/components/categories-only"; import CategoriesOnly from "discourse/components/categories-only";
import CategoriesOnlyOptimized from "discourse/components/categories-only-optimized";
import CategoriesWithFeaturedTopics from "discourse/components/categories-with-featured-topics"; import CategoriesWithFeaturedTopics from "discourse/components/categories-with-featured-topics";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner"; import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import LoadMore from "discourse/components/load-more"; import LoadMore from "discourse/components/load-more";
@ -17,7 +16,6 @@ import { MAX_UNOPTIMIZED_CATEGORIES } from "discourse/lib/constants";
const mobileCompatibleViews = [ const mobileCompatibleViews = [
"categories_with_featured_topics", "categories_with_featured_topics",
"subcategories_with_featured_topics", "subcategories_with_featured_topics",
"categories_only_optimized",
]; ];
const subcategoryComponents = { const subcategoryComponents = {
@ -34,7 +32,6 @@ const globalComponents = {
categories_boxes_with_topics: CategoriesBoxesWithTopics, categories_boxes_with_topics: CategoriesBoxesWithTopics,
categories_boxes: CategoriesBoxes, categories_boxes: CategoriesBoxes,
categories_only: CategoriesOnly, categories_only: CategoriesOnly,
categories_only_optimized: CategoriesOnlyOptimized,
categories_with_featured_topics: CategoriesWithFeaturedTopics, categories_with_featured_topics: CategoriesWithFeaturedTopics,
subcategories_with_featured_topics: SubcategoriesWithFeaturedTopics, subcategories_with_featured_topics: SubcategoriesWithFeaturedTopics,
}; };
@ -64,7 +61,7 @@ export default class CategoriesDisplay extends Component {
style = mobileCompatibleViews[0]; style = mobileCompatibleViews[0];
} }
if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) { if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) {
style = "categories_only_optimized"; style = "categories_only";
} }
return style; return style;
} }
@ -95,7 +92,7 @@ export default class CategoriesDisplay extends Component {
return ( return (
this.args.loadMore && this.args.loadMore &&
(this.site.lazy_load_categories || (this.site.lazy_load_categories ||
this.style === "categories_only_optimized") this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES)
); );
} }

View File

@ -1,97 +0,0 @@
{{#unless this.isHidden}}
<PluginOutlet
@name="category-list-above-each-category"
@outletArgs={{hash category=this.category}}
/>
{{#if this.site.mobileView}}
<div
data-category-id={{this.category.id}}
data-notification-level={{this.category.notificationLevelString}}
style={{border-color this.category.color}}
class="category-list-item category {{if this.isMuted 'muted'}}"
>
<table class="topic-list">
<tbody>
<tr>
<th class="main-link">
<CategoryTitleLink @category={{this.category}} />
</th>
</tr>
{{#if this.category.description_excerpt}}
<tr class="category-description">
<td colspan="3">
{{html-safe this.category.description_excerpt}}
</td>
</tr>
{{/if}}
{{#if (gt this.category.subcategories.length 0)}}
<tr class="category-subcategories">
<td colspan="3">
<LinkTo
@route="discovery.subcategories"
@model={{this.slugPath}}
>
{{i18n
"category_row.subcategory_count"
count=this.category.subcategories.length
}}
</LinkTo>
</td>
</tr>
{{/if}}
</tbody>
</table>
</div>
{{else}}
<tr
data-category-id={{this.category.id}}
data-notification-level={{this.category.notificationLevelString}}
class="{{if
this.category.description_excerpt
'has-description'
'no-description'
}}
{{if this.category.uploaded_logo.url 'has-logo' 'no-logo'}}"
>
<td
class="category {{if this.isMuted 'muted'}}"
style={{category-color-variable this.category.color}}
>
<CategoryTitleLink @category={{this.category}} />
<PluginOutlet
@name="below-category-title-link"
@connectorTagName="div"
@outletArgs={{hash category=this.category}}
/>
{{#if this.category.description_excerpt}}
<div class="category-description">
{{dir-span this.category.description_excerpt htmlSafe="true"}}
</div>
{{/if}}
{{#if (gt this.category.subcategories.length 0)}}
<div class="category-subcategories">
<LinkTo @route="discovery.subcategories" @model={{this.slugPath}}>
{{i18n
"category_row.subcategory_count"
count=this.category.subcategories.length
}}
</LinkTo>
</div>
{{/if}}
</td>
<td class="topics">
<div title={{this.category.statTitle}}>{{html-safe
this.category.stat
}}</div>
<CategoryUnread
@category={{this.category}}
@tagName="div"
@unreadTopicsCount={{this.unreadTopicsCount}}
@newTopicsCount={{this.newTopicsCount}}
class="unread-new"
/>
</td>
</tr>
{{/if}}
{{/unless}}

View File

@ -1,3 +0,0 @@
import CategoryListItem from "discourse/components/category-list-item";
export default class ParentCategoryRowOptimized extends CategoryListItem {}

View File

@ -25,7 +25,7 @@ export default class DiscoveryCategoriesRoute extends DiscourseRoute {
let style = let style =
this.site.desktopView && this.siteSettings.desktop_category_page_style; this.site.desktopView && this.siteSettings.desktop_category_page_style;
if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) { if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) {
style = "categories_only_optimized"; style = "categories_only";
} }
if ( if (

View File

@ -314,14 +314,6 @@
overflow: hidden; overflow: hidden;
color: var(--primary-high); color: var(--primary-high);
} }
.category-subcategories {
font-size: var(--font-down-1);
margin-top: 0.5em;
a {
color: var(--primary-high);
}
}
.category-logo.aspect-image { .category-logo.aspect-image {
margin-top: 0.5em; margin-top: 0.5em;
} }

View File

@ -144,16 +144,6 @@
border-left: 6px solid; border-left: 6px solid;
} }
} }
&.optimized {
tr {
border: none;
}
th {
padding: 10px 0 10px;
}
}
} }
.category-list-item.category { .category-list-item.category {
@ -265,14 +255,6 @@ tr.category-topic-link {
padding-bottom: 15px; padding-bottom: 15px;
} }
.category-subcategories td {
padding-top: 0;
}
.category-description + .category-subcategories td {
padding-top: 0;
}
.subcategories-list { .subcategories-list {
border-bottom: none; border-bottom: none;
td { td {

View File

@ -135,21 +135,21 @@ class CategoryList
end end
def find_categories def find_categories
# Enforce paginaion for users who can see a large number of categories to
# smooth out the performance of the category list page.
paginate =
Category.secured(@guardian).count > MAX_UNOPTIMIZED_CATEGORIES ||
@guardian.can_lazy_load_categories?
query = Category.includes(CategoryList.included_associations).secured(@guardian) query = Category.includes(CategoryList.included_associations).secured(@guardian)
query = self.class.order_categories(query) query = self.class.order_categories(query)
if @options[:parent_category_id].present? || @guardian.can_lazy_load_categories? if @options[:parent_category_id].present? || paginate
query = query.where(parent_category_id: @options[:parent_category_id]) query = query.where(parent_category_id: @options[:parent_category_id])
end end
style =
if Category.secured(@guardian).count > MAX_UNOPTIMIZED_CATEGORIES
"categories_only_optimized"
else
SiteSetting.desktop_category_page_style
end
page = [1, @options[:page].to_i].max page = [1, @options[:page].to_i].max
if style == "categories_only_optimized" || @guardian.can_lazy_load_categories? if paginate
query = query.limit(CATEGORIES_PER_PAGE).offset((page - 1) * CATEGORIES_PER_PAGE) query = query.limit(CATEGORIES_PER_PAGE).offset((page - 1) * CATEGORIES_PER_PAGE)
elsif page > 1 elsif page > 1
# Pagination is supported only when lazy load is enabled. If it is not, # Pagination is supported only when lazy load is enabled. If it is not,
@ -162,7 +162,7 @@ class CategoryList
@categories = query.to_a @categories = query.to_a
if @guardian.can_lazy_load_categories? && @options[:parent_category_id].blank? if paginate && @options[:parent_category_id].blank?
categories_with_rownum = categories_with_rownum =
Category Category
.secured(@guardian) .secured(@guardian)
@ -182,7 +182,7 @@ class CategoryList
include_subcategories = @options[:include_subcategories] == true include_subcategories = @options[:include_subcategories] == true
if @guardian.can_lazy_load_categories? if paginate
subcategory_ids = {} subcategory_ids = {}
Category Category
.secured(@guardian) .secured(@guardian)

View File

@ -10,7 +10,6 @@ class CategoryPageStyle < EnumSiteSetting
def self.values def self.values
@values ||= [ @values ||= [
{ name: "category_page_style.categories_only", value: "categories_only" }, { name: "category_page_style.categories_only", value: "categories_only" },
{ name: "category_page_style.categories_only_optimized", value: "categories_only_optimized" },
{ {
name: "category_page_style.categories_with_featured_topics", name: "category_page_style.categories_with_featured_topics",
value: "categories_with_featured_topics", value: "categories_with_featured_topics",

View File

@ -2518,7 +2518,6 @@ en:
category_page_style: category_page_style:
categories_only: "Categories Only" categories_only: "Categories Only"
categories_only_optimized: "Categories Only (Optimized)"
categories_with_featured_topics: "Categories with Featured Topics" categories_with_featured_topics: "Categories with Featured Topics"
categories_and_latest_topics: "Categories and Latest Topics" categories_and_latest_topics: "Categories and Latest Topics"
categories_and_latest_topics_created_date: "Categories and Latest Topics (sort by topic created date)" categories_and_latest_topics_created_date: "Categories and Latest Topics (sort by topic created date)"

View File

@ -2335,7 +2335,6 @@ ug:
facebook_messenger: "Facebook Messenger" facebook_messenger: "Facebook Messenger"
category_page_style: category_page_style:
categories_only: "سەھىپىلا" categories_only: "سەھىپىلا"
categories_only_optimized: "سەھىپەلەرلا (ئەلالاشتۇرۇلغان)"
categories_with_featured_topics: "جەۋھەر تېمىلىق سەھىپە" categories_with_featured_topics: "جەۋھەر تېمىلىق سەھىپە"
categories_and_latest_topics: "سەھىپە ۋە ئاخىرقى تېما" categories_and_latest_topics: "سەھىپە ۋە ئاخىرقى تېما"
categories_and_latest_topics_created_date: "سەھىپە ۋە ئاخىرقى تېما (قۇرۇلغان چېسلا بويىچە تەرتىپلەيدۇ)" categories_and_latest_topics_created_date: "سەھىپە ۋە ئاخىرقى تېما (قۇرۇلغان چېسلا بويىچە تەرتىپلەيدۇ)"

View File

@ -404,7 +404,7 @@ RSpec.describe CategoriesController do
let!(:category2) { Fabricate(:category, user: admin) } let!(:category2) { Fabricate(:category, user: admin) }
let!(:category3) { Fabricate(:category, user: admin) } let!(:category3) { Fabricate(:category, user: admin) }
it "paginates results wihen lazy_load_categories is enabled" do it "paginates results when lazy_load_categories is enabled" do
SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:everyone]}" SiteSetting.lazy_load_categories_groups = "#{Group::AUTO_GROUPS[:everyone]}"
stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" }
@ -416,9 +416,8 @@ RSpec.describe CategoriesController do
expect(response.parsed_body["category_list"]["categories"].count).to eq(2) expect(response.parsed_body["category_list"]["categories"].count).to eq(2)
end end
it "paginates results wihen desktop_category_page_style is categories_only_optimized" do it "paginates results when there are many categories" do
SiteSetting.desktop_category_page_style = "categories_only_optimized" stub_const(CategoryList, "MAX_UNOPTIMIZED_CATEGORIES", 2) do
stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" }
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.parsed_body["category_list"]["categories"].count).to eq(2) expect(response.parsed_body["category_list"]["categories"].count).to eq(2)
@ -427,6 +426,7 @@ RSpec.describe CategoriesController do
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.parsed_body["category_list"]["categories"].count).to eq(2) expect(response.parsed_body["category_list"]["categories"].count).to eq(2)
end end
end
it "does not paginate results by default" do it "does not paginate results by default" do
stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" }