FEATURE: theme selection is now global per-user

This commit is contained in:
Sam
2017-05-12 12:41:26 -04:00
parent b301b69d00
commit 2d96a0785d
11 changed files with 53 additions and 29 deletions

View File

@ -2,7 +2,6 @@ import PreferencesTabController from "discourse/mixins/preferences-tab-controlle
import { default as computed, observes } from "ember-addons/ember-computed-decorators"; import { default as computed, observes } from "ember-addons/ember-computed-decorators";
import { listThemes, previewTheme } from 'discourse/lib/theme-selector'; import { listThemes, previewTheme } from 'discourse/lib/theme-selector';
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from 'discourse/lib/ajax-error';
import { selectDefaultTheme } from 'discourse/lib/theme-selector';
export default Ember.Controller.extend(PreferencesTabController, { export default Ember.Controller.extend(PreferencesTabController, {
@ -12,7 +11,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
'dynamic_favicon', 'dynamic_favicon',
'enable_quoting', 'enable_quoting',
'disable_jump_reply', 'disable_jump_reply',
'automatically_unpin_topics' 'automatically_unpin_topics',
'theme_key'
], ],
preferencesController: Ember.inject.controller('preferences'), preferencesController: Ember.inject.controller('preferences'),
@ -26,10 +26,9 @@ export default Ember.Controller.extend(PreferencesTabController, {
return listThemes(this.site); return listThemes(this.site);
}.property(), }.property(),
@observes("selectedTheme") @observes("model.user_option.theme_key")
themeKeyChanged() { themeKeyChanged() {
let key = this.get("selectedTheme"); let key = this.get("model.user_option.theme_key");
this.get('preferencesController').set('selectedTheme', key);
previewTheme(key); previewTheme(key);
}, },
@ -38,7 +37,6 @@ export default Ember.Controller.extend(PreferencesTabController, {
this.set('saved', false); this.set('saved', false);
return this.get('model').save(this.get('saveAttrNames')).then(() => { return this.get('model').save(this.get('saveAttrNames')).then(() => {
this.set('saved', true); this.set('saved', true);
selectDefaultTheme(this.get('selectedTheme'));
}).catch(popupAjaxError); }).catch(popupAjaxError);
} }
} }

View File

