mirror of
https://github.com/discourse/discourse.git
synced 2026-08-13 06:25:11 -05:00
UX: Display only top categories in hamburger menu (#6146)
This commit is contained in:
@@ -51,7 +51,7 @@ export default createWidget("hamburger-categories", {
|
|||||||
|
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
const href = Discourse.getURL("/categories");
|
const href = Discourse.getURL("/categories");
|
||||||
const result = [
|
let result = [
|
||||||
h(
|
h(
|
||||||
"li.heading",
|
"li.heading",
|
||||||
h(
|
h(
|
||||||
@@ -66,8 +66,23 @@ export default createWidget("hamburger-categories", {
|
|||||||
if (categories.length === 0) {
|
if (categories.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return result.concat(
|
result = result.concat(
|
||||||
categories.map(c => this.attach("hamburger-category", c))
|
categories.map(c => this.attach("hamburger-category", c))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (attrs.showMore) {
|
||||||
|
result = result.concat(
|
||||||
|
h(
|
||||||
|
"li.footer",
|
||||||
|
h(
|
||||||
|
"a.d-link.more-link",
|
||||||
|
{ attributes: { href } },
|
||||||
|
I18n.t("categories.more")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -176,20 +176,29 @@ export default createWidget("hamburger-menu", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
listCategories() {
|
listCategories() {
|
||||||
const hideUncategorized = !this.siteSettings.allow_uncategorized_topics;
|
const maxCategoriesToDisplay = 6;
|
||||||
const isStaff = Discourse.User.currentProp("staff");
|
const categoriesList = this.site
|
||||||
|
.get("categoriesByCount")
|
||||||
|
.reject(c => c.parent_category_id);
|
||||||
|
let categories = [];
|
||||||
|
let showMore = categoriesList.length > maxCategoriesToDisplay;
|
||||||
|
|
||||||
const categories = this.site.get("categoriesList").reject(c => {
|
if (this.currentUser) {
|
||||||
if (c.get("parentCategory.show_subcategory_list")) {
|
let categoryIds = this.currentUser.get("top_category_ids") || [];
|
||||||
return true;
|
categoryIds = categoryIds.concat(categoriesList.map(c => c.id)).uniq();
|
||||||
}
|
|
||||||
if (hideUncategorized && c.get("isUncategorizedCategory") && !isStaff) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.attach("hamburger-categories", { categories });
|
showMore = categoryIds.length > maxCategoriesToDisplay;
|
||||||
|
categoryIds = categoryIds.slice(0, maxCategoriesToDisplay);
|
||||||
|
|
||||||
|
categories = categoryIds.map(id => {
|
||||||
|
return categoriesList.find(c => c.id === id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showMore = categoriesList.length > maxCategoriesToDisplay;
|
||||||
|
categories = categoriesList.slice(0, maxCategoriesToDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.attach("hamburger-categories", { categories, showMore });
|
||||||
},
|
},
|
||||||
|
|
||||||
footerLinks(prioritizeFaq, faqUrl) {
|
footerLinks(prioritizeFaq, faqUrl) {
|
||||||
|
|||||||
@@ -108,6 +108,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-links {
|
||||||
|
.footer {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// note these topic counts only appear for anons in the category hamburger drop down
|
// note these topic counts only appear for anons in the category hamburger drop down
|
||||||
b.topics-count {
|
b.topics-count {
|
||||||
color: dark-light-choose($primary-medium, $secondary-medium);
|
color: dark-light-choose($primary-medium, $secondary-medium);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ require_dependency 'new_post_manager'
|
|||||||
|
|
||||||
class CurrentUserSerializer < BasicUserSerializer
|
class CurrentUserSerializer < BasicUserSerializer
|
||||||
|
|
||||||
|
MAX_TOP_CATEGORIES_COUNT = 6.freeze
|
||||||
|
|
||||||
attributes :name,
|
attributes :name,
|
||||||
:unread_notifications,
|
:unread_notifications,
|
||||||
:unread_private_messages,
|
:unread_private_messages,
|
||||||
@@ -41,7 +43,8 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||||||
:primary_group_name,
|
:primary_group_name,
|
||||||
:can_create_topic,
|
:can_create_topic,
|
||||||
:link_posting_access,
|
:link_posting_access,
|
||||||
:external_id
|
:external_id,
|
||||||
|
:top_category_ids
|
||||||
|
|
||||||
def link_posting_access
|
def link_posting_access
|
||||||
scope.link_posting_access
|
scope.link_posting_access
|
||||||
@@ -153,9 +156,20 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||||||
end
|
end
|
||||||
|
|
||||||
def muted_category_ids
|
def muted_category_ids
|
||||||
@muted_category_ids ||= CategoryUser.where(user_id: object.id,
|
CategoryUser.lookup(object, :muted).pluck(:category_id)
|
||||||
notification_level: TopicUser.notification_levels[:muted])
|
end
|
||||||
|
|
||||||
|
def top_category_ids
|
||||||
|
CategoryUser.where(user_id: object.id)
|
||||||
|
.where.not(notification_level: CategoryUser.notification_levels[:muted])
|
||||||
|
.order("
|
||||||
|
CASE
|
||||||
|
WHEN notification_level = 3 THEN 1
|
||||||
|
WHEN notification_level = 2 THEN 2
|
||||||
|
WHEN notification_level = 4 THEN 3
|
||||||
|
END")
|
||||||
.pluck(:category_id)
|
.pluck(:category_id)
|
||||||
|
.slice(0, MAX_TOP_CATEGORIES_COUNT)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dismissed_banner_key
|
def dismissed_banner_key
|
||||||
|
|||||||
@@ -571,6 +571,7 @@ en:
|
|||||||
topic_stat_sentence:
|
topic_stat_sentence:
|
||||||
one: "%{count} new topic in the past %{unit}."
|
one: "%{count} new topic in the past %{unit}."
|
||||||
other: "%{count} new topics in the past %{unit}."
|
other: "%{count} new topics in the past %{unit}."
|
||||||
|
more: "more"
|
||||||
|
|
||||||
ip_lookup:
|
ip_lookup:
|
||||||
title: IP Address Lookup
|
title: IP Address Lookup
|
||||||
|
|||||||
@@ -32,4 +32,31 @@ RSpec.describe CurrentUserSerializer do
|
|||||||
expect(payload[:external_id]).to eq("12345")
|
expect(payload[:external_id]).to eq("12345")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "#top_category_ids" do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:category1) { Fabricate(:category) }
|
||||||
|
let(:category2) { Fabricate(:category) }
|
||||||
|
let :serializer do
|
||||||
|
CurrentUserSerializer.new(user, scope: Guardian.new, root: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should include empty top_category_ids array" do
|
||||||
|
payload = serializer.as_json
|
||||||
|
expect(payload[:top_category_ids]).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should include correct id in top_category_ids array" do
|
||||||
|
category = Category.first
|
||||||
|
CategoryUser.create!(user_id: user.id,
|
||||||
|
category_id: category1.id,
|
||||||
|
notification_level: CategoryUser.notification_levels[:tracking])
|
||||||
|
|
||||||
|
CategoryUser.create!(user_id: user.id,
|
||||||
|
category_id: category2.id,
|
||||||
|
notification_level: CategoryUser.notification_levels[:watching])
|
||||||
|
payload = serializer.as_json
|
||||||
|
expect(payload[:top_category_ids]).to eq([category2.id, category1.id])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import { moduleForWidget, widgetTest } from "helpers/widget-test";
|
|||||||
|
|
||||||
moduleForWidget("hamburger-menu");
|
moduleForWidget("hamburger-menu");
|
||||||
|
|
||||||
|
const maxCategoriesToDisplay = 6;
|
||||||
|
const topCategoryIds = [2, 3, 1];
|
||||||
|
|
||||||
widgetTest("prioritize faq", {
|
widgetTest("prioritize faq", {
|
||||||
template: '{{mount-widget widget="hamburger-menu"}}',
|
template: '{{mount-widget widget="hamburger-menu"}}',
|
||||||
|
|
||||||
@@ -125,42 +128,40 @@ widgetTest("general links", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
widgetTest("category links", {
|
widgetTest("top categories - anonymous", {
|
||||||
template: '{{mount-widget widget="hamburger-menu"}}',
|
template: '{{mount-widget widget="hamburger-menu"}}',
|
||||||
anonymous: true,
|
anonymous: true,
|
||||||
|
|
||||||
|
test(assert) {
|
||||||
|
const count = this.site.get("categoriesByCount").length;
|
||||||
|
const maximum =
|
||||||
|
count <= maxCategoriesToDisplay ? count : maxCategoriesToDisplay;
|
||||||
|
assert.equal(find(".category-link").length, maximum);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
widgetTest("top categories", {
|
||||||
|
template: '{{mount-widget widget="hamburger-menu"}}',
|
||||||
|
|
||||||
beforeEach() {
|
beforeEach() {
|
||||||
const cat = this.site.get("categoriesList")[0];
|
this.currentUser.set("top_category_ids", topCategoryIds);
|
||||||
|
|
||||||
const parent = Discourse.Category.create({
|
|
||||||
id: 1,
|
|
||||||
topic_count: 5,
|
|
||||||
name: "parent",
|
|
||||||
url: "https://test.com/parent",
|
|
||||||
show_subcategory_list: true,
|
|
||||||
topicTrackingState: cat.get("topicTrackingState")
|
|
||||||
});
|
|
||||||
const child = Discourse.Category.create({
|
|
||||||
id: 2,
|
|
||||||
parent_category_id: 1,
|
|
||||||
parentCategory: parent,
|
|
||||||
topic_count: 4,
|
|
||||||
name: "child",
|
|
||||||
url: "https://test.com/child",
|
|
||||||
topicTrackingState: cat.get("topicTrackingState")
|
|
||||||
});
|
|
||||||
|
|
||||||
parent.subcategories = [child];
|
|
||||||
|
|
||||||
const list = [parent, child];
|
|
||||||
this.site.set("categoriesList", list);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test(assert) {
|
test(assert) {
|
||||||
// if show_subcategory_list is enabled we suppress the categories from hamburger
|
assert.equal(find(".category-link").length, maxCategoriesToDisplay);
|
||||||
// this means that people can be confused about counts
|
|
||||||
assert.equal(this.$(".category-link").length, 1);
|
const categoriesList = this.site
|
||||||
assert.equal(this.$(".category-link .topics-count").text(), "9");
|
.get("categoriesByCount")
|
||||||
|
.reject(c => c.parent_category_id);
|
||||||
|
let ids = topCategoryIds
|
||||||
|
.concat(categoriesList.map(c => c.id))
|
||||||
|
.uniq()
|
||||||
|
.slice(0, maxCategoriesToDisplay);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
find(".category-link .category-name").text(),
|
||||||
|
ids.map(i => categoriesList.find(c => c.id === i).name).join("")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user