FEATURE: public custom sidebar sections visible to anonymous (#20931)
Previously, public custom sections were only visible to logged-in users. In this PR, we are making them visible to anonymous as well. The reason is that Community Section will be moved into custom section model to be easily editable by admins.
This commit is contained in:
parent
cd6d47e012
commit
e586f6052f
|
@ -0,0 +1,31 @@
|
|||
<div class="sidebar-custom-sections">
|
||||
{{#each this.sections as |section|}}
|
||||
<Sidebar::Section
|
||||
@sectionName={{section.slug}}
|
||||
@headerLinkText={{section.decoratedTitle}}
|
||||
@collapsable={{true}}
|
||||
>
|
||||
{{#each section.links as |link|}}
|
||||
{{#if link.external}}
|
||||
<Sidebar::SectionLink
|
||||
@linkName={{link.name}}
|
||||
@content={{replace-emoji link.name}}
|
||||
@prefixType="icon"
|
||||
@prefixValue={{link.icon}}
|
||||
@href={{link.value}}
|
||||
/>
|
||||
{{else}}
|
||||
<Sidebar::SectionLink
|
||||
@linkName={{link.name}}
|
||||
@route={{link.route}}
|
||||
@models={{link.models}}
|
||||
@query={{link.query}}
|
||||
@content={{replace-emoji link.name}}
|
||||
@prefixType="icon"
|
||||
@prefixValue={{link.icon}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</Sidebar::Section>
|
||||
{{/each}}
|
||||
</div>
|
|
@ -0,0 +1,17 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { inject as service } from "@ember/service";
|
||||
import Section from "discourse/components/sidebar/user/section";
|
||||
|
||||
export default class SidebarAnonymousCustomSections extends Component {
|
||||
@service router;
|
||||
@service site;
|
||||
|
||||
get sections() {
|
||||
return this.site.anonymous_sidebar_sections?.map((section) => {
|
||||
return new Section({
|
||||
section,
|
||||
router: this.router,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<div class="sidebar-sections sidebar-sections-anonymous">
|
||||
<Sidebar::Anonymous::CommunitySection @collapsable={{@collapsableSections}} />
|
||||
<Sidebar::Anonymous::CustomSections />
|
||||
<Sidebar::Anonymous::CategoriesSection
|
||||
@collapsable={{@collapsableSections}}
|
||||
/>
|
||||
|
|
|
@ -23,13 +23,13 @@ export default class Section {
|
|||
}
|
||||
|
||||
get decoratedTitle() {
|
||||
return this.section.public && this.currentUser.staff
|
||||
return this.section.public && this.currentUser?.staff
|
||||
? htmlSafe(`${iconHTML("globe")} ${this.section.title}`)
|
||||
: this.section.title;
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
if (!this.section.public || this.currentUser.staff) {
|
||||
if (!this.section.public || this.currentUser?.staff) {
|
||||
return [
|
||||
{
|
||||
action: () => {
|
||||
|
|
|
@ -25,6 +25,7 @@ class SidebarSectionsController < ApplicationController
|
|||
nil,
|
||||
group_ids: SiteSetting.enable_custom_sidebar_sections_map,
|
||||
)
|
||||
Site.clear_anon_cache!
|
||||
end
|
||||
|
||||
render json: SidebarSectionSerializer.new(sidebar_section)
|
||||
|
@ -48,6 +49,7 @@ class SidebarSectionsController < ApplicationController
|
|||
nil,
|
||||
group_ids: SiteSetting.enable_custom_sidebar_sections_map,
|
||||
)
|
||||
Site.clear_anon_cache!
|
||||
end
|
||||
|
||||
render json: SidebarSectionSerializer.new(sidebar_section)
|
||||
|
|
|
@ -23,6 +23,8 @@ class SidebarSection < ActiveRecord::Base
|
|||
maximum: MAX_TITLE_LENGTH,
|
||||
}
|
||||
|
||||
scope :public_sections, -> { where("public") }
|
||||
|
||||
private
|
||||
|
||||
def set_system_user_for_public_section
|
||||
|
|
|
@ -79,8 +79,9 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
|
||||
def sidebar_sections
|
||||
SidebarSection
|
||||
.public_sections
|
||||
.or(SidebarSection.where(user_id: object.id))
|
||||
.includes(sidebar_section_links: :linkable)
|
||||
.where("public OR user_id = ?", object.id)
|
||||
.order("(public IS TRUE) DESC")
|
||||
.map { |section| SidebarSectionSerializer.new(section, root: false) }
|
||||
end
|
||||
|
|
|
@ -39,6 +39,7 @@ class SiteSerializer < ApplicationSerializer
|
|||
:displayed_about_plugin_stat_groups,
|
||||
:show_welcome_topic_banner,
|
||||
:anonymous_default_sidebar_tags,
|
||||
:anonymous_sidebar_sections,
|
||||
:whispers_allowed_groups_names,
|
||||
)
|
||||
|
||||
|
@ -260,6 +261,17 @@ class SiteSerializer < ApplicationSerializer
|
|||
SiteSetting.default_sidebar_tags.present?
|
||||
end
|
||||
|
||||
def anonymous_sidebar_sections
|
||||
SidebarSection
|
||||
.public_sections
|
||||
.includes(sidebar_section_links: :linkable)
|
||||
.map { |section| SidebarSectionSerializer.new(section, root: false) }
|
||||
end
|
||||
|
||||
def include_anonymous_sidebar_sections?
|
||||
scope.anonymous?
|
||||
end
|
||||
|
||||
def whispers_allowed_groups_names
|
||||
Group.where(id: SiteSetting.whispers_allowed_groups_map).pluck(:name)
|
||||
end
|
||||
|
|
|
@ -192,6 +192,70 @@ RSpec.describe SiteSerializer do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#anonymous_sidebar_sections" do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:public_sidebar_section) do
|
||||
Fabricate(:sidebar_section, title: "Public section", public: true)
|
||||
end
|
||||
fab!(:private_sidebar_section) do
|
||||
Fabricate(:sidebar_section, title: "Private section", user: user, public: false)
|
||||
end
|
||||
|
||||
it "is not included in the serialised object when user is not anonymous" do
|
||||
guardian = Guardian.new(user)
|
||||
|
||||
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
|
||||
end
|
||||
|
||||
it "includes only public sidebar sections serialised object when user is anonymous" do
|
||||
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
|
||||
expect(serialized[:anonymous_sidebar_sections].map(&:title)).to eq(["Public section"])
|
||||
end
|
||||
|
||||
it "eager loads sidebar_urls" do
|
||||
public_section_link =
|
||||
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
|
||||
# warmup
|
||||
described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
|
||||
|
||||
initial_count =
|
||||
track_sql_queries do
|
||||
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
|
||||
|
||||
expect(
|
||||
serialized[:anonymous_sidebar_sections].map { |sidebar_section| sidebar_section.id },
|
||||
).to eq([public_sidebar_section.id])
|
||||
|
||||
expect(serialized[:anonymous_sidebar_sections].first.links.map { |link| link.id }).to eq(
|
||||
[public_section_link.linkable.id],
|
||||
)
|
||||
end.count
|
||||
|
||||
public_section_link_2 =
|
||||
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
|
||||
public_section_link_3 =
|
||||
Fabricate(:custom_sidebar_section_link, user: user, sidebar_section: public_sidebar_section)
|
||||
|
||||
final_count =
|
||||
track_sql_queries do
|
||||
serialized = described_class.new(Site.new(guardian), scope: guardian, root: false).as_json
|
||||
|
||||
expect(
|
||||
serialized[:anonymous_sidebar_sections].map { |sidebar_section| sidebar_section.id },
|
||||
).to eq([public_sidebar_section.id])
|
||||
|
||||
expect(serialized[:anonymous_sidebar_sections].first.links.map { |link| link.id }).to eq(
|
||||
[
|
||||
public_section_link.linkable.id,
|
||||
public_section_link_2.linkable.id,
|
||||
public_section_link_3.linkable.id,
|
||||
],
|
||||
)
|
||||
end.count
|
||||
expect(final_count).to eq(initial_count)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#top_tags" do
|
||||
fab!(:tag) { Fabricate(:tag) }
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
Fabricate(:group_user, group: group, user: user)
|
||||
Fabricate(:group_user, group: group, user: admin)
|
||||
SiteSetting.enable_custom_sidebar_sections = group.id.to_s
|
||||
sign_in user
|
||||
end
|
||||
|
||||
it "allows the user to create custom section" do
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
sidebar.open_new_custom_section
|
||||
|
||||
|
@ -30,11 +30,12 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("My section")
|
||||
expect(sidebar).to have_section("My section")
|
||||
expect(sidebar).to have_link("Sidebar Tags")
|
||||
end
|
||||
|
||||
it "allows the user to create custom section with /my link" do
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
sidebar.open_new_custom_section
|
||||
|
||||
|
@ -49,11 +50,12 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("My section")
|
||||
expect(sidebar).to have_section("My section")
|
||||
expect(sidebar).to have_link("My preferences")
|
||||
end
|
||||
|
||||
it "allows the user to create custom section with external link" do
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
sidebar.open_new_custom_section
|
||||
|
||||
|
@ -71,7 +73,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("My section")
|
||||
expect(sidebar).to have_section("My section")
|
||||
expect(sidebar).to have_link("Discourse Homepage", href: "https://discourse.org")
|
||||
end
|
||||
|
||||
|
@ -82,6 +84,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
sidebar_url_2 = Fabricate(:sidebar_url, name: "Sidebar Categories", value: "/categories")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_2)
|
||||
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
|
||||
sidebar.edit_custom_section("My section")
|
||||
|
@ -93,7 +96,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("Edited section")
|
||||
expect(sidebar).to have_section("Edited section")
|
||||
expect(sidebar).to have_link("Edited Tag")
|
||||
|
||||
expect(page).not_to have_link("Sidebar Categories")
|
||||
|
@ -106,6 +109,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
sidebar_url_2 = Fabricate(:sidebar_url, name: "Sidebar Categories", value: "/categories")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_2)
|
||||
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
within(".sidebar-custom-sections .sidebar-section-link-wrapper:nth-child(1)") do
|
||||
expect(page).to have_css(".sidebar-section-link-sidebar-tags")
|
||||
|
@ -127,15 +131,16 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
end
|
||||
|
||||
it "does not allow the user to edit public section" do
|
||||
sidebar_section = Fabricate(:sidebar_section, title: "Public section", user: user, public: true)
|
||||
sidebar_section = Fabricate(:sidebar_section, title: "Public section", public: true)
|
||||
sidebar_url_1 = Fabricate(:sidebar_url, name: "Sidebar Tags", value: "/tags")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_1)
|
||||
sidebar_url_2 = Fabricate(:sidebar_url, name: "Sidebar Categories", value: "/categories")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_2)
|
||||
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
|
||||
expect(page).to have_button("Public section")
|
||||
expect(sidebar).to have_section("Public section")
|
||||
|
||||
find(".sidebar-section[data-section-name='public-section']").hover
|
||||
|
||||
|
@ -153,6 +158,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
sidebar_url_1 = Fabricate(:sidebar_url, name: "tags", value: "/tags")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_1)
|
||||
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
|
||||
sidebar.edit_custom_section("My section")
|
||||
|
@ -160,7 +166,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
section_modal.delete
|
||||
section_modal.confirm_delete
|
||||
|
||||
expect(page).not_to have_button("My section")
|
||||
expect(sidebar).not_to have_section("My section")
|
||||
end
|
||||
|
||||
it "allows admin to create, edit and delete public section" do
|
||||
|
@ -173,7 +179,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
section_modal.mark_as_public
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("Public section")
|
||||
expect(sidebar).to have_section("Public section")
|
||||
expect(sidebar).to have_link("Sidebar Tags")
|
||||
expect(page).to have_css(".sidebar-section[data-section-name='public-section'] .d-icon-globe")
|
||||
|
||||
|
@ -181,16 +187,30 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
section_modal.fill_name("Edited public section")
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("Edited public section")
|
||||
expect(sidebar).to have_section("Edited public section")
|
||||
|
||||
sidebar.edit_custom_section("Edited public section")
|
||||
section_modal.delete
|
||||
section_modal.confirm_delete
|
||||
|
||||
expect(page).not_to have_button("Edited public section")
|
||||
expect(sidebar).not_to have_section("Edited public section")
|
||||
end
|
||||
|
||||
it "shows anonymous public sections" do
|
||||
sidebar_section = Fabricate(:sidebar_section, title: "Public section", public: true)
|
||||
sidebar_url_1 = Fabricate(:sidebar_url, name: "Sidebar Tags", value: "/tags")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_1)
|
||||
sidebar_url_2 = Fabricate(:sidebar_url, name: "Sidebar Categories", value: "/categories")
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_2)
|
||||
|
||||
visit("/latest")
|
||||
expect(sidebar).to have_section("Public section")
|
||||
expect(sidebar).to have_link("Sidebar Tags")
|
||||
expect(sidebar).to have_link("Sidebar Categories")
|
||||
end
|
||||
|
||||
it "validates custom section fields" do
|
||||
sign_in user
|
||||
visit("/latest")
|
||||
sidebar.open_new_custom_section
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ module PageObjects
|
|||
def custom_section_modal_title
|
||||
find("#discourse-modal-title")
|
||||
end
|
||||
|
||||
def has_section?(name)
|
||||
find(".sidebar-wrapper").has_button?(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue