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:
Sam 2017-04-14 13:35:12 -04:00
parent 8370b4b1b7
commit def7348777
14 changed files with 113 additions and 50 deletions

View File

@ -81,7 +81,7 @@ export default Ember.Controller.extend({
});
},
previewUrl: url('model.key', '/?preview-style=%@'),
previewUrl: url('model.id', '/admin/themes/%@/preview'),
maximizeIcon: function() {
return this.get('maximized') ? 'compress' : 'expand';
@ -95,9 +95,6 @@ export default Ember.Controller.extend({
return !this.get('model.changed') || this.get('model.isSaving');
}.property('model.changed', 'model.isSaving'),
undoPreviewUrl: url('/?preview-style='),
defaultStyleUrl: url('/?preview-style=default'),
actions: {
save() {
this.get('model').saveChanges("theme_fields");

View File

@ -25,6 +25,8 @@ export default Ember.Controller.extend({
return descriptions.reject(d=>Em.isBlank(d));
},
previewUrl: url('model.id', '/admin/themes/%@/preview'),
@computed("colorSchemeId", "model.color_scheme_id")
colorSchemeChanged(colorSchemeId, existingId) {
colorSchemeId = colorSchemeId === null ? null : parseInt(colorSchemeId);

View File

@ -106,6 +106,7 @@
{{/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>
{{d-button action="destroy" label="admin.customize.delete" icon="trash" class="btn-danger"}}

View File

@ -13,9 +13,9 @@ export function currentThemeKey() {
export function selectDefaultTheme(key) {
if (key) {
$.cookie('preview_style', key, {path: '/', expires: 9999});
$.cookie('theme_key', key, {path: '/', expires: 9999});
} else {
$.cookie('preview_style', null, {path: '/', expires: 1});
$.cookie('theme_key', null, {path: '/', expires: 1});
}
}

View File

@ -13,7 +13,7 @@ export default RestrictedUserRoute.extend({
controller.setProperties({
model: user,
newNameInput: user.get('name'),
selectedTheme: $.cookie('preview_style') || currentThemeKey()
selectedTheme: $.cookie('theme_key') || currentThemeKey()
});
},

View File

@ -1,6 +1,12 @@
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

View File

@ -33,12 +33,11 @@ class ApplicationController < ActionController::Base
end
end
before_filter :handle_theme
before_filter :set_current_user_for_logs
before_filter :clear_notifications
before_filter :set_locale
before_filter :set_mobile_view
before_filter :inject_preview_style
before_filter :disable_customization
before_filter :block_if_readonly_mode
before_filter :authorize_mini_profiler
before_filter :preload_json
@ -243,28 +242,40 @@ class ApplicationController < ActionController::Base
session[:mobile_view] = params[:mobile_view] if params.has_key?(:mobile_view)
end
def inject_preview_style
style = request['preview-style']
NO_CUSTOM = "no_custom".freeze
NO_PLUGINS = "no_plugins".freeze
ONLY_OFFICIAL = "only_official".freeze
SAFE_MODE = "safe_mode".freeze
if style.nil?
session[:preview_style] = cookies[:preview_style]
else
cookies.delete(:preview_style)
if style.blank? || style == 'default'
session[:preview_style] = nil
else
session[:preview_style] = style
if request['sticky']
cookies[:preview_style] = style
end
end
def resolve_safe_mode
safe_mode = params[SAFE_MODE]
if safe_mode
request.env[NO_CUSTOM] = true if safe_mode.include?(NO_CUSTOM)
request.env[NO_PLUGINS] = true if safe_mode.include?(NO_PLUGINS)
request.env[ONLY_OFFICIAL] = true if safe_mode.include?(ONLY_OFFICIAL)
end
end
def disable_customization
session[:disable_customization] = params[:customization] == "0" if params.has_key?(:customization)
def handle_theme
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
def guardian
@ -410,10 +421,14 @@ class ApplicationController < ActionController::Base
def custom_html_json
target = view_context.mobile_view? ? :mobile : :desktop
data = {
top: Theme.lookup_field(session[:preview_style], target, "after_header"),
footer: Theme.lookup_field(session[:preview_style], target, "footer")
}
data = if @theme_key
{
top: Theme.lookup_field(@theme_key, target, "after_header"),
footer: Theme.lookup_field(@theme_key, target, "footer")
}
else
{}
end
if DiscoursePluginRegistry.custom_html
data.merge! DiscoursePluginRegistry.custom_html

View File

@ -248,32 +248,23 @@ module ApplicationHelper
MobileDetection.mobile_device?(request.user_agent)
end
NO_CUSTOM = "no_custom".freeze
NO_PLUGINS = "no_plugins".freeze
ONLY_OFFICIAL = "only_official".freeze
SAFE_MODE = "safe_mode".freeze
def customization_disabled?
safe_mode = params[SAFE_MODE]
session[:disable_customization] || (safe_mode && safe_mode.include?(NO_CUSTOM))
request.env[ApplicationController::NO_CUSTOM]
end
def allow_plugins?
safe_mode = params[SAFE_MODE]
!(safe_mode && safe_mode.include?(NO_PLUGINS))
!request.env[ApplicationController::NO_PLUGINS]
end
def allow_third_party_plugins?
safe_mode = params[SAFE_MODE]
!(safe_mode && (safe_mode.include?(NO_PLUGINS) || safe_mode.include?(ONLY_OFFICIAL)))
allow_plugins? && !request.env[ApplicationController::ONLY_OFFICIAL]
end
def normalized_safe_mode
mode_string = params["safe_mode"]
safe_mode = nil
(safe_mode ||= []) << NO_CUSTOM if mode_string.include?(NO_CUSTOM)
(safe_mode ||= []) << NO_PLUGINS if mode_string.include?(NO_PLUGINS)
(safe_mode ||= []) << ONLY_OFFICIAL if mode_string.include?(ONLY_OFFICIAL)
(safe_mode ||= []) << ApplicationController::NO_CUSTOM if customization_disabled?
(safe_mode ||= []) << ApplicationController::NO_PLUGINS if !allow_plugins?
(safe_mode ||= []) << ApplicationController::ONLY_OFFICIAL if !allow_third_party_plugins?
if safe_mode
safe_mode.join(",").html_safe
end
@ -321,7 +312,7 @@ module ApplicationHelper
if customization_disabled?
nil
else
session[:preview_style] || SiteSetting.default_theme_key
request.env[:resolved_theme_key]
end
end

View File

@ -45,6 +45,24 @@ class Theme < ActiveRecord::Base
theme.notify_theme_change
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!
Site.clear_anon_cache!
ApplicationSerializer.expire_cache_fragment!("user_themes")

View File

@ -2785,7 +2785,7 @@ en:
title: "Customize"
long_title: "Site Customizations"
preview: "preview"
explain_preview: "See the site with this custom stylesheet"
explain_preview: "See the site with this theme enabled"
save: "Save"
new: "New"
new_style: "New Style"
@ -2815,6 +2815,7 @@ en:
common: "Common"
desktop: "Desktop"
mobile: "Mobile"
preview: "Preview"
is_default: "Theme is enabled by default"
user_selectable: "Theme can be selected by users"
color_scheme: "Color Scheme"

View File

@ -3361,7 +3361,7 @@ en:
safe_mode:
title: "Enter safe mode"
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"
no_plugins: "Disable all plugins"
enter: "Enter Safe Mode"

View File

@ -188,6 +188,7 @@ Discourse::Application.routes.draw do
resources :themes, constraints: AdminConstraint.new
post "themes/import" => "themes#import"
get "themes/:id/preview" => "themes#preview"
scope "/customize", constraints: AdminConstraint.new do
resources :user_fields, constraints: AdminConstraint.new

View File

@ -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
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

View File

@ -137,5 +137,28 @@ HTML
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