discourse/app/controllers/sidebar_sections_controller.rb
Krzysztof Kotlarek 9f78ff5572
FEATURE: modal for admins to edit Community section (#21668)
Allow admins to edit Community section. This includes drag and drop reorder, change names, delete and reset to default.

Visual improvements introduced in edit community section modal are available in edit custom section form as well. For example:
- drag and drop links to change their position;
- smaller icon picker.
2023-05-29 15:20:23 +10:00

144 lines
4.3 KiB
Ruby

# frozen_string_literal: true
class SidebarSectionsController < ApplicationController
requires_login
before_action :check_access_if_public
def index
sections =
SidebarSection
.strict_loading
.includes(:sidebar_urls)
.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 =
SidebarSection.create!(section_params.merge(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)
Site.clear_anon_cache!
end
render_serialized(sidebar_section, SidebarSectionSerializer)
rescue ActiveRecord::RecordInvalid => e
render_json_error(e.record.errors.full_messages.first)
end
def update
sidebar_section = SidebarSection.find_by(id: section_params["id"])
@guardian.ensure_can_edit!(sidebar_section)
ActiveRecord::Base.transaction do
sidebar_section.update!(section_params.merge(sidebar_urls_attributes: links_params))
sidebar_section.sidebar_section_links.update_all(user_id: sidebar_section.user_id)
order =
sidebar_section
.sidebar_urls
.sort_by do |url|
links_params.index { |link| link["name"] == url.name && link["value"] == url.value } ||
-1
end
.each_with_index
.map { |url, index| [url.id, index] }
.to_h
set_order(sidebar_section, order)
end
if sidebar_section.public?
StaffActionLogger.new(current_user).log_update_public_sidebar_section(sidebar_section)
MessageBus.publish("/refresh-sidebar-sections", nil)
Site.clear_anon_cache!
end
render_serialized(sidebar_section.reload, SidebarSectionSerializer)
rescue ActiveRecord::RecordInvalid => e
render_json_error(e.record.errors.full_messages.first)
rescue Discourse::InvalidAccess
render json: failed_json, status: 403
end
def reset
sidebar_section = SidebarSection.find_by(id: params[:id])
raise Discourse::InvalidParameters if !sidebar_section
@guardian.ensure_can_edit!(sidebar_section)
case sidebar_section.section_type
when "community"
sidebar_section.reset_community!
end
render_serialized(sidebar_section, SidebarSectionSerializer)
end
def reorder
sidebar_section = SidebarSection.find_by(id: reorder_params["sidebar_section_id"])
@guardian.ensure_can_edit!(sidebar_section)
order = reorder_params["links_order"].map(&:to_i).each_with_index.to_h
set_order(sidebar_section, order)
render_serialized(sidebar_section, SidebarSectionSerializer)
rescue Discourse::InvalidAccess
render json: failed_json, status: 403
end
def destroy
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)
end
render json: success_json
rescue Discourse::InvalidAccess
render json: failed_json, status: 403
end
def section_params
section_params = params.permit(:id, :title, :public)
section_params.merge!(user: current_user) if !params[:public]
section_params
end
def links_params
params.permit(links: %i[icon name value id _destroy segment])["links"]
end
def reorder_params
params.permit(:sidebar_section_id, links_order: [])
end
private
def set_order(sidebar_section, order)
position_generator =
(0..sidebar_section.sidebar_section_links.count * 2).excluding(
sidebar_section.sidebar_section_links.map(&:position),
).each
links =
sidebar_section
.sidebar_section_links
.sort_by { |link| order[link.linkable_id] }
.map { |link| link.attributes.merge(position: position_generator.next) }
sidebar_section.sidebar_section_links.upsert_all(links, update_only: [:position])
end
def check_access_if_public
return true if !params[:public]
raise Discourse::InvalidAccess.new if !guardian.can_create_public_sidebar_section?
end
end