From f1700ca58929bcbfad23565861d1d3084ae1b3f8 Mon Sep 17 00:00:00 2001 From: Bianca Nenciu Date: Mon, 11 Nov 2024 17:32:45 +0200 Subject: [PATCH] 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`. --- .../components/categories-only-optimized.hbs | 112 ------------------ .../components/categories-only-optimized.js | 56 --------- .../discovery/categories-display.gjs | 7 +- .../parent-category-row-optimized.hbs | 97 --------------- .../parent-category-row-optimized.js | 3 - .../app/routes/discovery-categories.js | 2 +- .../common/base/category-list.scss | 8 -- app/assets/stylesheets/mobile/topic-list.scss | 18 --- app/models/category_list.rb | 20 ++-- app/models/category_page_style.rb | 1 - config/locales/client.en.yml | 1 - config/locales/client.ug.yml | 1 - spec/requests/categories_controller_spec.rb | 20 ++-- 13 files changed, 23 insertions(+), 323 deletions(-) delete mode 100644 app/assets/javascripts/discourse/app/components/categories-only-optimized.hbs delete mode 100644 app/assets/javascripts/discourse/app/components/categories-only-optimized.js delete mode 100644 app/assets/javascripts/discourse/app/components/parent-category-row-optimized.hbs delete mode 100644 app/assets/javascripts/discourse/app/components/parent-category-row-optimized.js diff --git a/app/assets/javascripts/discourse/app/components/categories-only-optimized.hbs b/app/assets/javascripts/discourse/app/components/categories-only-optimized.hbs deleted file mode 100644 index b544ccc6ed6..00000000000 --- a/app/assets/javascripts/discourse/app/components/categories-only-optimized.hbs +++ /dev/null @@ -1,112 +0,0 @@ - - {{#if this.categories}} - {{#if this.filteredCategories}} - {{#if this.site.mobileView}} -
- {{#each this.filteredCategories as |c|}} - - {{/each}} -
- {{else}} - - - - - - {{#if this.showTopics}} - - {{/if}} - - - - {{#each this.categories as |category|}} - - {{/each}} - -
{{i18n "categories.category"}}{{i18n "categories.topics"}}{{i18n "categories.latest"}}
- {{/if}} - {{/if}} - - {{#if this.mutedCategories}} -
- -

{{i18n "categories.muted"}}

- {{#if this.mutedToggleIcon}} - {{d-icon this.mutedToggleIcon}} - {{/if}} -
- {{#if this.site.mobileView}} -
- {{#each this.mutedCategories as |c|}} - - {{/each}} -
- {{else}} - - - - - - {{#if this.showTopics}} - - {{/if}} - - - - {{#each this.categories as |category|}} - - {{/each}} - -
{{i18n "categories.category"}}{{i18n "categories.topics"}}{{i18n "categories.latest"}}
- {{/if}} -
- {{/if}} - {{/if}} -
- - \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/categories-only-optimized.js b/app/assets/javascripts/discourse/app/components/categories-only-optimized.js deleted file mode 100644 index 992c588e272..00000000000 --- a/app/assets/javascripts/discourse/app/components/categories-only-optimized.js +++ /dev/null @@ -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"); - } -} diff --git a/app/assets/javascripts/discourse/app/components/discovery/categories-display.gjs b/app/assets/javascripts/discourse/app/components/discovery/categories-display.gjs index f1679b5db85..d0c6c24c8b1 100644 --- a/app/assets/javascripts/discourse/app/components/discovery/categories-display.gjs +++ b/app/assets/javascripts/discourse/app/components/discovery/categories-display.gjs @@ -6,7 +6,6 @@ import CategoriesAndTopTopics from "discourse/components/categories-and-top-topi import CategoriesBoxes from "discourse/components/categories-boxes"; import CategoriesBoxesWithTopics from "discourse/components/categories-boxes-with-topics"; 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 ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner"; import LoadMore from "discourse/components/load-more"; @@ -17,7 +16,6 @@ import { MAX_UNOPTIMIZED_CATEGORIES } from "discourse/lib/constants"; const mobileCompatibleViews = [ "categories_with_featured_topics", "subcategories_with_featured_topics", - "categories_only_optimized", ]; const subcategoryComponents = { @@ -34,7 +32,6 @@ const globalComponents = { categories_boxes_with_topics: CategoriesBoxesWithTopics, categories_boxes: CategoriesBoxes, categories_only: CategoriesOnly, - categories_only_optimized: CategoriesOnlyOptimized, categories_with_featured_topics: CategoriesWithFeaturedTopics, subcategories_with_featured_topics: SubcategoriesWithFeaturedTopics, }; @@ -64,7 +61,7 @@ export default class CategoriesDisplay extends Component { style = mobileCompatibleViews[0]; } if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) { - style = "categories_only_optimized"; + style = "categories_only"; } return style; } @@ -95,7 +92,7 @@ export default class CategoriesDisplay extends Component { return ( this.args.loadMore && (this.site.lazy_load_categories || - this.style === "categories_only_optimized") + this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) ); } diff --git a/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.hbs b/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.hbs deleted file mode 100644 index bd09d5a983d..00000000000 --- a/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.hbs +++ /dev/null @@ -1,97 +0,0 @@ -{{#unless this.isHidden}} - - {{#if this.site.mobileView}} -
- - - - - - {{#if this.category.description_excerpt}} - - - - {{/if}} - {{#if (gt this.category.subcategories.length 0)}} - - - - {{/if}} - -
- -
- {{html-safe this.category.description_excerpt}} -
- - {{i18n - "category_row.subcategory_count" - count=this.category.subcategories.length - }} - -
-
- {{else}} - - - - - {{#if this.category.description_excerpt}} -
- {{dir-span this.category.description_excerpt htmlSafe="true"}} -
- {{/if}} - {{#if (gt this.category.subcategories.length 0)}} -
- - {{i18n - "category_row.subcategory_count" - count=this.category.subcategories.length - }} - -
- {{/if}} - - - -
{{html-safe - this.category.stat - }}
- - - - {{/if}} -{{/unless}} \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.js b/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.js deleted file mode 100644 index ca7e2e4e44b..00000000000 --- a/app/assets/javascripts/discourse/app/components/parent-category-row-optimized.js +++ /dev/null @@ -1,3 +0,0 @@ -import CategoryListItem from "discourse/components/category-list-item"; - -export default class ParentCategoryRowOptimized extends CategoryListItem {} diff --git a/app/assets/javascripts/discourse/app/routes/discovery-categories.js b/app/assets/javascripts/discourse/app/routes/discovery-categories.js index 15e7101b0a5..5f4b1326674 100644 --- a/app/assets/javascripts/discourse/app/routes/discovery-categories.js +++ b/app/assets/javascripts/discourse/app/routes/discovery-categories.js @@ -25,7 +25,7 @@ export default class DiscoveryCategoriesRoute extends DiscourseRoute { let style = this.site.desktopView && this.siteSettings.desktop_category_page_style; if (this.site.categories.length > MAX_UNOPTIMIZED_CATEGORIES) { - style = "categories_only_optimized"; + style = "categories_only"; } if ( diff --git a/app/assets/stylesheets/common/base/category-list.scss b/app/assets/stylesheets/common/base/category-list.scss index a6daf77df12..35cbf8a383e 100644 --- a/app/assets/stylesheets/common/base/category-list.scss +++ b/app/assets/stylesheets/common/base/category-list.scss @@ -314,14 +314,6 @@ overflow: hidden; 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 { margin-top: 0.5em; } diff --git a/app/assets/stylesheets/mobile/topic-list.scss b/app/assets/stylesheets/mobile/topic-list.scss index d174749a63d..36a97cde37e 100644 --- a/app/assets/stylesheets/mobile/topic-list.scss +++ b/app/assets/stylesheets/mobile/topic-list.scss @@ -144,16 +144,6 @@ border-left: 6px solid; } } - - &.optimized { - tr { - border: none; - } - - th { - padding: 10px 0 10px; - } - } } .category-list-item.category { @@ -265,14 +255,6 @@ tr.category-topic-link { padding-bottom: 15px; } - .category-subcategories td { - padding-top: 0; - } - - .category-description + .category-subcategories td { - padding-top: 0; - } - .subcategories-list { border-bottom: none; td { diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 490f44416ee..c783e47b6c9 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -135,21 +135,21 @@ class CategoryList end 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 = 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]) 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 - if style == "categories_only_optimized" || @guardian.can_lazy_load_categories? + if paginate query = query.limit(CATEGORIES_PER_PAGE).offset((page - 1) * CATEGORIES_PER_PAGE) elsif page > 1 # Pagination is supported only when lazy load is enabled. If it is not, @@ -162,7 +162,7 @@ class CategoryList @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 = Category .secured(@guardian) @@ -182,7 +182,7 @@ class CategoryList include_subcategories = @options[:include_subcategories] == true - if @guardian.can_lazy_load_categories? + if paginate subcategory_ids = {} Category .secured(@guardian) diff --git a/app/models/category_page_style.rb b/app/models/category_page_style.rb index 8acb3360bf0..fe8c5d41978 100644 --- a/app/models/category_page_style.rb +++ b/app/models/category_page_style.rb @@ -10,7 +10,6 @@ class CategoryPageStyle < EnumSiteSetting def self.values @values ||= [ { 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", value: "categories_with_featured_topics", diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index cfccb3dc1f8..6c50b630773 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2518,7 +2518,6 @@ en: category_page_style: categories_only: "Categories Only" - categories_only_optimized: "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 (sort by topic created date)" diff --git a/config/locales/client.ug.yml b/config/locales/client.ug.yml index 9c9ed130f89..3440cdf5022 100644 --- a/config/locales/client.ug.yml +++ b/config/locales/client.ug.yml @@ -2335,7 +2335,6 @@ ug: facebook_messenger: "Facebook Messenger" category_page_style: categories_only: "سەھىپىلا" - categories_only_optimized: "سەھىپەلەرلا (ئەلالاشتۇرۇلغان)" categories_with_featured_topics: "جەۋھەر تېمىلىق سەھىپە" categories_and_latest_topics: "سەھىپە ۋە ئاخىرقى تېما" categories_and_latest_topics_created_date: "سەھىپە ۋە ئاخىرقى تېما (قۇرۇلغان چېسلا بويىچە تەرتىپلەيدۇ)" diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb index fb3749c5fdc..1d5e37d80ab 100644 --- a/spec/requests/categories_controller_spec.rb +++ b/spec/requests/categories_controller_spec.rb @@ -404,7 +404,7 @@ RSpec.describe CategoriesController do let!(:category2) { 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]}" stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } @@ -416,16 +416,16 @@ RSpec.describe CategoriesController do expect(response.parsed_body["category_list"]["categories"].count).to eq(2) end - it "paginates results wihen desktop_category_page_style is categories_only_optimized" do - SiteSetting.desktop_category_page_style = "categories_only_optimized" + it "paginates results when there are many categories" do + stub_const(CategoryList, "MAX_UNOPTIMIZED_CATEGORIES", 2) do + stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } + expect(response.status).to eq(200) + expect(response.parsed_body["category_list"]["categories"].count).to eq(2) - stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=1" } - expect(response.status).to eq(200) - expect(response.parsed_body["category_list"]["categories"].count).to eq(2) - - stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=2" } - expect(response.status).to eq(200) - expect(response.parsed_body["category_list"]["categories"].count).to eq(2) + stub_const(CategoryList, "CATEGORIES_PER_PAGE", 2) { get "/categories.json?page=2" } + expect(response.status).to eq(200) + expect(response.parsed_body["category_list"]["categories"].count).to eq(2) + end end it "does not paginate results by default" do