Add ability to change an instance default theme from the administration panel (#7092) (#8381)

* Add default_settings class method to ScopedSettings

ScopedSettings was extended to use value of unscoped setting instead of
only using defaults set in config/settings.yml for selected settings.
This adds possibility for admins to set default values of users' settings,
for example default theme (as requested in #7092).

* Add ability to change an instance default theme

Closes #7092
pull/8386/head
Jakub Mendyk 2018-08-23 14:17:35 +02:00 committed by Eugen Rochko
parent d1c2c917d9
commit 6cb3514d64
6 changed files with 51 additions and 3 deletions

View File

@ -16,6 +16,7 @@ module Admin
timeline_preview timeline_preview
show_staff_badge show_staff_badge
bootstrap_timeline_accounts bootstrap_timeline_accounts
theme
thumbnail thumbnail
hero hero
min_invite_role min_invite_role

View File

@ -95,7 +95,7 @@ class ApplicationController < ActionController::Base
end end
def current_theme def current_theme
return Setting.default_settings['theme'] unless Themes.instance.names.include? current_user&.setting_theme return Setting.theme unless Themes.instance.names.include? current_user&.setting_theme
current_user.setting_theme current_user.setting_theme
end end

View File

@ -2,6 +2,10 @@
module Settings module Settings
class ScopedSettings class ScopedSettings
DEFAULTING_TO_UNSCOPED = %w(
theme
).freeze
def initialize(object) def initialize(object)
@object = object @object = object
end end
@ -50,15 +54,22 @@ module Settings
Rails.cache.fetch(Setting.cache_key(key, @object)) do Rails.cache.fetch(Setting.cache_key(key, @object)) do
db_val = thing_scoped.find_by(var: key.to_s) db_val = thing_scoped.find_by(var: key.to_s)
if db_val if db_val
default_value = Setting.default_settings[key] default_value = ScopedSettings.default_settings[key]
return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash) return default_value.with_indifferent_access.merge!(db_val.value) if default_value.is_a?(Hash)
db_val.value db_val.value
else else
Setting.default_settings[key] ScopedSettings.default_settings[key]
end end
end end
end end
class << self
def default_settings
defaulting = DEFAULTING_TO_UNSCOPED.map { |k| [k, Setting[k]] }.to_h
Setting.default_settings.merge!(defaulting)
end
end
protected protected
def thing_scoped def thing_scoped

View File

@ -30,6 +30,8 @@ class Form::AdminSettings
:show_staff_badge=, :show_staff_badge=,
:bootstrap_timeline_accounts, :bootstrap_timeline_accounts,
:bootstrap_timeline_accounts=, :bootstrap_timeline_accounts=,
:theme,
:theme=,
:min_invite_role, :min_invite_role,
:min_invite_role=, :min_invite_role=,
:activity_api_enabled, :activity_api_enabled,

View File

@ -15,6 +15,7 @@
%hr/ %hr/
.fields-group .fields-group
= f.input :theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false
= f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html') = f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
= f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html') = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html')

View File

@ -92,6 +92,39 @@ describe ApplicationController, type: :controller do
end end
end end
describe 'helper_method :current_theme' do
it 'returns "default" when theme wasn\'t changed in admin settings' do
allow(Setting).to receive(:default_settings).and_return({'theme' => 'default'})
expect(controller.view_context.current_theme).to eq 'default'
end
it 'returns instances\'s theme when user is not signed in' do
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
expect(controller.view_context.current_theme).to eq 'contrast'
end
it 'returns instances\'s default theme when user didn\'t set theme' do
current_user = Fabricate(:user)
sign_in current_user
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
expect(controller.view_context.current_theme).to eq 'contrast'
end
it 'returns user\'s theme when it is set' do
current_user = Fabricate(:user)
current_user.settings['theme'] = 'mastodon-light'
sign_in current_user
allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
expect(controller.view_context.current_theme).to eq 'mastodon-light'
end
end
context 'ActionController::RoutingError' do context 'ActionController::RoutingError' do
subject do subject do
routes.draw { get 'routing_error' => 'anonymous#routing_error' } routes.draw { get 'routing_error' => 'anonymous#routing_error' }