FIX: add category hashtags support for sub-sub categories.

FIX: add category hashtags support for sub-sub categories.

Hashtags will include last two levels only (ex: “parent:child”).

diff --git a/app/assets/javascripts/discourse/lib/category-tag-search.js b/app/assets/javascripts/discourse/lib/category-tag-search.js
index ca1ddcc..c258ddb 100644
--- a/app/assets/javascripts/discourse/lib/category-tag-search.js
+++ b/app/assets/javascripts/discourse/lib/category-tag-search.js
@@ -76,7 +76,7 @@ export function search(term, siteSettings) {
   var numOfCategories = categories.length;
 
   categories = categories.map(category => {
-    return { model: category, text: Category.slugFor(category, SEPARATOR) };
+    return { model: category, text: Category.slugFor(category, SEPARATOR, 2) };
   });
 
   if (numOfCategories !== limit && siteSettings.tagging_enabled) {
diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js
index bbbe590..f264248 100644
--- a/app/assets/javascripts/discourse/models/category.js
+++ b/app/assets/javascripts/discourse/models/category.js
@@ -264,14 +264,15 @@ Category.reopenClass({
     return _uncategorized;
   },
 
-  slugFor(category, separator = "/") {
+  slugFor(category, separator = "/", depth = 3) {
     if (!category) return "";
 
     const parentCategory = get(category, "parentCategory");
     let result = "";
 
-    if (parentCategory) {
-      result = Category.slugFor(parentCategory) + separator;
+    if (parentCategory && depth > 1) {
+      result =
+        Category.slugFor(parentCategory, separator, depth - 1) + separator;
     }
 
     const id = get(category, "id"),
diff --git a/app/models/concerns/category_hashtag.rb b/app/models/concerns/category_hashtag.rb
index 5a8c92f..95b1521 100644
--- a/app/models/concerns/category_hashtag.rb
+++ b/app/models/concerns/category_hashtag.rb
@@ -9,17 +9,17 @@ module CategoryHashtag
     def query_from_hashtag_slug(category_slug)
       parent_slug, child_slug = category_slug.split(SEPARATOR, 2)
 
-      category = Category.where(slug: parent_slug, parent_category_id: nil)
+      categories = Category.where(slug: parent_slug)
 
       if child_slug
-        Category.where(slug: child_slug, parent_category_id: category.select(:id)).first
+        Category.where(slug: child_slug, parent_category_id: categories.select(:id)).first
       else
-        category.first
+        categories.where(parent_category_id: nil).first
       end
     end
   end
 
   def hashtag_slug
-    full_slug(SEPARATOR)
+    full_slug.split("-").last(2).join(SEPARATOR)
   end
 end
diff --git a/spec/components/concern/category_hashtag_spec.rb b/spec/components/concern/category_hashtag_spec.rb
index 3d59995..81f437e 100644
--- a/spec/components/concern/category_hashtag_spec.rb
+++ b/spec/components/concern/category_hashtag_spec.rb
@@ -36,5 +36,17 @@ describe CategoryHashtag do
       expect(Category.query_from_hashtag_slug("apple")).to eq(nil)
       expect(Category.query_from_hashtag_slug("apple#{CategoryHashtag::SEPARATOR}orange")).to eq(nil)
     end
+
+    context "multi-level categories" do
+      before do
+        SiteSetting.max_category_nesting = 3
+      end
+
+      it "should return the right result for a grand child category slug" do
+        category = Fabricate(:category, parent_category: child_category)
+        expect(Category.query_from_hashtag_slug("#{child_category.slug}#{CategoryHashtag::SEPARATOR}#{category.slug}"))
+          .to eq(category)
+      end
+    end
   end
 end

GitHub sha: fd39c85c

1 Like

Can we convert this to an object literal so the call looks like Category.slugFor(category, SEPARATOR, { depth: 2 }) - I dislike parameters that aren’t obvious from the call site.

It probably makes sense to also put separator in it too.

1 Like

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/kanban-board-theme-component/118164/138

It looks like the first change is missing a ‘depth’ before the 2?

See the linked discussion on meta.