FEATURE: out-of-the-box dark/light user selectable themes

This commit is contained in:
Sam 2017-05-03 11:31:16 -04:00
parent 81190f5d66
commit 342ef5f81a
13 changed files with 68 additions and 35 deletions

View File

@ -92,13 +92,19 @@ class ColorScheme < ActiveRecord::Base
# create_from_base will create a new ColorScheme that overrides Discourse's base color scheme with the given colors. # create_from_base will create a new ColorScheme that overrides Discourse's base color scheme with the given colors.
def self.create_from_base(params) def self.create_from_base(params)
new_color_scheme = new(name: params[:name]) new_color_scheme = new(name: params[:name])
colors = base.colors_hashes new_color_scheme.via_wizard = true if params[:via_wizard]
new_color_scheme.base_scheme_id = params[:base_scheme_id]
colors = CUSTOM_SCHEMES[params[:base_scheme_id].to_sym]&.map do |name, hex|
{name: name, hex: hex}
end if params[:base_scheme_id]
colors ||= base.colors_hashes
# Override base values # Override base values
params[:colors].each do |name, hex| params[:colors].each do |name, hex|
c = colors.find {|x| x[:name].to_s == name.to_s} c = colors.find {|x| x[:name].to_s == name.to_s}
c[:hex] = hex c[:hex] = hex
end end if params[:colors]
new_color_scheme.colors = colors new_color_scheme.colors = colors
new_color_scheme.save new_color_scheme.save

View File

@ -83,6 +83,10 @@ class Theme < ActiveRecord::Base
Theme.expire_site_cache! Theme.expire_site_cache!
end end
def default?
SiteSetting.default_theme_key == key
end
def self.lookup_field(key, target, field) def self.lookup_field(key, target, field)
return if key.blank? return if key.blank?

View File

@ -2772,6 +2772,9 @@ en:
base_theme_name: "Base" base_theme_name: "Base"
default: "Light Scheme" default: "Light Scheme"
dark: "Dark Scheme" dark: "Dark Scheme"
default_theme_name: "Default"
dark_theme_name: "Dark"
light_theme_name: "Light"
about: "About" about: "About"
guidelines: "Guidelines" guidelines: "Guidelines"

19
db/fixtures/600_themes.rb Normal file
View File

@ -0,0 +1,19 @@
# we can not guess what to do if customization already started, so skip it
if !Theme.exists?
STDERR.puts "> Seeding dark and light themes"
name = I18n.t("wizard.step.colors.fields.theme_id.choices.dark.label")
dark_scheme = ColorScheme.where.find_by(base_scheme_id: "dark")
dark_scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: "dark")
name = I18n.t('color_schemes.dark_theme_name')
_dark_theme = Theme.create(name: name, user_id: -1,
color_scheme_id: dark_scheme.id,
user_selectable: true)
name = I18n.t('color_schemes.default_theme_name')
default_theme = Theme.create(name: name, user_id: -1,
user_selectable: true)
default_theme.set_default!
end

View File

@ -114,8 +114,8 @@ class Wizard
end end
@wizard.append_step('colors') do |step| @wizard.append_step('colors') do |step|
scheme_id = ColorScheme.where(via_wizard: true).pluck(:base_scheme_id)&.first default_theme = Theme.find_by(key: SiteSetting.default_theme_key)
scheme_id ||= 'default' scheme_id = default_theme&.color_scheme&.base_scheme_id || 'default'
themes = step.add_field(id: 'base_scheme_id', type: 'dropdown', required: true, value: scheme_id) themes = step.add_field(id: 'base_scheme_id', type: 'dropdown', required: true, value: scheme_id)
ColorScheme.base_color_scheme_colors.each do |t| ColorScheme.base_color_scheme_colors.each do |t|
@ -128,37 +128,28 @@ class Wizard
step.on_update do |updater| step.on_update do |updater|
scheme_name = updater.fields[:base_scheme_id] scheme_name = updater.fields[:base_scheme_id]
theme = ColorScheme.base_color_schemes.find{|s| s.base_scheme_id == scheme_name} theme = nil
colors = [] if scheme_name == "dark"
theme.colors.each do |color| scheme = ColorScheme.find_by(base_scheme_id: 'dark', via_wizard: true)
colors << {name: color.name, hex: color.hex }
end
attrs = { name = I18n.t("wizard.step.colors.fields.theme_id.choices.dark.label")
name: I18n.t("wizard.step.colors.fields.theme_id.choices.#{scheme_name}.label"), scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: "dark")
colors: colors,
base_scheme_id: scheme_name
}
scheme = ColorScheme.where(via_wizard: true).first theme = Theme.find_by(color_scheme_id: scheme.id)
if scheme.present? name = I18n.t('color_schemes.dark_theme_name')
attrs[:colors] = colors theme ||= Theme.create(name: name, color_scheme_id: scheme.id)
revisor = ColorSchemeRevisor.new(scheme, attrs)
revisor.revise
else else
attrs[:via_wizard] = true
scheme = ColorScheme.new(attrs) themes = Theme.where(color_scheme_id: nil).order(:id).to_a
scheme.save! theme = themes.find(&:default?)
theme ||= themes.first
name = I18n.t('color_schemes.light_theme_name')
theme ||= Theme.create(name: name)
end end
default_theme = Theme.find_by(key: SiteSetting.default_theme_key) theme.set_default!
unless default_theme
default_theme = Theme.new(name: "Default Theme", user_id: -1)
end
default_theme.color_scheme_id = scheme.id
default_theme.save!
SiteSetting.default_theme_key = default_theme.key
end end
end end