@ -13,14 +13,6 @@ export function currentThemeKey() {
return themeKey; return themeKey;
} }
export function selectDefaultTheme(key) {
if (key) {
$.cookie('theme_key', key, {path: '/', expires: 9999});
} else {
$.cookie('theme_key', null, {path: '/', expires: 1});
}
}
export function refreshCSS(node, hash, newHref, options) { export function refreshCSS(node, hash, newHref, options) {
let $orig = $(node); let $orig = $(node);

View File

@ -242,7 +242,8 @@ const User = RestModel.extend({
'auto_track_topics_after_msecs', 'auto_track_topics_after_msecs',
'notification_level_when_replying', 'notification_level_when_replying',
'like_notification_frequency', 'like_notification_frequency',
'include_tl0_in_digests' 'include_tl0_in_digests',
'theme_key'
]; ];
if (fields) { if (fields) {

View File

@ -1,11 +1,9 @@
import RestrictedUserRoute from "discourse/routes/restricted-user"; import RestrictedUserRoute from "discourse/routes/restricted-user";
import { currentThemeKey } from 'discourse/lib/theme-selector';
export default RestrictedUserRoute.extend({ export default RestrictedUserRoute.extend({
setupController(controller, user) { setupController(controller, user) {
controller.setProperties({ controller.setProperties({
model: user, model: user
selectedTheme: $.cookie('theme_key') || currentThemeKey()
}); });
} }
}); });

View File

@ -2,7 +2,7 @@
<div class="control-group theme"> <div class="control-group theme">
<label class="control-label">{{i18n 'user.theme'}}</label> <label class="control-label">{{i18n 'user.theme'}}</label>
<div class="controls"> <div class="controls">
{{combo-box content=userSelectableThemes value=selectedTheme}} {{combo-box content=userSelectableThemes value=model.user_option.theme_key}}
</div> </div>
</div> </div>
{{/if}} {{/if}}

View File

@ -18,6 +18,8 @@ class ApplicationController < ActionController::Base
include JsonError include JsonError
include GlobalPath include GlobalPath
attr_reader :theme_key
serialization_scope :guardian serialization_scope :guardian
protect_from_forgery protect_from_forgery
@ -265,12 +267,15 @@ class ApplicationController < ActionController::Base
resolve_safe_mode resolve_safe_mode
return if request.env[NO_CUSTOM] return if request.env[NO_CUSTOM]
theme_key = flash[:preview_theme_key] || cookies[:theme_key] || session[:theme_key] theme_key = flash[:preview_theme_key] || current_user&.user_option&.theme_key
# TODO 2018: delete this, old cookie cleanup code
if cookies[:theme_key]
cookies.delete(:theme_key)
end
if theme_key && !guardian.allow_theme?(theme_key) if theme_key && !guardian.allow_theme?(theme_key)
theme_key = nil theme_key = nil
cookies[:theme_key] = nil
session[:theme_key] = nil
end end
theme_key ||= SiteSetting.default_theme_key theme_key ||= SiteSetting.default_theme_key

View File

@ -18,7 +18,8 @@ class UserOptionSerializer < ApplicationSerializer
:email_previous_replies, :email_previous_replies,
:email_in_reply_to, :email_in_reply_to,
:like_notification_frequency, :like_notification_frequency,
:include_tl0_in_digests :include_tl0_in_digests,
:theme_key
def auto_track_topics_after_msecs def auto_track_topics_after_msecs
@ -33,4 +34,8 @@ class UserOptionSerializer < ApplicationSerializer
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
end end
def theme_key
object.theme_key || SiteSetting.default_theme_key
end
end end

View File

@ -33,7 +33,8 @@ class UserUpdater
:email_previous_replies, :email_previous_replies,
:email_in_reply_to, :email_in_reply_to,
:like_notification_frequency, :like_notification_frequency,
:include_tl0_in_digests :include_tl0_in_digests,
:theme_key
] ]
def initialize(actor, user) def initialize(actor, user)

View File

@ -0,0 +1,5 @@
class AddThemeKeyToUserOptions < ActiveRecord::Migration
def change
add_column :user_options, :theme_key, :string
end
end

View File

@ -17,6 +17,22 @@ describe TopicsController do
request.env['HTTP_ACCEPT_LANGUAGE'] = locale request.env['HTTP_ACCEPT_LANGUAGE'] = locale
end end
describe "themes" do
it "selects the theme the user has selected" do
theme = Theme.create!(user_id: -1, name: 'bob', user_selectable: true)
user = log_in
user.user_option.update_columns(theme_key: theme.key)
get :show, id: 666
expect(controller.theme_key).to eq(theme.key)
theme.update_columns(user_selectable: false)
get :show, id: 666
expect(controller.theme_key).not_to eq(theme.key)
end
end
it "doesn't store an incoming link when there's no referer" do it "doesn't store an incoming link when there's no referer" do
expect { expect {
get :show, id: topic.id get :show, id: topic.id
@ -32,20 +48,19 @@ describe TopicsController do
render_views render_views
context "when the SiteSetting is disabled" do context "when the SiteSetting is disabled" do
before do
SiteSetting.stubs(:enable_escaped_fragments?).returns(false)
end
it "uses the application layout even with an escaped fragment param" do it "uses the application layout even with an escaped fragment param" do
SiteSetting.enable_escaped_fragments = false
get :show, {'topic_id' => topic.id, 'slug' => topic.slug, '_escaped_fragment_' => 'true'} get :show, {'topic_id' => topic.id, 'slug' => topic.slug, '_escaped_fragment_' => 'true'}
expect(response).to render_template(layout: 'application') expect(response).to render_template(layout: 'application')
assert_select "meta[name=fragment]", false, "it doesn't have the meta tag" assert_select "meta[name=fragment]", false, "it doesn't have the meta tag"
end end
end end
context "when the SiteSetting is enabled" do context "when the SiteSetting is enabled" do
before do before do
SiteSetting.stubs(:enable_escaped_fragments?).returns(true) SiteSetting.enable_escaped_fragments = true
end end
it "uses the application layout when there's no param" do it "uses the application layout when there's no param" do

View File

@ -1221,13 +1221,17 @@ describe UsersController do
expect(user.custom_fields['test']).to eq 'it' expect(user.custom_fields['test']).to eq 'it'
expect(user.muted_users.pluck(:username).sort).to eq [user2.username,user3.username].sort expect(user.muted_users.pluck(:username).sort).to eq [user2.username,user3.username].sort
theme = Theme.create(name: "test", user_selectable: true, user_id: -1)
put :update, put :update,
username: user.username, username: user.username,
muted_usernames: "" muted_usernames: "",
theme_key: theme.key
user.reload user.reload
expect(user.muted_users.pluck(:username).sort).to be_empty expect(user.muted_users.pluck(:username).sort).to be_empty
expect(user.user_option.theme_key).to eq(theme.key)
end end