diff --git a/app/assets/javascripts/admin/models/color-scheme-color.js.es6 b/app/assets/javascripts/admin/models/color-scheme-color.js.es6 index a2f1a7b12d6..a3b22d23bc6 100644 --- a/app/assets/javascripts/admin/models/color-scheme-color.js.es6 +++ b/app/assets/javascripts/admin/models/color-scheme-color.js.es6 @@ -3,7 +3,7 @@ import { observes, on } from "ember-addons/ember-computed-decorators"; -import { propertyNotEqual, i18n } from "discourse/lib/computed"; +import { propertyNotEqual } from "discourse/lib/computed"; const ColorSchemeColor = Discourse.Model.extend({ @on("init") @@ -42,9 +42,23 @@ const ColorSchemeColor = Discourse.Model.extend({ } }, - translatedName: i18n("name", "admin.customize.colors.%@.name"), + @computed("name") + translatedName(name) { + if (!this.is_advanced) { + return I18n.t(`admin.customize.colors.${name}.name`); + } else { + return name; + } + }, - description: i18n("name", "admin.customize.colors.%@.description"), + @computed("name") + description(name) { + if (!this.is_advanced) { + return I18n.t(`admin.customize.colors.${name}.description`); + } else { + return ""; + } + }, /** brightness returns a number between 0 (darkest) to 255 (brightest). diff --git a/app/assets/javascripts/admin/models/color-scheme.js.es6 b/app/assets/javascripts/admin/models/color-scheme.js.es6 index 5276ef849d0..26c8ccdc0ed 100644 --- a/app/assets/javascripts/admin/models/color-scheme.js.es6 +++ b/app/assets/javascripts/admin/models/color-scheme.js.es6 @@ -128,7 +128,8 @@ ColorScheme.reopenClass({ return ColorSchemeColor.create({ name: c.name, hex: c.hex, - default_hex: c.default_hex + default_hex: c.default_hex, + is_advanced: c.is_advanced }); }) }) diff --git a/app/assets/stylesheets/common/foundation/color_transformations.scss b/app/assets/stylesheets/common/foundation/color_transformations.scss new file mode 100644 index 00000000000..ca6068a774d --- /dev/null +++ b/app/assets/stylesheets/common/foundation/color_transformations.scss @@ -0,0 +1,77 @@ +// standard color transformations, use these if possible, and add any new dark-light-diffs here +// any variables defined here can be added in theme color schemes +// all variables should have the !default flag + +//primary +$primary-very-low: dark-light-diff($primary, $secondary, 97%, -82%) !default; +$primary-low: dark-light-diff($primary, $secondary, 90%, -78%) !default; +$primary-low-mid: dark-light-diff($primary, $secondary, 70%, -45%) !default; +$primary-medium: dark-light-diff($primary, $secondary, 50%, -35%) !default; +$primary-high: dark-light-diff($primary, $secondary, 30%, -25%) !default; +$primary-very-high: dark-light-diff($primary, $secondary, 15%, -10%) !default; + +//header_primary +$header_primary-low: dark-light-diff( + $header_primary, + $header_background, + 90%, + -78% +) !default; +$header_primary-low-mid: dark-light-diff( + $header_primary, + $header_background, + 70%, + -45% +) !default; + +$header_primary-medium: dark-light-diff( + $header_primary, + $header_background, + 50%, + -35% +) !default; +$header_primary-high: dark-light-diff( + $header_primary, + $header_background, + 30%, + -25% +) !default; +$header_primary-very-high: dark-light-diff( + $header_primary, + $header_background, + 15%, + -10% +) !default; + +//secondary +$secondary-low: dark-light-diff($secondary, $primary, 70%, -70%) !default; +$secondary-medium: dark-light-diff($secondary, $primary, 50%, -50%) !default; +$secondary-high: dark-light-diff($secondary, $primary, 30%, -35%) !default; +$secondary-very-high: dark-light-diff($secondary, $primary, 7%, -7%) !default; + +//tertiary +$tertiary-low: dark-light-diff($tertiary, $secondary, 85%, -65%) !default; +$tertiary-medium: dark-light-diff($tertiary, $secondary, 50%, -45%) !default; +$tertiary-high: dark-light-diff($tertiary, $secondary, 20%, -25%) !default; + +//quaternary +$quaternary-low: dark-light-diff($quaternary, $secondary, 70%, -70%) !default; + +//highlight +$highlight-low: dark-light-diff($highlight, $secondary, 70%, -80%) !default; +$highlight-medium: dark-light-diff($highlight, $secondary, 50%, -55%) !default; +$highlight-high: dark-light-diff($highlight, $secondary, -50%, -10%) !default; + +//danger +$danger-low: dark-light-diff($danger, $secondary, 85%, -64%) !default; +$danger-medium: dark-light-diff($danger, $secondary, 30%, -35%) !default; + +//success +$success-low: dark-light-diff($success, $secondary, 80%, -60%) !default; +$success-medium: dark-light-diff($success, $secondary, 50%, -40%) !default; + +//love +$love-low: dark-light-diff($love, $secondary, 85%, -60%) !default; + +//wiki +$wiki: green !default; diff --git a/app/assets/stylesheets/common/foundation/variables.scss b/app/assets/stylesheets/common/foundation/variables.scss index 71efde7ed1e..644d3ee5995 100644 --- a/app/assets/stylesheets/common/foundation/variables.scss +++ b/app/assets/stylesheets/common/foundation/variables.scss @@ -204,78 +204,4 @@ $box-shadow: ( } } -// standard color transformations, use these if possible, and add any new dark-light-diffs here - -//primary -$primary-very-low: dark-light-diff($primary, $secondary, 97%, -82%); -$primary-low: dark-light-diff($primary, $secondary, 90%, -78%); -$primary-low-mid: dark-light-diff($primary, $secondary, 70%, -45%); -$primary-medium: dark-light-diff($primary, $secondary, 50%, -35%); -$primary-high: dark-light-diff($primary, $secondary, 30%, -25%); -$primary-very-high: dark-light-diff($primary, $secondary, 15%, -10%); - -//header_primary -$header_primary-low: dark-light-diff( - $header_primary, - $header_background, - 90%, - -78% -); -$header_primary-low-mid: dark-light-diff( - $header_primary, - $header_background, - 70%, - -45% -); - -$header_primary-medium: dark-light-diff( - $header_primary, - $header_background, - 50%, - -35% -); -$header_primary-high: dark-light-diff( - $header_primary, - $header_background, - 30%, - -25% -); -$header_primary-very-high: dark-light-diff( - $header_primary, - $header_background, - 15%, - -10% -); - -//secondary -$secondary-low: dark-light-diff($secondary, $primary, 70%, -70%); -$secondary-medium: dark-light-diff($secondary, $primary, 50%, -50%); -$secondary-high: dark-light-diff($secondary, $primary, 30%, -35%); -$secondary-very-high: dark-light-diff($secondary, $primary, 7%, -7%); - -//tertiary -$tertiary-low: dark-light-diff($tertiary, $secondary, 85%, -65%); -$tertiary-medium: dark-light-diff($tertiary, $secondary, 50%, -45%); -$tertiary-high: dark-light-diff($tertiary, $secondary, 20%, -25%); - -//quaternary -$quaternary-low: dark-light-diff($quaternary, $secondary, 70%, -70%); - -//highlight -$highlight-low: dark-light-diff($highlight, $secondary, 70%, -80%); -$highlight-medium: dark-light-diff($highlight, $secondary, 50%, -55%); -$highlight-high: dark-light-diff($highlight, $secondary, -50%, -10%); - -//danger -$danger-low: dark-light-diff($danger, $secondary, 85%, -64%); -$danger-medium: dark-light-diff($danger, $secondary, 30%, -35%); - -//success -$success-low: dark-light-diff($success, $secondary, 80%, -60%); -$success-medium: dark-light-diff($success, $secondary, 50%, -40%); - -//love -$love-low: dark-light-diff($love, $secondary, 85%, -60%); - -//wiki -$wiki: green; +@import "color_transformations"; diff --git a/app/models/color_scheme.rb b/app/models/color_scheme.rb index 151f8c353f8..c242b634428 100644 --- a/app/models/color_scheme.rb +++ b/app/models/color_scheme.rb @@ -140,6 +140,7 @@ class ColorScheme < ActiveRecord::Base validates_associated :color_scheme_colors BASE_COLORS_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/colors.scss" + COLOR_TRANSFORMATION_FILE = "#{Rails.root}/app/assets/stylesheets/common/foundation/color_transformations.scss" @mutex = Mutex.new @@ -157,6 +158,20 @@ class ColorScheme < ActiveRecord::Base @base_colors end + def self.color_transformation_variables + return @transformation_variables if @transformation_variables + @mutex.synchronize do + return @transformation_variables if @transformation_variables + transformation_variables = [] + File.readlines(COLOR_TRANSFORMATION_FILE).each do |line| + matches = /\$([\w\-_]+):.*/.match(line.strip) + transformation_variables.append(matches[1]) if matches + end + @transformation_variables = transformation_variables + end + @transformation_variables + end + def self.base_color_schemes base_color_scheme_colors.map do |hash| scheme = new(name: I18n.t("color_schemes.#{hash[:id].downcase.gsub(' ', '_')}"), base_scheme_id: hash[:id]) diff --git a/app/models/remote_theme.rb b/app/models/remote_theme.rb index 86d78030d2e..4949f3b0366 100644 --- a/app/models/remote_theme.rb +++ b/app/models/remote_theme.rb @@ -203,24 +203,32 @@ class RemoteTheme < ActiveRecord::Base schemes&.each do |name, colors| missing_scheme_names.delete(name) - existing = theme.color_schemes.find_by(name: name) - if existing - existing.colors.each do |c| - override = normalize_override(colors[c.name]) - if override && c.hex != override - c.hex = override - theme.notify_color_change(c) - end - end - ordered_schemes << existing - else - scheme = theme.color_schemes.build(name: name) - ColorScheme.base.colors_hashes.each do |color| - override = normalize_override(colors[color[:name]]) - scheme.color_scheme_colors << ColorSchemeColor.new(name: color[:name], hex: override || color[:hex]) - end - ordered_schemes << scheme + scheme = theme.color_schemes.find_by(name: name) || theme.color_schemes.build(name: name) + + # Update main colors + ColorScheme.base.colors_hashes.each do |color| + override = normalize_override(colors[color[:name]]) + color_scheme_color = scheme.color_scheme_colors.to_a.find { |c| c.name == color[:name] } || + scheme.color_scheme_colors.build(name: color[:name]) + color_scheme_color.hex = override || color[:hex] + theme.notify_color_change(color_scheme_color) end + + # Update advanced colors + ColorScheme.color_transformation_variables.each do |variable_name| + override = normalize_override(colors[variable_name]) + color_scheme_color = scheme.color_scheme_colors.to_a.find { |c| c.name == variable_name } + if override + color_scheme_color ||= scheme.color_scheme_colors.build(name: variable_name) + color_scheme_color.hex = override + theme.notify_color_change(color_scheme_color) + elsif color_scheme_color # No longer specified in about.json, delete record + scheme.color_scheme_colors.delete(color_scheme_color) + theme.notify_color_change(nil, scheme: scheme) + end + end + + ordered_schemes << scheme end if missing_scheme_names.length > 0 diff --git a/app/models/theme.rb b/app/models/theme.rb index 72e9471fb4e..d5d855434be 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -34,20 +34,18 @@ class Theme < ActiveRecord::Base where('user_selectable OR id = ?', SiteSetting.default_theme_id) } - def notify_color_change(color) - changed_colors << color + def notify_color_change(color, scheme: nil) + scheme ||= color.color_scheme + changed_colors << color if color + changed_schemes << scheme if scheme end after_save do - color_schemes = {} - changed_colors.each do |color| - color.save! - color_schemes[color.color_scheme_id] ||= color.color_scheme - end - - color_schemes.values.each(&:save!) + changed_colors.each(&:save!) + changed_schemes.each(&:save!) changed_colors.clear + changed_schemes.clear changed_fields.each(&:save!) changed_fields.clear @@ -343,6 +341,10 @@ class Theme < ActiveRecord::Base @changed_colors ||= [] end + def changed_schemes + @changed_schemes ||= Set.new + end + def set_field(target:, name:, value: nil, type: nil, type_id: nil, upload_id: nil) name = name.to_s diff --git a/app/serializers/color_scheme_color_serializer.rb b/app/serializers/color_scheme_color_serializer.rb index fdc0e796ad3..a4bb2073fb7 100644 --- a/app/serializers/color_scheme_color_serializer.rb +++ b/app/serializers/color_scheme_color_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ColorSchemeColorSerializer < ApplicationSerializer - attributes :name, :hex, :default_hex + attributes :name, :hex, :default_hex, :is_advanced def hex object.hex # otherwise something crazy is returned @@ -15,4 +15,8 @@ class ColorSchemeColorSerializer < ApplicationSerializer object.hex end end + + def is_advanced + !ColorScheme.base_colors.keys.include?(object.name) + end end diff --git a/spec/models/remote_theme_spec.rb b/spec/models/remote_theme_spec.rb index 83d5a3f2b06..f27c73242d3 100644 --- a/spec/models/remote_theme_spec.rb +++ b/spec/models/remote_theme_spec.rb @@ -20,7 +20,7 @@ describe RemoteTheme do repo_dir end - def about_json(love_color: "FAFAFA", color_scheme_name: "Amazing", about_url: "https://www.site.com/about") + def about_json(love_color: "FAFAFA", tertiary_low_color: "FFFFFF", color_scheme_name: "Amazing", about_url: "https://www.site.com/about") <<~JSON { "name": "awesome theme", @@ -33,7 +33,8 @@ describe RemoteTheme do }, "color_schemes": { "#{color_scheme_name}": { - "love": "#{love_color}" + "love": "#{love_color}", + "tertiary-low": "#{tertiary_low_color}" } } } @@ -105,6 +106,7 @@ describe RemoteTheme do scheme = ColorScheme.find_by(theme_id: @theme.id) expect(scheme.name).to eq("Amazing") expect(scheme.colors.find_by(name: 'love').hex).to eq('fafafa') + expect(scheme.colors.find_by(name: 'tertiary-low').hex).to eq('ffffff') expect(@theme.color_scheme_id).to eq(scheme.id) @theme.update(color_scheme_id: nil) @@ -150,7 +152,7 @@ describe RemoteTheme do expect(remote.about_url).to eq("https://newsite.com/about") # It should be able to remove old colors as well - File.write("#{initial_repo}/about.json", about_json(love_color: "BABABA", color_scheme_name: "Amazing 2")) + File.write("#{initial_repo}/about.json", about_json(love_color: "BABABA", tertiary_low_color: "", color_scheme_name: "Amazing 2")) `cd #{initial_repo} && git commit -am "update"` remote.update_from_remote @@ -160,6 +162,9 @@ describe RemoteTheme do scheme_count = ColorScheme.where(theme_id: @theme.id).count expect(scheme_count).to eq(1) + scheme = ColorScheme.find_by(theme_id: @theme.id) + expect(scheme.colors.find_by(name: 'tertiary_low_color')).to eq(nil) + # It should detect local changes @theme.set_field(target: :common, name: :scss, value: 'body {background-color: blue};') @theme.save