View File

@ -4,6 +4,7 @@ require 'stylesheet/compiler'
describe Stylesheet::Manager do describe Stylesheet::Manager do
it 'does not crash for missing theme' do it 'does not crash for missing theme' do
Theme.clear_default!
link = Stylesheet::Manager.stylesheet_link_tag(:embedded_theme) link = Stylesheet::Manager.stylesheet_link_tag(:embedded_theme)
expect(link).to eq("") expect(link).to eq("")

View File

@ -155,17 +155,14 @@ describe Wizard::StepUpdater do
updater.update updater.update
expect(updater.success?).to eq(true) expect(updater.success?).to eq(true)
expect(wizard.completed_steps?('colors')).to eq(true) expect(wizard.completed_steps?('colors')).to eq(true)
theme = Theme.find_by(key: SiteSetting.default_theme_key) theme = Theme.find_by(key: SiteSetting.default_theme_key)
expect(theme.color_scheme_id).to eq(color_scheme.id) expect(theme.color_scheme.base_scheme_id).to eq('dark')
end end
end end
context "without an existing scheme" do context "without an existing scheme" do
it "creates the scheme" do it "creates the scheme" do
updater = wizard.create_updater('colors', base_scheme_id: 'dark') updater = wizard.create_updater('colors', base_scheme_id: 'dark', allow_dark_light_selection: true)
updater.update updater.update
expect(updater.success?).to eq(true) expect(updater.success?).to eq(true)
expect(wizard.completed_steps?('colors')).to eq(true) expect(wizard.completed_steps?('colors')).to eq(true)
@ -176,6 +173,8 @@ describe Wizard::StepUpdater do
theme = Theme.find_by(key: SiteSetting.default_theme_key) theme = Theme.find_by(key: SiteSetting.default_theme_key)
expect(theme.color_scheme_id).to eq(color_scheme.id) expect(theme.color_scheme_id).to eq(color_scheme.id)
expect(Theme.where(user_selectable: true).count).to eq(2)
end end
end end
end end

View File

@ -12,7 +12,11 @@ describe Admin::ThemesController do
end end
context ' .index' do context ' .index' do
it 'returns success' do it 'correctly returns themes' do
ColorScheme.destroy_all
Theme.destroy_all
theme = Theme.new(name: 'my name', user_id: -1) theme = Theme.new(name: 'my name', user_id: -1)
theme.set_field(target: :common, name: :scss, value: '.body{color: black;}') theme.set_field(target: :common, name: :scss, value: '.body{color: black;}')
theme.set_field(target: :desktop, name: :after_header, value: '<b>test</b>') theme.set_field(target: :desktop, name: :after_header, value: '<b>test</b>')

View File

@ -4,6 +4,8 @@ describe StylesheetCache do
describe "add" do describe "add" do
it "correctly cycles once MAX_TO_KEEP is hit" do it "correctly cycles once MAX_TO_KEEP is hit" do
StylesheetCache.destroy_all
(StylesheetCache::MAX_TO_KEEP + 1).times do |i| (StylesheetCache::MAX_TO_KEEP + 1).times do |i|
StylesheetCache.add("a", "d" + i.to_s, "c" + i.to_s, "map") StylesheetCache.add("a", "d" + i.to_s, "c" + i.to_s, "map")
end end
@ -13,6 +15,8 @@ describe StylesheetCache do
end end
it "does nothing if digest is set and already exists" do it "does nothing if digest is set and already exists" do
StylesheetCache.destroy_all
StylesheetCache.add("a", "b", "c", "map") StylesheetCache.add("a", "b", "c", "map")
StylesheetCache.add("a", "b", "cc", "map") StylesheetCache.add("a", "b", "cc", "map")

View File

@ -152,6 +152,8 @@ HTML
end end
it 'correctly caches theme keys' do it 'correctly caches theme keys' do
Theme.destroy_all
theme = Theme.create!(name: "bob", user_id: -1) theme = Theme.create!(name: "bob", user_id: -1)
expect(Theme.theme_keys).to eq(Set.new([theme.key])) expect(Theme.theme_keys).to eq(Set.new([theme.key]))