DEV: configurable public sidebar sections (#20303)
Extension of https://github.com/discourse/discourse/pull/20057 Admin can create a public session visible to everyone. An additional checkbox is displayed for staff members.
This commit is contained in:
parent
e3ee81aa3c
commit
b9d037770c
|
@ -2,14 +2,9 @@
|
|||
{{#each this.sections as |section|}}
|
||||
<Sidebar::Section
|
||||
@sectionName={{section.slug}}
|
||||
@headerLinkText={{section.title}}
|
||||
@headerLinkText={{section.decoratedTitle}}
|
||||
@collapsable={{true}}
|
||||
@headerActions={{array
|
||||
(hash
|
||||
action=(action this.editSection section)
|
||||
title=(i18n "sidebar.sections.custom.edit")
|
||||
)
|
||||
}}
|
||||
@headerActions={{section.headerActions}}
|
||||
@headerActionsIcon="pencil-alt"
|
||||
>
|
||||
{{#each section.links as |link|}}
|
||||
|
|
|
@ -1,15 +1,43 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { inject as service } from "@ember/service";
|
||||
import RouteInfoHelper from "discourse/lib/sidebar/route-info-helper";
|
||||
import I18n from "I18n";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
||||
export default class SidebarUserCustomSections extends Component {
|
||||
@service currentUser;
|
||||
@service router;
|
||||
@service messageBus;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.messageBus.subscribe("/refresh-sidebar-sections", this._refresh);
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
this.messageBus.unsubscribe("/refresh-sidebar-sections");
|
||||
}
|
||||
|
||||
get sections() {
|
||||
this.currentUser.sidebarSections.forEach((section) => {
|
||||
if (!section.public || this.currentUser.staff) {
|
||||
section.headerActions = [
|
||||
{
|
||||
action: () => {
|
||||
return showModal("sidebar-section-form", { model: section });
|
||||
},
|
||||
title: I18n.t("sidebar.sections.custom.edit"),
|
||||
},
|
||||
];
|
||||
}
|
||||
section.decoratedTitle =
|
||||
section.public && this.currentUser.staff
|
||||
? htmlSafe(`${iconHTML("globe")} ${section.title}`)
|
||||
: section.title;
|
||||
section.links.forEach((link) => {
|
||||
const routeInfoHelper = new RouteInfoHelper(this.router, link.value);
|
||||
link.route = routeInfoHelper.route;
|
||||
|
@ -20,8 +48,10 @@ export default class SidebarUserCustomSections extends Component {
|
|||
return this.currentUser.sidebarSections;
|
||||
}
|
||||
|
||||
@action
|
||||
editSection(section) {
|
||||
showModal("sidebar-section-form", { model: section });
|
||||
@bind
|
||||
_refresh() {
|
||||
return ajax("/sidebar_sections.json", {}).then((json) => {
|
||||
this.currentUser.set("sidebar_sections", json.sidebar_sections);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ class Section {
|
|||
@tracked title;
|
||||
@tracked links;
|
||||
|
||||
constructor({ title, links, id }) {
|
||||
constructor({ title, links, id, publicSection }) {
|
||||
this.title = title;
|
||||
this.public = publicSection;
|
||||
this.links = links;
|
||||
this.id = id;
|
||||
}
|
||||
|
@ -112,6 +113,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||
if (this.model) {
|
||||
return new Section({
|
||||
title: this.model.title,
|
||||
publicSection: this.model.public,
|
||||
links: A(
|
||||
this.model.links.map(
|
||||
(link) =>
|
||||
|
@ -140,6 +142,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||
dataType: "json",
|
||||
data: JSON.stringify({
|
||||
title: this.model.title,
|
||||
public: this.model.public,
|
||||
links: this.model.links.map((link) => {
|
||||
return {
|
||||
icon: link.icon,
|
||||
|
@ -168,6 +171,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||
dataType: "json",
|
||||
data: JSON.stringify({
|
||||
title: this.model.title,
|
||||
public: this.model.public,
|
||||
links: this.model.links.map((link) => {
|
||||
return {
|
||||
id: link.id,
|
||||
|
|
|
@ -69,6 +69,18 @@
|
|||
@icon="plus"
|
||||
@label="sidebar.sections.custom.links.add"
|
||||
/>
|
||||
{{#if this.currentUser.staff}}
|
||||
<div class="row-wrapper">
|
||||
<label class="checkbox-label">
|
||||
<Input
|
||||
@type="checkbox"
|
||||
@checked={{this.model.public}}
|
||||
class="mark-public"
|
||||
/>
|
||||
{{i18n "sidebar.sections.custom.public"}}
|
||||
</label>
|
||||
</div>
|
||||
{{/if}}
|
||||
</form>
|
||||
</DModalBody>
|
||||
|
||||
|
|
|
@ -130,6 +130,14 @@
|
|||
.sidebar-section-wrapper {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.d-icon-globe {
|
||||
position: absolute;
|
||||
left: 0.5em;
|
||||
height: 0.75em;
|
||||
width: 0.75em;
|
||||
margin-top: 0.15em;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.sidebar-section-form-modal {
|
||||
.modal-inner-container {
|
||||
|
@ -138,7 +146,7 @@
|
|||
form {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
input {
|
||||
.input-group input {
|
||||
width: 100%;
|
||||
}
|
||||
input.warning {
|
||||
|
|
|
@ -3,6 +3,16 @@
|
|||
class SidebarSectionsController < ApplicationController
|
||||
requires_login
|
||||
before_action :check_if_member_of_group
|
||||
before_action :check_access_if_public
|
||||
|
||||
def index
|
||||
sections =
|
||||
SidebarSection
|
||||
.where("public OR user_id = ?", current_user.id)
|
||||
.order("(public IS TRUE) DESC")
|
||||
.map { |section| SidebarSectionSerializer.new(section, root: false) }
|
||||
render json: sections
|
||||
end
|
||||
|
||||
def create
|
||||
sidebar_section =
|
||||
|
@ -10,6 +20,15 @@ class SidebarSectionsController < ApplicationController
|
|||
section_params.merge(user: current_user, sidebar_urls_attributes: links_params),
|
||||
)
|
||||
|
||||
if sidebar_section.public?
|
||||
StaffActionLogger.new(current_user).log_create_public_sidebar_section(sidebar_section)
|
||||
MessageBus.publish(
|
||||
"/refresh-sidebar-sections",
|
||||
nil,
|
||||
group_ids: SiteSetting.enable_custom_sidebar_sections_map,
|
||||
)
|
||||
end
|
||||
|
||||
render json: SidebarSectionSerializer.new(sidebar_section)
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
render_json_error(e.record.errors.full_messages.first)
|
||||
|
@ -21,6 +40,15 @@ class SidebarSectionsController < ApplicationController
|
|||
|
||||
sidebar_section.update!(section_params.merge(sidebar_urls_attributes: links_params))
|
||||
|
||||
if sidebar_section.public?
|
||||
StaffActionLogger.new(current_user).log_update_public_sidebar_section(sidebar_section)
|
||||
MessageBus.publish(
|
||||
"/refresh-sidebar-sections",
|
||||
nil,
|
||||
group_ids: SiteSetting.enable_custom_sidebar_sections_map,
|
||||
)
|
||||
end
|
||||
|
||||
render json: SidebarSectionSerializer.new(sidebar_section)
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
render_json_error(e.record.errors.full_messages.first)
|
||||
|
@ -32,13 +60,22 @@ class SidebarSectionsController < ApplicationController
|
|||
sidebar_section = SidebarSection.find_by(id: section_params["id"])
|
||||
@guardian.ensure_can_delete!(sidebar_section)
|
||||
sidebar_section.destroy!
|
||||
|
||||
if sidebar_section.public?
|
||||
StaffActionLogger.new(current_user).log_destroy_public_sidebar_section(sidebar_section)
|
||||
MessageBus.publish(
|
||||
"/refresh-sidebar-sections",
|
||||
nil,
|
||||
group_ids: SiteSetting.enable_custom_sidebar_sections_map,
|
||||
)
|
||||
end
|
||||
render json: SidebarSectionSerializer.new(sidebar_section)
|
||||
rescue Discourse::InvalidAccess
|
||||
render json: failed_json, status: 403
|
||||
end
|
||||
|
||||
def section_params
|
||||
params.permit(:id, :title)
|
||||
params.permit(:id, :title, :public)
|
||||
end
|
||||
|
||||
def links_params
|
||||
|
@ -52,4 +89,11 @@ class SidebarSectionsController < ApplicationController
|
|||
raise Discourse::InvalidAccess
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_access_if_public
|
||||
return true if !params[:public]
|
||||
raise Discourse::InvalidAccess.new if !guardian.can_create_public_sidebar_section?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,7 @@ end
|
|||
# title :string(30) not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# public :boolean default(FALSE), not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
@ -120,6 +120,9 @@ class UserHistory < ActiveRecord::Base
|
|||
watched_word_destroy: 98,
|
||||
delete_group: 99,
|
||||
permanently_delete_post_revisions: 100,
|
||||
create_public_sidebar_section: 101,
|
||||
update_public_sidebar_section: 102,
|
||||
destroy_public_sidebar_section: 103,
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -215,6 +218,9 @@ class UserHistory < ActiveRecord::Base
|
|||
watched_word_destroy
|
||||
delete_group
|
||||
permanently_delete_post_revisions
|
||||
create_public_sidebar_section
|
||||
update_public_sidebar_section
|
||||
destroy_public_sidebar_section
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -77,6 +77,13 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
|
||||
has_one :user_option, embed: :object, serializer: CurrentUserOptionSerializer
|
||||
|
||||
def sidebar_sections
|
||||
SidebarSection
|
||||
.where("public OR user_id = ?", object.id)
|
||||
.order("(public IS TRUE) DESC")
|
||||
.map { |section| SidebarSectionSerializer.new(section, root: false) }
|
||||
end
|
||||
|
||||
def groups
|
||||
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SidebarSectionSerializer < ApplicationSerializer
|
||||
attributes :id, :title, :links, :slug
|
||||
attributes :id, :title, :links, :slug, :public
|
||||
|
||||
def links
|
||||
object.sidebar_section_links.map(&:linkable)
|
||||
|
|
|
@ -964,6 +964,32 @@ class StaffActionLogger
|
|||
)
|
||||
end
|
||||
|
||||
def log_create_public_sidebar_section(section)
|
||||
UserHistory.create!(
|
||||
action: UserHistory.actions[:create_public_sidebar_section],
|
||||
acting_user_id: @admin.id,
|
||||
subject: section.title,
|
||||
details: custom_section_details(section),
|
||||
)
|
||||
end
|
||||
|
||||
def log_update_public_sidebar_section(section)
|
||||
UserHistory.create!(
|
||||
action: UserHistory.actions[:update_public_sidebar_section],
|
||||
acting_user_id: @admin.id,
|
||||
subject: section.title,
|
||||
details: custom_section_details(section),
|
||||
)
|
||||
end
|
||||
|
||||
def log_destroy_public_sidebar_section(section)
|
||||
UserHistory.create!(
|
||||
action: UserHistory.actions[:destroy_public_sidebar_section],
|
||||
acting_user_id: @admin.id,
|
||||
subject: section.title,
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_changes(changes)
|
||||
|
@ -990,4 +1016,9 @@ class StaffActionLogger
|
|||
def validate_category(category)
|
||||
raise Discourse::InvalidParameters.new(:category) unless category && category.is_a?(Category)
|
||||
end
|
||||
|
||||
def custom_section_details(section)
|
||||
urls = section.sidebar_urls.map { |url| "#{url.name} - #{url.value}" }
|
||||
"links: #{urls.join(", ")}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4373,6 +4373,7 @@ en:
|
|||
save: "Save"
|
||||
delete: "Delete"
|
||||
delete_confirm: "Are you sure you want to delete this section?"
|
||||
public: "Make this section public and visible to everyone"
|
||||
links:
|
||||
icon: "Icon"
|
||||
name: "Name"
|
||||
|
@ -5426,6 +5427,9 @@ en:
|
|||
delete_group: "delete group"
|
||||
watched_word_create: "add watched word"
|
||||
watched_word_destroy: "delete watched word"
|
||||
create_public_sidebar_section: "create public sidebar section"
|
||||
update_public_sidebar_section: "update public sidebar section"
|
||||
destroy_public_sidebar_section: "destroy public sidebar section"
|
||||
screened_emails:
|
||||
title: "Screened Emails"
|
||||
description: "When someone tries to create a new account, the following email addresses will be checked and the registration will be blocked, or some other action performed."
|
||||
|
|
|
@ -1589,7 +1589,7 @@ Discourse::Application.routes.draw do
|
|||
put "user-status" => "user_status#set"
|
||||
delete "user-status" => "user_status#clear"
|
||||
|
||||
resources :sidebar_sections, only: %i[create update destroy]
|
||||
resources :sidebar_sections, only: %i[index create update destroy]
|
||||
|
||||
get "*url", to: "permalinks#show", constraints: PermalinkConstraint.new
|
||||
end
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPublicToSidebarSections < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :sidebar_sections, :public, :boolean, null: false, default: false
|
||||
end
|
||||
end
|
|
@ -1,11 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SidebarGuardian
|
||||
def can_create_public_sidebar_section?
|
||||
@user.staff?
|
||||
end
|
||||
|
||||
def can_edit_sidebar_section?(sidebar_section)
|
||||
return @user.staff? if sidebar_section.public?
|
||||
is_my_own?(sidebar_section)
|
||||
end
|
||||
|
||||
def can_delete_sidebar_section?(sidebar_section)
|
||||
return @user.staff? if sidebar_section.public?
|
||||
is_my_own?(sidebar_section)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,14 +2,39 @@
|
|||
|
||||
RSpec.describe SidebarSectionsController do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
|
||||
before do
|
||||
### TODO remove when enable_custom_sidebar_sections SiteSetting is removed
|
||||
group = Fabricate(:group)
|
||||
Fabricate(:group_user, group: group, user: user)
|
||||
Fabricate(:group_user, group: group, user: admin)
|
||||
SiteSetting.enable_custom_sidebar_sections = group.id.to_s
|
||||
end
|
||||
|
||||
describe "#index" do
|
||||
fab!(:sidebar_section) { Fabricate(:sidebar_section, title: "private section", user: user) }
|
||||
fab!(:sidebar_url_1) { Fabricate(:sidebar_url, name: "tags", value: "/tags") }
|
||||
fab!(:section_link_1) do
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_1)
|
||||
end
|
||||
fab!(:sidebar_section_2) do
|
||||
Fabricate(:sidebar_section, title: "public section", user: admin, public: true)
|
||||
end
|
||||
fab!(:section_link_2) do
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section, linkable: sidebar_url_1)
|
||||
end
|
||||
|
||||
it "returns public and private sections" do
|
||||
sign_in(user)
|
||||
get "/sidebar_sections.json"
|
||||
expect(response.status).to eq(200)
|
||||
expect(response.parsed_body["sidebar_sections"].map { |section| section["title"] }).to eq(
|
||||
["public section", "private section"],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
it "is not available for anonymous" do
|
||||
post "/sidebar_sections.json",
|
||||
|
@ -20,7 +45,6 @@ RSpec.describe SidebarSectionsController do
|
|||
{ icon: "link", name: "tags", value: "/tags" },
|
||||
],
|
||||
}
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
|
@ -42,6 +66,8 @@ RSpec.describe SidebarSectionsController do
|
|||
|
||||
expect(sidebar_section.title).to eq("custom section")
|
||||
expect(sidebar_section.user).to eq(user)
|
||||
expect(sidebar_section.public).to be false
|
||||
expect(UserHistory.count).to eq(0)
|
||||
expect(sidebar_section.sidebar_urls.count).to eq(2)
|
||||
expect(sidebar_section.sidebar_urls.first.icon).to eq("link")
|
||||
expect(sidebar_section.sidebar_urls.first.name).to eq("categories")
|
||||
|
@ -50,6 +76,43 @@ RSpec.describe SidebarSectionsController do
|
|||
expect(sidebar_section.sidebar_urls.second.name).to eq("tags")
|
||||
expect(sidebar_section.sidebar_urls.second.value).to eq("/tags")
|
||||
end
|
||||
|
||||
it "does not allow regular user to create public section" do
|
||||
sign_in(user)
|
||||
post "/sidebar_sections.json",
|
||||
params: {
|
||||
title: "custom section",
|
||||
public: true,
|
||||
links: [
|
||||
{ icon: "link", name: "categories", value: "/categories" },
|
||||
{ icon: "address-book", name: "tags", value: "/tags" },
|
||||
],
|
||||
}
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "allows admin to create public section" do
|
||||
sign_in(admin)
|
||||
post "/sidebar_sections.json",
|
||||
params: {
|
||||
title: "custom section",
|
||||
public: true,
|
||||
links: [
|
||||
{ icon: "link", name: "categories", value: "/categories" },
|
||||
{ icon: "address-book", name: "tags", value: "/tags" },
|
||||
],
|
||||
}
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
sidebar_section = SidebarSection.last
|
||||
expect(sidebar_section.title).to eq("custom section")
|
||||
expect(sidebar_section.public).to be true
|
||||
|
||||
user_history = UserHistory.last
|
||||
expect(user_history.action).to eq(UserHistory.actions[:create_public_sidebar_section])
|
||||
expect(user_history.subject).to eq("custom section")
|
||||
expect(user_history.details).to eq("links: categories - /categories, tags - /tags")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
|
@ -77,12 +140,39 @@ RSpec.describe SidebarSectionsController do
|
|||
expect(response.status).to eq(200)
|
||||
|
||||
expect(sidebar_section.reload.title).to eq("custom section edited")
|
||||
expect(UserHistory.count).to eq(0)
|
||||
expect(sidebar_url_1.reload.name).to eq("latest")
|
||||
expect(sidebar_url_1.value).to eq("/latest")
|
||||
expect { section_link_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect { sidebar_url_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
it "allows admin to update public section and links" do
|
||||
sign_in(admin)
|
||||
sidebar_section.update!(user: admin, public: true)
|
||||
put "/sidebar_sections/#{sidebar_section.id}.json",
|
||||
params: {
|
||||
title: "custom section edited",
|
||||
links: [
|
||||
{ icon: "link", id: sidebar_url_1.id, name: "latest", value: "/latest" },
|
||||
{ icon: "link", id: sidebar_url_2.id, name: "tags", value: "/tags", _destroy: "1" },
|
||||
],
|
||||
}
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
expect(sidebar_section.reload.title).to eq("custom section edited")
|
||||
expect(sidebar_url_1.reload.name).to eq("latest")
|
||||
expect(sidebar_url_1.value).to eq("/latest")
|
||||
expect { section_link_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect { sidebar_url_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
|
||||
user_history = UserHistory.last
|
||||
expect(user_history.action).to eq(UserHistory.actions[:update_public_sidebar_section])
|
||||
expect(user_history.subject).to eq("custom section edited")
|
||||
expect(user_history.details).to eq("links: latest - /latest")
|
||||
end
|
||||
|
||||
it "doesn't allow to edit other's sections" do
|
||||
sidebar_section_2 = Fabricate(:sidebar_section)
|
||||
sidebar_url_3 = Fabricate(:sidebar_url, name: "other_tags", value: "/tags")
|
||||
|
@ -97,6 +187,20 @@ RSpec.describe SidebarSectionsController do
|
|||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "doesn't allow to edit public sections" do
|
||||
sign_in(user)
|
||||
sidebar_section.update!(public: true)
|
||||
put "/sidebar_sections/#{sidebar_section.id}.json",
|
||||
params: {
|
||||
title: "custom section edited",
|
||||
links: [
|
||||
{ icon: "link", id: sidebar_url_1.id, name: "latest", value: "/latest" },
|
||||
{ icon: "link", id: sidebar_url_2.id, name: "tags", value: "/tags", _destroy: "1" },
|
||||
],
|
||||
}
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "doesn't allow to edit other's links" do
|
||||
sidebar_url_3 = Fabricate(:sidebar_url, name: "other_tags", value: "/tags")
|
||||
Fabricate(
|
||||
|
@ -127,6 +231,22 @@ RSpec.describe SidebarSectionsController do
|
|||
expect(response.status).to eq(200)
|
||||
|
||||
expect { sidebar_section.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
|
||||
expect(UserHistory.count).to eq(0)
|
||||
end
|
||||
|
||||
it "allows admin to delete public section" do
|
||||
sign_in(admin)
|
||||
sidebar_section.update!(user: admin, public: true)
|
||||
delete "/sidebar_sections/#{sidebar_section.id}.json"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
expect { sidebar_section.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
|
||||
user_history = UserHistory.last
|
||||
expect(user_history.action).to eq(UserHistory.actions[:destroy_public_sidebar_section])
|
||||
expect(user_history.subject).to eq("Sidebar section")
|
||||
end
|
||||
|
||||
it "doesn't allow to delete other's sidebar section" do
|
||||
|
@ -136,5 +256,13 @@ RSpec.describe SidebarSectionsController do
|
|||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "doesn't allow to delete public sidebar section" do
|
||||
sign_in(user)
|
||||
sidebar_section.update!(public: true)
|
||||
delete "/sidebar_sections/#{sidebar_section.id}.json"
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
describe "Custom sidebar sections", type: :system, js: true do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
let(:section_modal) { PageObjects::Modals::SidebarSectionForm.new }
|
||||
let(:sidebar) { PageObjects::Components::Sidebar.new }
|
||||
|
||||
|
@ -9,6 +10,7 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
### TODO remove when enable_custom_sidebar_sections SiteSetting is removed
|
||||
group = Fabricate(:group)
|
||||
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
|
||||
|
@ -55,6 +57,23 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
expect(page).not_to have_link("Sidebar Categories")
|
||||
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_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(page).to have_button("Public section")
|
||||
find(".sidebar-section-public-section").hover
|
||||
expect(page).not_to have_css(
|
||||
".sidebar-section-public-section button.sidebar-section-header-button",
|
||||
)
|
||||
expect(page).not_to have_css(".sidebar-section-public-section .d-icon-globe")
|
||||
end
|
||||
|
||||
it "allows the user to delete custom section" do
|
||||
sidebar_section = Fabricate(:sidebar_section, title: "My section", user: user)
|
||||
sidebar_url_1 = Fabricate(:sidebar_url, name: "tags", value: "/tags")
|
||||
|
@ -69,4 +88,31 @@ describe "Custom sidebar sections", type: :system, js: true do
|
|||
|
||||
expect(page).not_to have_button("My section")
|
||||
end
|
||||
|
||||
it "allows admin to create, edit and delete public section" do
|
||||
sign_in admin
|
||||
visit("/latest")
|
||||
sidebar.open_new_custom_section
|
||||
|
||||
section_modal.fill_name("Public section")
|
||||
section_modal.fill_link("Sidebar Tags", "/tags")
|
||||
section_modal.mark_as_public
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("Public section")
|
||||
expect(page).to have_link("Sidebar Tags")
|
||||
expect(page).to have_css(".sidebar-section-public-section .d-icon-globe")
|
||||
|
||||
sidebar.edit_custom_section("Public section")
|
||||
section_modal.fill_name("Edited public section")
|
||||
section_modal.save
|
||||
|
||||
expect(page).to have_button("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")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,10 @@ module PageObjects
|
|||
fill_in "link-url", with: url, match: :first
|
||||
end
|
||||
|
||||
def mark_as_public
|
||||
find(".modal .mark-public").click
|
||||
end
|
||||
|
||||
def remove_last_link
|
||||
all(".delete-link").last.click
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue