From a2dbcedbd9fa79aa64a9612f9b9e76eadb771f99 Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Wed, 5 Feb 2025 12:31:50 +1000 Subject: [PATCH] UX: Show parent category name for category hashtags (#31188) This commit changes the display of category hashtag autocomplete to show the parent category name in this format: * Parent Name > Child Name This helps further distinguish categories in the autocomplete where there may be multiple different parent categories with the same name child category, e.g. if every category has an Announcements subcategory. --- app/services/category_hashtag_data_source.rb | 9 +++- .../category_hashtag_data_source_spec.rb | 43 ++++++++++++++++--- .../hashtag_autocomplete_service_spec.rb | 6 +-- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/app/services/category_hashtag_data_source.rb b/app/services/category_hashtag_data_source.rb index 2ef743517c1..c3ea01ea413 100644 --- a/app/services/category_hashtag_data_source.rb +++ b/app/services/category_hashtag_data_source.rb @@ -18,7 +18,14 @@ class CategoryHashtagDataSource def self.category_to_hashtag_item(category) HashtagAutocompleteService::HashtagItem.new.tap do |item| - item.text = category.name + item.text = + ( + if category.parent_category + "#{category.parent_category.name} > #{category.name}" + else + category.name + end + ) item.slug = category.slug item.description = category.description_text item.icon = icon diff --git a/spec/services/category_hashtag_data_source_spec.rb b/spec/services/category_hashtag_data_source_spec.rb index b3e0fd29105..12fb7820d43 100644 --- a/spec/services/category_hashtag_data_source_spec.rb +++ b/spec/services/category_hashtag_data_source_spec.rb @@ -1,15 +1,23 @@ # frozen_string_literal: true RSpec.describe CategoryHashtagDataSource do - fab!(:parent_category) { Fabricate(:category, slug: "fun", topic_count: 2) } + fab!(:parent_category) { Fabricate(:category, name: "Silly Land", slug: "fun", topic_count: 2) } fab!(:category1) do - Fabricate(:category, slug: "random", topic_count: 12, parent_category: parent_category) + Fabricate( + :category, + name: "Random", + slug: "random", + topic_count: 12, + parent_category: parent_category, + ) end fab!(:category2) { Fabricate(:category, name: "Book Section", slug: "books", topic_count: 566) } - fab!(:category3) { Fabricate(:category, slug: "movies", topic_count: 245) } + fab!(:category3) { Fabricate(:category, name: "Kino Korner", slug: "movies", topic_count: 245) } fab!(:group) - fab!(:category4) { Fabricate(:private_category, slug: "secret", group: group, topic_count: 40) } - fab!(:category5) { Fabricate(:category, slug: "casual", topic_count: 99) } + fab!(:category4) do + Fabricate(:private_category, name: "Nunya", slug: "secret", group: group, topic_count: 40) + end + fab!(:category5) { Fabricate(:category, name: "Chillzone", slug: "casual", topic_count: 99) } fab!(:user) let(:guardian) { Guardian.new(user) } let(:uncategorized_category) { Category.find(SiteSetting.uncategorized_category_id) } @@ -55,6 +63,16 @@ RSpec.describe CategoryHashtagDataSource do expect(described_class.lookup(Guardian.new(user), ["secret"]).first).not_to eq(nil) end + it "formats the category text for a category without a parent" do + result = described_class.lookup(guardian, ["movies"]).first + expect(result.text).to eq("Kino Korner") + end + + it "formats the category text for a category with a parent" do + result = described_class.lookup(guardian, ["fun:random"]).first + expect(result.text).to eq("Silly Land > Random") + end + context "with sub-sub-categories" do before { SiteSetting.max_category_nesting = 3 } @@ -94,6 +112,15 @@ RSpec.describe CategoryHashtagDataSource do result = described_class.lookup(guardian, ["child:grandchild"]) expect(result.map(&:relative_url)).to eq([parent2_child_grandchild.url]) end + + it "formats the category text for sub-sub-categories" do + parent = Fabricate(:category, slug: "parent", name: "Parent") + child = Fabricate(:category, slug: "child", parent_category_id: parent.id, name: "Child") + grandchild = + Fabricate(:category, slug: "grandchild", parent_category_id: child.id, name: "Grandchild") + result = described_class.lookup(guardian, ["child:grandchild"]) + expect(result.last.text).to eq("Child > Grandchild") + end end end @@ -102,6 +129,7 @@ RSpec.describe CategoryHashtagDataSource do result = described_class.search(guardian, "mov", 5).first expect(result.ref).to eq("movies") expect(result.slug).to eq("movies") + expect(result.text).to eq("Kino Korner") end it "finds categories by partial slug" do @@ -121,6 +149,11 @@ RSpec.describe CategoryHashtagDataSource do expect(result.ref).to eq("fun:random") expect(result.slug).to eq("random") end + + it "formats the text correctly for a parent:child category that is found" do + result = described_class.search(guardian, "random", 5).first + expect(result.text).to eq("Silly Land > Random") + end end describe "#search_without_term" do diff --git a/spec/services/hashtag_autocomplete_service_spec.rb b/spec/services/hashtag_autocomplete_service_spec.rb index 5d9906024fe..568281f9478 100644 --- a/spec/services/hashtag_autocomplete_service_spec.rb +++ b/spec/services/hashtag_autocomplete_service_spec.rb @@ -212,8 +212,8 @@ RSpec.describe HashtagAutocompleteService do expect(service.search("book", %w[category tag]).map(&:ref)).to eq( [ - "book-reviews:book", # category exact match on slug, name sorted "book-library:book", + "book-reviews:book", # category exact match on slug, name sorted "book-library", # category starts with match on slug, name sorted "book-reviews", "bookmania", # tag starts with match on slug, name sorted @@ -226,8 +226,8 @@ RSpec.describe HashtagAutocompleteService do ) expect(service.search("book", %w[category tag]).map(&:text)).to eq( [ - "Good Books", - "Horror", + "Book Library > Horror", + "Book Reviews > Good Books", "Book Library", "Book Reviews", "bookmania",