diff --git a/app/assets/javascripts/admin/models/site_setting.js b/app/assets/javascripts/admin/models/site_setting.js
index 5e0ac79c1..5768208ad 100644
--- a/app/assets/javascripts/admin/models/site_setting.js
+++ b/app/assets/javascripts/admin/models/site_setting.js
@@ -78,7 +78,16 @@ Discourse.SiteSetting = Discourse.Model.extend({
}).then(function() {
setting.set('originalValue', setting.get('value'));
});
- }
+ },
+
+ validValues: function() {
+ var vals;
+ vals = Em.A();
+ this.get("valid_values").each(function(v){
+ vals.addObject({ name: v, value: v });
+ });
+ return vals;
+ }.property('valid_values')
});
Discourse.SiteSetting.reopenClass({
diff --git a/app/assets/javascripts/admin/templates/site_settings/setting_enum.js.handlebars b/app/assets/javascripts/admin/templates/site_settings/setting_enum.js.handlebars
new file mode 100644
index 000000000..a3d7920eb
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site_settings/setting_enum.js.handlebars
@@ -0,0 +1,19 @@
+{{#with view.content}}
+
+
{{unbound setting}}
+
+
+ {{combobox valueAttribute="value" content=validValues value=value}}
+
{{unbound description}}
+
+ {{#if dirty}}
+
+
+
+
+ {{else}}
+ {{#if overridden}}
+
+ {{/if}}
+ {{/if}}
+{{/with}}
\ No newline at end of file
diff --git a/app/assets/javascripts/admin/views/site_setting_view.js b/app/assets/javascripts/admin/views/site_setting_view.js
index 8a6dc7e28..140714aa2 100644
--- a/app/assets/javascripts/admin/views/site_setting_view.js
+++ b/app/assets/javascripts/admin/views/site_setting_view.js
@@ -12,7 +12,10 @@ Discourse.SiteSettingView = Discourse.View.extend({
templateName: function() {
// If we're editing a boolean, return a different template
- if (this.get('content.type') === 'bool') return 'admin/templates/site_settings/setting_bool'
+ if (this.get('content.type') === 'bool') return 'admin/templates/site_settings/setting_bool';
+
+ // If we're editing an enum field, show a dropdown
+ if (this.get('content.type') === 'enum' ) return 'admin/templates/site_settings/setting_enum';
// Default to string editor
return 'admin/templates/site_settings/setting_string';
diff --git a/app/models/locale_site_setting.rb b/app/models/locale_site_setting.rb
new file mode 100644
index 000000000..904a7fba5
--- /dev/null
+++ b/app/models/locale_site_setting.rb
@@ -0,0 +1,21 @@
+class LocaleSiteSetting
+
+ def self.valid_value?(val)
+ supported_locales.include?(val)
+ end
+
+ def self.all_values
+ supported_locales
+ end
+
+
+ private
+
+ @lock = Mutex.new
+
+ def self.supported_locales
+ @lock.synchronize do
+ @supported_locales ||= Dir.glob( File.join(Rails.root, 'config', 'locales', 'client.*.yml') ).map {|x| x.split('.')[-2]}
+ end
+ end
+end
diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
index c31fd0cd6..acdf6ff46 100644
--- a/app/models/site_setting.rb
+++ b/app/models/site_setting.rb
@@ -203,7 +203,7 @@ class SiteSetting < ActiveRecord::Base
setting(:title_fancy_entities, true)
# The default locale for the site
- setting(:default_locale, 'en')
+ setting(:default_locale, 'en', enum: 'LocaleSiteSetting')
client_setting(:educate_until_posts, 2)
diff --git a/lib/site_setting_extension.rb b/lib/site_setting_extension.rb
index 60aff615d..f7ad6913e 100644
--- a/lib/site_setting_extension.rb
+++ b/lib/site_setting_extension.rb
@@ -3,7 +3,7 @@ require_dependency 'enum'
module SiteSettingExtension
def types
- @types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null)
+ @types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum)
end
def mutex
@@ -19,10 +19,15 @@ module SiteSettingExtension
@defaults ||= {}
end
- def setting(name, default = nil)
+ def enums
+ @enums ||= {}
+ end
+
+ def setting(name, default = nil, opts = {})
mutex.synchronize do
self.defaults[name] = default
current_value = current.has_key?(name) ? current[name] : default
+ enums[name] = opts[:enum] if opts[:enum]
setup_methods(name, current_value)
end
end
@@ -56,11 +61,12 @@ module SiteSettingExtension
def all_settings
@defaults.map do |s, v|
value = send(s)
+ type = types[get_data_type(s, value)]
{setting: s,
description: description(s),
default: v,
- type: types[get_data_type(value)].to_s,
- value: value.to_s}
+ type: type.to_s,
+ value: value.to_s}.merge( type == :enum ? {valid_values: enum_class(s).all_values} : {})
end
end
@@ -154,7 +160,7 @@ module SiteSettingExtension
return unless table_exists?
setting = SiteSetting.where(name: name).first
- type = get_data_type(defaults[name])
+ type = get_data_type(name, defaults[name])
if type == types[:bool] && val != true && val != false
val = (val == "t" || val == "true") ? 't' : 'f'
@@ -165,7 +171,11 @@ module SiteSettingExtension
end
if type == types[:null] && val != ''
- type = get_data_type(val)
+ type = get_data_type(name, val)
+ end
+
+ if type == types[:enum]
+ raise Discourse::InvalidParameters.new(:value) unless enum_class(name).valid_value?(val)
end
if setting
@@ -182,10 +192,12 @@ module SiteSettingExtension
protected
- def get_data_type(val)
+ def get_data_type(name,val)
return types[:null] if val.nil?
- if String === val
+ if enums[name]
+ types[:enum]
+ elsif String === val
types[:string]
elsif Fixnum === val
types[:fixnum]
@@ -200,7 +212,7 @@ module SiteSettingExtension
case type
when types[:fixnum]
value.to_i
- when types[:string]
+ when types[:string], types[:enum]
value
when types[:bool]
value == "t"
@@ -242,6 +254,10 @@ module SiteSettingExtension
super(method, *args, &block)
end
+ def enum_class(name)
+ enums[name] = enums[name].constantize unless enums[name].is_a?(Class)
+ enums[name]
+ end
end
diff --git a/spec/controllers/admin/site_settings_controller_spec.rb b/spec/controllers/admin/site_settings_controller_spec.rb
index 36d0b3982..1644ff2e3 100644
--- a/spec/controllers/admin/site_settings_controller_spec.rb
+++ b/spec/controllers/admin/site_settings_controller_spec.rb
@@ -26,7 +26,7 @@ describe Admin::SiteSettingsController do
context 'update' do
it 'requires a value parameter' do
- lambda { xhr :put, :update, id: 'test_setting' }.should raise_error(ActionController::ParameterMissing)
+ lambda { xhr :put, :update, id: 'test_setting' }.should raise_error(ActionController::ParameterMissing)
end
it 'sets the value when the param is present' do
diff --git a/spec/models/locale_site_setting_spec.rb b/spec/models/locale_site_setting_spec.rb
new file mode 100644
index 000000000..c7114fb98
--- /dev/null
+++ b/spec/models/locale_site_setting_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe LocaleSiteSetting do
+
+ describe 'valid_value?' do
+ it 'returns true for a locale that we have translations for' do
+ expect(LocaleSiteSetting.valid_value?('en')).to eq(true)
+ end
+
+ it 'returns false for a locale that we do not have translations for' do
+ expect(LocaleSiteSetting.valid_value?('swedish-chef')).to eq(false)
+ end
+ end
+
+ describe 'all_values' do
+ it 'returns all the locales that we have translations for' do
+ expect(LocaleSiteSetting.all_values.sort).to eq(Dir.glob( File.join(Rails.root, 'config', 'locales', 'client.*.yml') ).map {|x| x.split('.')[-2]}.sort)
+ end
+ end
+
+end
diff --git a/spec/models/site_setting_spec.rb b/spec/models/site_setting_spec.rb
index 31584f82b..62b6f3901 100644
--- a/spec/models/site_setting_spec.rb
+++ b/spec/models/site_setting_spec.rb
@@ -114,6 +114,35 @@ describe SiteSetting do
end
end
+ describe 'enum setting' do
+ before :all do
+ @enum_class = Class.new
+ SiteSetting.setting(:test_enum, 'en', enum: @enum_class)
+ SiteSetting.refresh!
+ end
+
+ it 'should have the correct default' do
+ expect(SiteSetting.test_enum).to eq('en')
+ end
+
+ context 'when overridden' do
+ after :each do
+ SiteSetting.remove_override!(:test_enum)
+ end
+
+ it 'stores valid values' do
+ @enum_class.expects(:valid_value?).with('fr').returns(true)
+ SiteSetting.test_enum = 'fr'
+ expect(SiteSetting.test_enum).to eq('fr')
+ end
+
+ it 'rejects invalid values' do
+ @enum_class.expects(:valid_value?).with('gg').returns(false)
+ expect { SiteSetting.test_enum = 'gg' }.to raise_error(Discourse::InvalidParameters)
+ end
+ end
+ end
+
describe 'call_discourse_hub?' do
it 'should be true when enforce_global_nicknames is true and discourse_org_access_key is set' do
SiteSetting.enforce_global_nicknames = true