mirror of
https://github.com/discourse/discourse.git
synced 2025-05-24 02:38:16 +08:00
FIX: display custom sections with default theme
also cleans up mechanism for previewing themes, cleans up naming, gets rid of old janky "preview_style", secures local theme key
This commit is contained in:
@ -81,7 +81,7 @@ export default Ember.Controller.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
previewUrl: url('model.key', '/?preview-style=%@'),
|
previewUrl: url('model.id', '/admin/themes/%@/preview'),
|
||||||
|
|
||||||
maximizeIcon: function() {
|
maximizeIcon: function() {
|
||||||
return this.get('maximized') ? 'compress' : 'expand';
|
return this.get('maximized') ? 'compress' : 'expand';
|
||||||
@ -95,9 +95,6 @@ export default Ember.Controller.extend({
|
|||||||
return !this.get('model.changed') || this.get('model.isSaving');
|
return !this.get('model.changed') || this.get('model.isSaving');
|
||||||
}.property('model.changed', 'model.isSaving'),
|
}.property('model.changed', 'model.isSaving'),
|
||||||
|
|
||||||
undoPreviewUrl: url('/?preview-style='),
|
|
||||||
defaultStyleUrl: url('/?preview-style=default'),
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
save() {
|
save() {
|
||||||
this.get('model').saveChanges("theme_fields");
|
this.get('model').saveChanges("theme_fields");
|
||||||
|
@ -25,6 +25,8 @@ export default Ember.Controller.extend({
|
|||||||
return descriptions.reject(d=>Em.isBlank(d));
|
return descriptions.reject(d=>Em.isBlank(d));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
previewUrl: url('model.id', '/admin/themes/%@/preview'),
|
||||||
|
|
||||||
@computed("colorSchemeId", "model.color_scheme_id")
|
@computed("colorSchemeId", "model.color_scheme_id")
|
||||||
colorSchemeChanged(colorSchemeId, existingId) {
|
colorSchemeChanged(colorSchemeId, existingId) {
|
||||||
colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId);
|
colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId);
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<a href='{{previewUrl}}' title="{{i18n 'admin.customize.explain_preview'}}" target='_blank' class='btn'>{{fa-icon 'desktop'}}{{i18n 'admin.customize.theme.preview'}}</a>
|
||||||
<a class="btn export" target="_blank" href={{downloadUrl}}>{{fa-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a>
|
<a class="btn export" target="_blank" href={{downloadUrl}}>{{fa-icon "download"}} {{i18n 'admin.export_json.button_text'}}</a>
|
||||||
|
|
||||||
{{d-button action="destroy" label="admin.customize.delete" icon="trash" class="btn-danger"}}
|
{{d-button action="destroy" label="admin.customize.delete" icon="trash" class="btn-danger"}}
|
||||||
|
@ -13,9 +13,9 @@ export function currentThemeKey() {
|
|||||||
|
|
||||||
export function selectDefaultTheme(key) {
|
export function selectDefaultTheme(key) {
|
||||||
if (key) {
|
if (key) {
|
||||||
$.cookie('preview_style', key, {path: '/', expires: 9999});
|
$.cookie('theme_key', key, {path: '/', expires: 9999});
|
||||||
} else {
|
} else {
|
||||||
$.cookie('preview_style', null, {path: '/', expires: 1});
|
$.cookie('theme_key', null, {path: '/', expires: 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export default RestrictedUserRoute.extend({
|
|||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
model: user,
|
model: user,
|
||||||
newNameInput: user.get('name'),
|
newNameInput: user.get('name'),
|
||||||
selectedTheme: $.cookie('preview_style') || currentThemeKey()
|
selectedTheme: $.cookie('theme_key') || currentThemeKey()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
class Admin::ThemesController < Admin::AdminController
|
class Admin::ThemesController < Admin::AdminController
|
||||||
|
|
||||||
skip_before_filter :check_xhr, only: [:show]
|
skip_before_filter :check_xhr, only: [:show, :preview]
|
||||||
|
|
||||||
|
def preview
|
||||||
|
@theme = Theme.find(params[:id])
|
||||||
|
|
||||||
|
redirect_to path("/"), flash: {preview_theme_key: @theme.key}
|
||||||
|
end
|
||||||
|
|
||||||
def import
|
def import
|
||||||
|
|
||||||
|
@ -33,12 +33,11 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
before_filter :handle_theme
|
||||||
before_filter :set_current_user_for_logs
|
before_filter :set_current_user_for_logs
|
||||||
before_filter :clear_notifications
|
before_filter :clear_notifications
|
||||||
before_filter :set_locale
|
before_filter :set_locale
|
||||||
before_filter :set_mobile_view
|
before_filter :set_mobile_view
|
||||||
before_filter :inject_preview_style
|
|
||||||
before_filter :disable_customization
|
|
||||||
before_filter :block_if_readonly_mode
|
before_filter :block_if_readonly_mode
|
||||||
before_filter :authorize_mini_profiler
|
before_filter :authorize_mini_profiler
|
||||||
before_filter :preload_json
|
before_filter :preload_json
|
||||||
@ -243,28 +242,40 @@ class ApplicationController < ActionController::Base
|
|||||||
session[:mobile_view] = params[:mobile_view] if params.has_key?(:mobile_view)
|
session[:mobile_view] = params[:mobile_view] if params.has_key?(:mobile_view)
|
||||||
end
|
end
|
||||||
|
|
||||||
def inject_preview_style
|
NO_CUSTOM = "no_custom".freeze
|
||||||
style = request['preview-style']
|
NO_PLUGINS = "no_plugins".freeze
|
||||||
|
ONLY_OFFICIAL = "only_official".freeze
|
||||||
|
SAFE_MODE = "safe_mode".freeze
|
||||||
|
|
||||||
if style.nil?
|
def resolve_safe_mode
|
||||||
session[:preview_style] = cookies[:preview_style]
|
safe_mode = params[SAFE_MODE]
|
||||||
else
|
if safe_mode
|
||||||
cookies.delete(:preview_style)
|
request.env[NO_CUSTOM] = true if safe_mode.include?(NO_CUSTOM)
|
||||||
|
request.env[NO_PLUGINS] = true if safe_mode.include?(NO_PLUGINS)
|
||||||
if style.blank? || style == 'default'
|
request.env[ONLY_OFFICIAL] = true if safe_mode.include?(ONLY_OFFICIAL)
|
||||||
session[:preview_style] = nil
|
|
||||||
else
|
|
||||||
session[:preview_style] = style
|
|
||||||
if request['sticky']
|
|
||||||
cookies[:preview_style] = style
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_customization
|
def handle_theme
|
||||||
session[:disable_customization] = params[:customization] == "0" if params.has_key?(:customization)
|
|
||||||
|
return if request.xhr? || request.format.json?
|
||||||
|
return if request.method != "GET"
|
||||||
|
|
||||||
|
resolve_safe_mode
|
||||||
|
return if request.env[NO_CUSTOM]
|
||||||
|
|
||||||
|
theme_key = flash[:preview_theme_key] || cookies[:theme_key] || session[:theme_key]
|
||||||
|
|
||||||
|
if theme_key && !guardian.allow_theme?(theme_key)
|
||||||
|
theme_key = nil
|
||||||
|
cookies[:theme_key] = nil
|
||||||
|
session[:theme_key] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
theme_key ||= SiteSetting.default_theme_key
|
||||||
|
theme_key = nil if theme_key.blank?
|
||||||
|
|
||||||
|
@theme_key = request.env[:resolved_theme_key] = theme_key
|
||||||
end
|
end
|
||||||
|
|
||||||
def guardian
|
def guardian
|
||||||
@ -410,10 +421,14 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
def custom_html_json
|
def custom_html_json
|
||||||
target = view_context.mobile_view? ? :mobile : :desktop
|
target = view_context.mobile_view? ? :mobile : :desktop
|
||||||
data = {
|
data = if @theme_key
|
||||||
top: Theme.lookup_field(session[:preview_style], target, "after_header"),
|
{
|
||||||
footer: Theme.lookup_field(session[:preview_style], target, "footer")
|
top: Theme.lookup_field(@theme_key, target, "after_header"),
|
||||||
}
|
footer: Theme.lookup_field(@theme_key, target, "footer")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
|
||||||
if DiscoursePluginRegistry.custom_html
|
if DiscoursePluginRegistry.custom_html
|
||||||
data.merge! DiscoursePluginRegistry.custom_html
|
data.merge! DiscoursePluginRegistry.custom_html
|
||||||
|
@ -248,32 +248,23 @@ module ApplicationHelper
|
|||||||
MobileDetection.mobile_device?(request.user_agent)
|
MobileDetection.mobile_device?(request.user_agent)
|
||||||
end
|
end
|
||||||
|
|
||||||
NO_CUSTOM = "no_custom".freeze
|
|
||||||
NO_PLUGINS = "no_plugins".freeze
|
|
||||||
ONLY_OFFICIAL = "only_official".freeze
|
|
||||||
SAFE_MODE = "safe_mode".freeze
|
|
||||||
|
|
||||||
def customization_disabled?
|
def customization_disabled?
|
||||||
safe_mode = params[SAFE_MODE]
|
request.env[ApplicationController::NO_CUSTOM]
|
||||||
session[:disable_customization] || (safe_mode && safe_mode.include?(NO_CUSTOM))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_plugins?
|
def allow_plugins?
|
||||||
safe_mode = params[SAFE_MODE]
|
!request.env[ApplicationController::NO_PLUGINS]
|
||||||
!(safe_mode && safe_mode.include?(NO_PLUGINS))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_third_party_plugins?
|
def allow_third_party_plugins?
|
||||||
safe_mode = params[SAFE_MODE]
|
allow_plugins? && !request.env[ApplicationController::ONLY_OFFICIAL]
|
||||||
!(safe_mode && (safe_mode.include?(NO_PLUGINS) || safe_mode.include?(ONLY_OFFICIAL)))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalized_safe_mode
|
def normalized_safe_mode
|
||||||
mode_string = params["safe_mode"]
|
|
||||||
safe_mode = nil
|
safe_mode = nil
|
||||||
(safe_mode ||= []) << NO_CUSTOM if mode_string.include?(NO_CUSTOM)
|
(safe_mode ||= []) << ApplicationController::NO_CUSTOM if customization_disabled?
|
||||||
(safe_mode ||= []) << NO_PLUGINS if mode_string.include?(NO_PLUGINS)
|
(safe_mode ||= []) << ApplicationController::NO_PLUGINS if !allow_plugins?
|
||||||
(safe_mode ||= []) << ONLY_OFFICIAL if mode_string.include?(ONLY_OFFICIAL)
|
(safe_mode ||= []) << ApplicationController::ONLY_OFFICIAL if !allow_third_party_plugins?
|
||||||
if safe_mode
|
if safe_mode
|
||||||
safe_mode.join(",").html_safe
|
safe_mode.join(",").html_safe
|
||||||
end
|
end
|
||||||
@ -321,7 +312,7 @@ module ApplicationHelper
|
|||||||
if customization_disabled?
|
if customization_disabled?
|
||||||
nil
|
nil
|
||||||
else
|
else
|
||||||
session[:preview_style] || SiteSetting.default_theme_key
|
request.env[:resolved_theme_key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -45,6 +45,24 @@ class Theme < ActiveRecord::Base
|
|||||||
theme.notify_theme_change
|
theme.notify_theme_change
|
||||||
end, on: :update
|
end, on: :update
|
||||||
|
|
||||||
|
def self.theme_keys
|
||||||
|
if keys = @cache["theme_keys"]
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
@cache["theme_keys"] = Set.new(Theme.pluck(:key))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.user_theme_keys
|
||||||
|
if keys = @cache["user_theme_keys"]
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
@cache["theme_keys"] = Set.new(
|
||||||
|
Theme
|
||||||
|
.where('user_selectable OR key = ?', SiteSetting.default_theme_key)
|
||||||
|
.pluck(:key)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def self.expire_site_cache!
|
def self.expire_site_cache!
|
||||||
Site.clear_anon_cache!
|
Site.clear_anon_cache!
|
||||||
ApplicationSerializer.expire_cache_fragment!("user_themes")
|
ApplicationSerializer.expire_cache_fragment!("user_themes")
|
||||||
|
@ -2785,7 +2785,7 @@ en:
|
|||||||
title: "Customize"
|
title: "Customize"
|
||||||
long_title: "Site Customizations"
|
long_title: "Site Customizations"
|
||||||
preview: "preview"
|
preview: "preview"
|
||||||
explain_preview: "See the site with this custom stylesheet"
|
explain_preview: "See the site with this theme enabled"
|
||||||
save: "Save"
|
save: "Save"
|
||||||
new: "New"
|
new: "New"
|
||||||
new_style: "New Style"
|
new_style: "New Style"
|
||||||
@ -2815,6 +2815,7 @@ en:
|
|||||||
common: "Common"
|
common: "Common"
|
||||||
desktop: "Desktop"
|
desktop: "Desktop"
|
||||||
mobile: "Mobile"
|
mobile: "Mobile"
|
||||||
|
preview: "Preview"
|
||||||
is_default: "Theme is enabled by default"
|
is_default: "Theme is enabled by default"
|
||||||
user_selectable: "Theme can be selected by users"
|
user_selectable: "Theme can be selected by users"
|
||||||
color_scheme: "Color Scheme"
|
color_scheme: "Color Scheme"
|
||||||
|
@ -3361,7 +3361,7 @@ en:
|
|||||||
safe_mode:
|
safe_mode:
|
||||||
title: "Enter safe mode"
|
title: "Enter safe mode"
|
||||||
description: "Safe mode allows you to test your site without loading plugins or site customizations."
|
description: "Safe mode allows you to test your site without loading plugins or site customizations."
|
||||||
no_customizations: "Disable all site customizations"
|
no_customizations: "Disable current theme"
|
||||||
only_official: "Disable unofficial plugins"
|
only_official: "Disable unofficial plugins"
|
||||||
no_plugins: "Disable all plugins"
|
no_plugins: "Disable all plugins"
|
||||||
enter: "Enter Safe Mode"
|
enter: "Enter Safe Mode"
|
||||||
|
@ -188,6 +188,7 @@ Discourse::Application.routes.draw do
|
|||||||
|
|
||||||
resources :themes, constraints: AdminConstraint.new
|
resources :themes, constraints: AdminConstraint.new
|
||||||
post "themes/import" => "themes#import"
|
post "themes/import" => "themes#import"
|
||||||
|
get "themes/:id/preview" => "themes#preview"
|
||||||
|
|
||||||
scope "/customize", constraints: AdminConstraint.new do
|
scope "/customize", constraints: AdminConstraint.new do
|
||||||
resources :user_fields, constraints: AdminConstraint.new
|
resources :user_fields, constraints: AdminConstraint.new
|
||||||
|
@ -297,6 +297,14 @@ class Guardian
|
|||||||
UserExport.where(user_id: @user.id, created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)).count == 0
|
UserExport.where(user_id: @user.id, created_at: (Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)).count == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def allow_theme?(theme_key)
|
||||||
|
if is_staff?
|
||||||
|
Theme.theme_keys.include?(theme_key)
|
||||||
|
else
|
||||||
|
Theme.theme_user_keys.include?(theme_key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
@ -137,5 +137,28 @@ HTML
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'correctly caches theme keys' do
|
||||||
|
theme = Theme.create!(name: "bob", user_id: -1)
|
||||||
|
|
||||||
|
expect(Theme.theme_keys).to eq(Set.new([theme.key]))
|
||||||
|
expect(Theme.user_theme_keys).to eq(Set.new([]))
|
||||||
|
|
||||||
|
theme.user_selectable = true
|
||||||
|
theme.save
|
||||||
|
|
||||||
|
expect(Theme.user_theme_keys).to eq(Set.new([theme.key]))
|
||||||
|
|
||||||
|
theme.user_selectable = false
|
||||||
|
theme.save
|
||||||
|
|
||||||
|
theme.set_default!
|
||||||
|
expect(Theme.user_theme_keys).to eq(Set.new([theme.key]))
|
||||||
|
|
||||||
|
theme.destroy
|
||||||
|
|
||||||
|
expect(Theme.theme_keys).to eq(Set.new([]))
|
||||||
|
expect(Theme.user_theme_keys).to eq(Set.new([]))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user