diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.hbs b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.hbs new file mode 100644 index 00000000000..f8541894e7c --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.hbs @@ -0,0 +1,22 @@ + + + {{#each this.sectionLinks as |sectionLink|}} + + + {{/each}} + + diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.js b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.js new file mode 100644 index 00000000000..39aea7eabbb --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/categories-section.js @@ -0,0 +1,36 @@ +import { cached } from "@glimmer/tracking"; +import { inject as service } from "@ember/service"; +import Component from "@glimmer/component"; +import CategorySectionLink from "discourse/lib/sidebar/user/categories-section/category-section-link"; + +export default class SidebarAnonymousCategoriesSection extends Component { + @service topicTrackingState; + @service site; + @service siteSettings; + + @cached + get sectionLinks() { + let categories = this.site.categoriesList; + + if (this.siteSettings.default_sidebar_categories) { + const defaultCategoryIds = this.siteSettings.default_sidebar_categories + .split("|") + .map((categoryId) => parseInt(categoryId, 10)); + + categories = categories.filter((category) => + defaultCategoryIds.includes(category.id) + ); + } else { + categories = categories + .filter((category) => !category.parent_category_id) + .slice(0, 5); + } + + return categories.map((category) => { + return new CategorySectionLink({ + category, + topicTrackingState: this.topicTrackingState, + }); + }); + } +} diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.hbs b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.hbs index 17f3217c72e..cc088f932db 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.hbs +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.hbs @@ -1,3 +1,6 @@ diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.js b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.js index 0c70e042df6..6cb84571db2 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.js +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/sections.js @@ -1,3 +1,6 @@ import Component from "@glimmer/component"; +import { inject as service } from "@ember/service"; -export default class SidebarAnonymousSections extends Component {} +export default class SidebarAnonymousSections extends Component { + @service siteSettings; +} diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.hbs b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.hbs new file mode 100644 index 00000000000..85dcfc0b32f --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.hbs @@ -0,0 +1,18 @@ + + + {{#each this.sectionLinks as |sectionLink|}} + + + {{/each}} + + diff --git a/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.js b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.js new file mode 100644 index 00000000000..0dc3804ba51 --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/sidebar/anonymous/tags-section.js @@ -0,0 +1,27 @@ +import { cached } from "@glimmer/tracking"; +import Component from "@glimmer/component"; +import { inject as service } from "@ember/service"; +import TagSectionLink from "discourse/lib/sidebar/user/tags-section/tag-section-link"; + +export default class SidebarAnonymousTagsSection extends Component { + @service router; + @service topicTrackingState; + @service site; + + @cached + get sectionLinks() { + let tags; + + if (this.site.anonymous_default_sidebar_tags) { + tags = this.site.anonymous_default_sidebar_tags; + } else { + tags = this.site.top_tags.slice(0, 5); + } + return tags.map((tagName) => { + return new TagSectionLink({ + tagName, + topicTrackingState: this.topicTrackingState, + }); + }); + } +} diff --git a/app/assets/javascripts/discourse/app/components/sidebar/user/tags-section.js b/app/assets/javascripts/discourse/app/components/sidebar/user/tags-section.js index f3b11416cfd..59649c991fd 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar/user/tags-section.js +++ b/app/assets/javascripts/discourse/app/components/sidebar/user/tags-section.js @@ -38,14 +38,14 @@ export default class SidebarUserTagsSection extends Component { if (tag.pm_only) { links.push( new PMTagSectionLink({ - tag, + tagName: tag.name, currentUser: this.currentUser, }) ); } else { links.push( new TagSectionLink({ - tag, + tagName: tag.name, topicTrackingState: this.topicTrackingState, }) ); diff --git a/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/pm-tag-section-link.js b/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/pm-tag-section-link.js index aec926b6013..fceac26abf6 100644 --- a/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/pm-tag-section-link.js +++ b/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/pm-tag-section-link.js @@ -1,15 +1,15 @@ export default class PMTagSectionLink { - constructor({ tag, currentUser }) { - this.tag = tag; + constructor({ tagName, currentUser }) { + this.tagName = tagName; this.currentUser = currentUser; } get name() { - return this.tag.name; + return this.tagName; } get models() { - return [this.currentUser, this.tag.name]; + return [this.currentUser, this.tagName]; } get route() { @@ -17,6 +17,6 @@ export default class PMTagSectionLink { } get text() { - return this.tag.name; + return this.tagName; } } diff --git a/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/tag-section-link.js b/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/tag-section-link.js index dd24165a494..48f55a317ec 100644 --- a/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/tag-section-link.js +++ b/app/assets/javascripts/discourse/app/lib/sidebar/user/tags-section/tag-section-link.js @@ -8,8 +8,8 @@ export default class TagSectionLink { @tracked totalUnread = 0; @tracked totalNew = 0; - constructor({ tag, topicTrackingState }) { - this.tagName = tag.name; + constructor({ tagName, topicTrackingState }) { + this.tagName = tagName; this.topicTrackingState = topicTrackingState; this.refreshCounts(); } diff --git a/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-categories-section-test.js b/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-categories-section-test.js new file mode 100644 index 00000000000..fa0e7717d31 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-categories-section-test.js @@ -0,0 +1,53 @@ +import { test } from "qunit"; +import { visit } from "@ember/test-helpers"; +import { + acceptance, + exists, + queryAll, +} from "discourse/tests/helpers/qunit-helpers"; + +acceptance("Sidebar - Anonymous Categories Section", function (needs) { + needs.settings({ + enable_experimental_sidebar_hamburger: true, + enable_sidebar: true, + suppress_uncategorized_badge: false, + }); + + test("category section links", async function (assert) { + await visit("/"); + + const categories = queryAll( + ".sidebar-section-categories .sidebar-section-link-wrapper" + ); + assert.strictEqual(categories.length, 6); + assert.strictEqual(categories[0].textContent.trim(), "support"); + assert.strictEqual(categories[1].textContent.trim(), "bug"); + assert.strictEqual(categories[2].textContent.trim(), "feature"); + assert.strictEqual(categories[3].textContent.trim(), "dev"); + assert.strictEqual(categories[4].textContent.trim(), "ux"); + + assert.ok( + exists("a.sidebar-section-link-more-categories"), + "more link is visible" + ); + }); + + test("default sidebar categories", async function (assert) { + this.siteSettings.default_sidebar_categories = "3|13|1"; + await visit("/"); + + const categories = queryAll( + ".sidebar-section-categories .sidebar-section-link-wrapper" + ); + + assert.strictEqual(categories.length, 4); + assert.strictEqual(categories[0].textContent.trim(), "bug"); + assert.strictEqual(categories[1].textContent.trim(), "meta"); + assert.strictEqual(categories[2].textContent.trim(), "blog"); + + assert.ok( + exists("a.sidebar-section-link-more-categories"), + "more link is visible" + ); + }); +}); diff --git a/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-tags-section-test.js b/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-tags-section-test.js new file mode 100644 index 00000000000..386e398a68f --- /dev/null +++ b/app/assets/javascripts/discourse/tests/acceptance/sidebar-anonymous-tags-section-test.js @@ -0,0 +1,89 @@ +import { test } from "qunit"; +import { visit } from "@ember/test-helpers"; +import { + acceptance, + exists, + queryAll, +} from "discourse/tests/helpers/qunit-helpers"; + +acceptance("Sidebar - Anonymous Tags Section", function (needs) { + needs.settings({ + enable_experimental_sidebar_hamburger: true, + enable_sidebar: true, + suppress_uncategorized_badge: false, + tagging_enabled: true, + }); + + needs.site({ + top_tags: ["design", "development", "fun"], + }); + + test("tag section links", async function (assert) { + await visit("/"); + + const categories = queryAll( + ".sidebar-section-tags .sidebar-section-link-wrapper" + ); + assert.strictEqual(categories.length, 4); + assert.strictEqual(categories[0].textContent.trim(), "design"); + assert.strictEqual(categories[1].textContent.trim(), "development"); + assert.strictEqual(categories[2].textContent.trim(), "fun"); + + assert.ok( + exists("a.sidebar-section-link-more-tags"), + "more link is visible" + ); + }); +}); + +acceptance("Sidebar - Anonymous Tags Section - default tags", function (needs) { + needs.settings({ + enable_experimental_sidebar_hamburger: true, + enable_sidebar: true, + suppress_uncategorized_badge: false, + tagging_enabled: true, + }); + + needs.site({ + top_tags: ["design", "development", "fun"], + anonymous_default_sidebar_tags: ["random", "meta"], + }); + + test("tag section links", async function (assert) { + await visit("/"); + + const categories = queryAll( + ".sidebar-section-tags .sidebar-section-link-wrapper" + ); + assert.strictEqual(categories.length, 3); + assert.strictEqual(categories[0].textContent.trim(), "random"); + assert.strictEqual(categories[1].textContent.trim(), "meta"); + + assert.ok( + exists("a.sidebar-section-link-more-tags"), + "more link is visible" + ); + }); +}); + +acceptance( + "Sidebar - Anonymous Tags Section - Tagging disabled", + function (needs) { + needs.settings({ + enable_experimental_sidebar_hamburger: true, + enable_sidebar: true, + suppress_uncategorized_badge: false, + tagging_enabled: false, + }); + + needs.site({ + top_tags: ["design", "development", "fun"], + }); + + test("tag section links", async function (assert) { + await visit("/"); + + assert.ok(!exists(".sidebar-section-tags"), "section is not visible"); + }); + } +); diff --git a/app/models/user.rb b/app/models/user.rb index fea9e07ebc8..61feea4144f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1670,6 +1670,15 @@ class User < ActiveRecord::Base categories_ids end + def sidebar_tags + return custom_sidebar_tags if custom_sidebar_tags.present? + if SiteSetting.default_sidebar_tags.present? + tag_names = SiteSetting.default_sidebar_tags.split("|") - DiscourseTagging.hidden_tag_names(guardian) + return Tag.where(name: tag_names) + end + Tag.none + end + protected def badge_grant @@ -1962,15 +1971,6 @@ class User < ActiveRecord::Base end end - def sidebar_tags - return custom_sidebar_tags if custom_sidebar_tags.present? - if SiteSetting.default_sidebar_tags.present? - tag_names = SiteSetting.default_sidebar_tags.split("|") - DiscourseTagging.hidden_tag_names(guardian) - return Tag.where(name: tag_names) - end - [] - end - def self.ensure_consistency! DB.exec <<~SQL UPDATE users diff --git a/app/serializers/site_serializer.rb b/app/serializers/site_serializer.rb index aa68f845f02..fa396d1a62d 100644 --- a/app/serializers/site_serializer.rb +++ b/app/serializers/site_serializer.rb @@ -35,7 +35,8 @@ class SiteSerializer < ApplicationSerializer :categories, :markdown_additional_options, :displayed_about_plugin_stat_groups, - :show_welcome_topic_banner + :show_welcome_topic_banner, + :anonymous_default_sidebar_tags ) has_many :archetypes, embed: :objects, serializer: ArchetypeSerializer @@ -218,6 +219,14 @@ class SiteSerializer < ApplicationSerializer Site.show_welcome_topic_banner?(scope) end + def anonymous_default_sidebar_tags + User.new.sidebar_tags.pluck(:name) + end + + def include_anonymous_default_sidebar_tags? + SiteSetting.default_sidebar_tags.present? + end + private def ordered_flags(flags) diff --git a/spec/serializers/site_serializer_spec.rb b/spec/serializers/site_serializer_spec.rb index f815b5afa07..2839ac774ef 100644 --- a/spec/serializers/site_serializer_spec.rb +++ b/spec/serializers/site_serializer_spec.rb @@ -124,4 +124,15 @@ RSpec.describe SiteSerializer do serialized = described_class.new(Site.new(admin_guardian), scope: admin_guardian, root: false).as_json expect(serialized[:show_welcome_topic_banner]).to eq(true) end + + it 'includes anonymous_default_sidebar_tags' do + Fabricate(:tag, name: "dev") + Fabricate(:tag, name: "random") + serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json + expect(serialized[:anonymous_default_sidebar_tags]).to eq(nil) + + SiteSetting.default_sidebar_tags = "dev|random" + serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json + expect(serialized[:anonymous_default_sidebar_tags]).to eq(["dev", "random"]) + end end