FEATURE: Allow to modify topic-backed static pages (#15324)
A plugin API that allows customizing existing topic-backed static pages, like: faq, tos, privacy (see: StaticController) The block passed to this method has to return a SiteSetting name that contains a topic id. ``` add_topic_static_page("faq") do |controller| current_user&.locale == "pl" ? "polish_faq_topic_id" : "faq_topic_id" end ``` You can also add new pages in a plugin, but remember to add a route, for example: ``` get "contact" => "static#show", id: "contact" ```
This commit is contained in:
parent
ad4faf637c
commit
2a4df93b8e
|
@ -1,7 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StaticController < ApplicationController
|
class StaticController < ApplicationController
|
||||||
|
|
||||||
skip_before_action :check_xhr, :redirect_to_login_if_required
|
skip_before_action :check_xhr, :redirect_to_login_if_required
|
||||||
skip_before_action :verify_authenticity_token, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
|
skip_before_action :verify_authenticity_token, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
|
||||||
skip_before_action :preload_json, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
|
skip_before_action :preload_json, only: [:brotli_asset, :cdn_asset, :enter, :favicon, :service_worker_asset]
|
||||||
|
@ -11,24 +10,26 @@ class StaticController < ApplicationController
|
||||||
|
|
||||||
PAGES_WITH_EMAIL_PARAM = ['login', 'password_reset', 'signup']
|
PAGES_WITH_EMAIL_PARAM = ['login', 'password_reset', 'signup']
|
||||||
MODAL_PAGES = ['password_reset', 'signup']
|
MODAL_PAGES = ['password_reset', 'signup']
|
||||||
|
DEFAULT_PAGES = {
|
||||||
|
"faq" => { redirect: "faq_url", topic_id: "guidelines_topic_id" },
|
||||||
|
"tos" => { redirect: "tos_url", topic_id: "tos_topic_id" },
|
||||||
|
"privacy" => { redirect: "privacy_policy_url", topic_id: "privacy_topic_id" },
|
||||||
|
}
|
||||||
|
CUSTOM_PAGES = {} # Add via `#add_topic_static_page` in plugin API
|
||||||
|
|
||||||
def show
|
def show
|
||||||
return redirect_to(path '/') if current_user && (params[:id] == 'login' || params[:id] == 'signup')
|
return redirect_to(path '/') if current_user && (params[:id] == 'login' || params[:id] == 'signup')
|
||||||
|
|
||||||
if SiteSetting.login_required? && current_user.nil? && ['faq', 'guidelines'].include?(params[:id])
|
if SiteSetting.login_required? && current_user.nil? && ['faq', 'guidelines'].include?(params[:id])
|
||||||
return redirect_to path('/login')
|
return redirect_to path('/login')
|
||||||
end
|
end
|
||||||
|
|
||||||
map = {
|
map = DEFAULT_PAGES.deep_merge(CUSTOM_PAGES)
|
||||||
"faq" => { redirect: "faq_url", topic_id: "guidelines_topic_id" },
|
|
||||||
"tos" => { redirect: "tos_url", topic_id: "tos_topic_id" },
|
|
||||||
"privacy" => { redirect: "privacy_policy_url", topic_id: "privacy_topic_id" }
|
|
||||||
}
|
|
||||||
|
|
||||||
@page = params[:id]
|
@page = params[:id]
|
||||||
|
|
||||||
if map.has_key?(@page)
|
if map.has_key?(@page)
|
||||||
site_setting_key = map[@page][:redirect]
|
site_setting_key = map[@page][:redirect]
|
||||||
url = SiteSetting.get(site_setting_key)
|
url = SiteSetting.get(site_setting_key) if site_setting_key
|
||||||
return redirect_to(url) if url.present?
|
return redirect_to(url) if url.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,8 +40,12 @@ class StaticController < ApplicationController
|
||||||
@page = @page.gsub(/[^a-z0-9\_\-]/, '')
|
@page = @page.gsub(/[^a-z0-9\_\-]/, '')
|
||||||
|
|
||||||
if map.has_key?(@page)
|
if map.has_key?(@page)
|
||||||
@topic = Topic.find_by_id(SiteSetting.get(map[@page][:topic_id]))
|
topic_id = map[@page][:topic_id]
|
||||||
|
topic_id = instance_exec(&topic_id) if topic_id.is_a?(Proc)
|
||||||
|
|
||||||
|
@topic = Topic.find_by_id(SiteSetting.get(topic_id))
|
||||||
raise Discourse::NotFound unless @topic
|
raise Discourse::NotFound unless @topic
|
||||||
|
|
||||||
title_prefix = if I18n.exists?("js.#{@page}")
|
title_prefix = if I18n.exists?("js.#{@page}")
|
||||||
I18n.t("js.#{@page}")
|
I18n.t("js.#{@page}")
|
||||||
else
|
else
|
||||||
|
@ -48,17 +53,16 @@ class StaticController < ApplicationController
|
||||||
end
|
end
|
||||||
@title = "#{title_prefix} - #{SiteSetting.title}"
|
@title = "#{title_prefix} - #{SiteSetting.title}"
|
||||||
@body = @topic.posts.first.cooked
|
@body = @topic.posts.first.cooked
|
||||||
@faq_overriden = !SiteSetting.faq_url.blank?
|
@faq_overridden = !SiteSetting.faq_url.blank?
|
||||||
|
|
||||||
render :show, layout: !request.xhr?, formats: [:html]
|
render :show, layout: !request.xhr?, formats: [:html]
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
unless @title.present?
|
@title = SiteSetting.title
|
||||||
@title = if SiteSetting.short_site_description.present?
|
|
||||||
"#{SiteSetting.title} - #{SiteSetting.short_site_description}"
|
if SiteSetting.short_site_description.present?
|
||||||
else
|
@title << " - #{SiteSetting.short_site_description}"
|
||||||
SiteSetting.title
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if I18n.exists?("static.#{@page}")
|
if I18n.exists?("static.#{@page}")
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<ul class='nav-pills' role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement'>
|
<ul class='nav-pills' role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement'>
|
||||||
<% unless SiteSetting.login_required? && current_user.nil? %>
|
<% unless SiteSetting.login_required? && current_user.nil? %>
|
||||||
<li class="nav-item-about"><%= link_to t('js.about.simple_title'), about_index_path %></a></li>
|
<li class="nav-item-about"><%= link_to t('js.about.simple_title'), about_index_path %></a></li>
|
||||||
<% if @faq_overriden %>
|
<% if @faq_overridden %>
|
||||||
<li class='nav-item-guidelines'><a class='<%= @page == 'faq' ? 'active' : '' %>' href='<%= guidelines_path %>'><%= t 'js.guidelines' %></a></li>
|
<li class='nav-item-guidelines'><a class='<%= @page == 'faq' ? 'active' : '' %>' href='<%= guidelines_path %>'><%= t 'js.guidelines' %></a></li>
|
||||||
<li class='nav-item-faq'><a href='<%= faq_path %>'><%= t 'js.faq' %></a></li>
|
<li class='nav-item-faq'><a href='<%= faq_path %>'><%= t 'js.faq' %></a></li>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|
|
@ -994,6 +994,22 @@ class Plugin::Instance
|
||||||
DiscoursePluginRegistry.register_notification_consolidation_plan(plan, self)
|
DiscoursePluginRegistry.register_notification_consolidation_plan(plan, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allows customizing existing topic-backed static pages, like:
|
||||||
|
# faq, tos, privacy (see: StaticController) The block passed to this
|
||||||
|
# method has to return a SiteSetting name that contains a topic id.
|
||||||
|
#
|
||||||
|
# add_topic_static_page("faq") do |controller|
|
||||||
|
# current_user&.locale == "pl" ? "polish_faq_topic_id" : "faq_topic_id"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# You can also add new pages in a plugin, but remember to add a route,
|
||||||
|
# for example:
|
||||||
|
#
|
||||||
|
# get "contact" => "static#show", id: "contact"
|
||||||
|
def add_topic_static_page(page, options = {}, &blk)
|
||||||
|
StaticController::CUSTOM_PAGES[page] = blk ? { topic_id: blk } : options
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def self.js_path
|
def self.js_path
|
||||||
|
|
|
@ -277,6 +277,52 @@ describe StaticController do
|
||||||
expect(response.body).to include("<title>FAQ - Discourse</title>")
|
expect(response.body).to include("<title>FAQ - Discourse</title>")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "plugin api extensions" do
|
||||||
|
after do
|
||||||
|
Rails.application.reload_routes!
|
||||||
|
StaticController::CUSTOM_PAGES.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds new topic-backed pages" do
|
||||||
|
routes = Proc.new do
|
||||||
|
get "contact" => "static#show", id: "contact"
|
||||||
|
end
|
||||||
|
Discourse::Application.routes.send(:eval_block, routes)
|
||||||
|
|
||||||
|
topic_id = Fabricate(:post, cooked: "contact info").topic_id
|
||||||
|
SiteSetting.setting(:contact_topic_id, topic_id)
|
||||||
|
|
||||||
|
Plugin::Instance.new.add_topic_static_page("contact", topic_id: "contact_topic_id")
|
||||||
|
|
||||||
|
get "/contact"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.body).to include("contact info")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "replaces existing topic-backed pages" do
|
||||||
|
topic_id = Fabricate(:post, cooked: "Regular FAQ").topic_id
|
||||||
|
SiteSetting.setting(:faq_topic_id, topic_id)
|
||||||
|
polish_topic_id = Fabricate(:post, cooked: "Polish FAQ").topic_id
|
||||||
|
SiteSetting.setting(:polish_faq_topic_id, polish_topic_id)
|
||||||
|
|
||||||
|
Plugin::Instance.new.add_topic_static_page("faq") do
|
||||||
|
current_user&.locale == "pl" ? "polish_faq_topic_id" : "faq_topic_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/faq"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.body).to include("Regular FAQ")
|
||||||
|
|
||||||
|
sign_in(Fabricate(:user, locale: "pl"))
|
||||||
|
get "/faq"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
expect(response.body).to include("Polish FAQ")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#enter' do
|
describe '#enter' do
|
||||||
|
|
Loading…
Reference in New Issue