Support for url_list site setting.

This commit is contained in:
Robin Ward 2015-03-02 12:12:19 -05:00
parent 35c58c1b00
commit 84b84a9d7c
35 changed files with 327 additions and 373 deletions

View file

@ -0,0 +1,91 @@
import BufferedContent from 'discourse/mixins/buffered-content';
import SiteSetting from 'admin/models/site-setting';
const CustomTypes = ['bool', 'enum', 'list', 'url_list'];
export default Ember.Component.extend(BufferedContent, Discourse.ScrollTop, {
classNameBindings: [':row', ':setting', 'setting.overridden', 'typeClass'],
content: Ember.computed.alias('setting'),
dirty: Discourse.computed.propertyNotEqual('buffered.value', 'setting.value'),
validationMessage: null,
preview: function() {
const preview = this.get('setting.preview');
if (preview) {
return new Handlebars.SafeString("<div class='preview'>" +
preview.replace("{{value}}", this.get('buffered.value')) +
"</div>");
}
}.property('buffered.value'),
typeClass: function() {
return this.get('partialType').replace("_", "-");
}.property('partialType'),
enabled: function(key, value) {
if (arguments.length > 1) {
this.set('buffered.value', value ? 'true' : 'false');
}
const bufferedValue = this.get('buffered.value');
if (Ember.isEmpty(bufferedValue)) { return false; }
return bufferedValue === 'true';
}.property('buffered.value'),
settingName: function() {
return this.get('setting.setting').replace(/\_/g, ' ');
}.property('setting.setting'),
partialType: function() {
let type = this.get('setting.type');
return (CustomTypes.indexOf(type) !== -1) ? type : 'string';
}.property('setting.type'),
partialName: function() {
return 'admin/templates/site-settings/' + this.get('partialType');
}.property('partialType'),
_watchEnterKey: function() {
const self = this;
this.$().on("keydown.site-setting-enter", ".input-setting-string", function (e) {
if (e.keyCode === 13) { // enter key
self._save();
}
});
}.on('didInsertElement'),
_removeBindings: function() {
this.$().off("keydown.site-setting-enter");
}.on("willDestroyElement"),
_save() {
const setting = this.get('buffered');
const self = this;
SiteSetting.update(setting.get('setting'), setting.get('value')).then(function() {
self.set('validationMessage', null);
self.commitBuffer();
}).catch(function(e) {
if (e.responseJSON && e.responseJSON.errors) {
self.set('validationMessage', e.responseJSON.errors[0]);
} else {
self.set('validationMessage', I18n.t('generic_error'));
}
});
},
actions: {
save() {
this._save();
},
resetDefault() {
this.set('buffered.value', this.get('setting.default'));
this._save();
},
cancel() {
this.rollbackBuffer();
}
}
});

View file

@ -0,0 +1,32 @@
export default Ember.Component.extend({
_setupUrls: function() {
const value = this.get('value');
this.set('urls', (value && value.length) ? value.split("\n") : []);
}.on('init').observes('value'),
_urlsChanged: function() {
this.set('value', this.get('urls').join("\n"));
}.observes('urls.@each'),
urlInvalid: Ember.computed.empty('newUrl'),
keyDown(e) {
if (e.keyCode === 13) {
this.send('addUrl');
}
},
actions: {
addUrl() {
if (this.get('urlInvalid')) { return; }
this.get('urls').addObject(this.get('newUrl'));
this.set('newUrl', '');
},
removeUrl(url) {
const urls = this.get('urls');
urls.removeObject(url);
}
}
});

View file

@ -5,46 +5,12 @@ export default Ember.ObjectController.extend({
filteredContent: function() {
if (!this.get('categoryNameKey')) { return []; }
var category = this.get('controllers.adminSiteSettings.content').findProperty('nameKey', this.get('categoryNameKey'));
const category = this.get('controllers.adminSiteSettings.content').findProperty('nameKey', this.get('categoryNameKey'));
if (category) {
return category.siteSettings;
} else {
return [];
}
}.property('controllers.adminSiteSettings.content', 'categoryNameKey'),
actions: {
/**
Reset a setting to its default value
@method resetDefault
@param {Discourse.SiteSetting} setting The setting we want to revert
**/
resetDefault: function(setting) {
setting.set('value', setting.get('default'));
setting.save();
},
/**
Save changes to a site setting
@method save
@param {Discourse.SiteSetting} setting The setting we've changed
**/
save: function(setting) {
setting.save();
},
/**
Cancel changes to a site setting
@method cancel
@param {Discourse.SiteSetting} setting The setting we've changed but want to revert
**/
cancel: function(setting) {
setting.resetValue();
}
}
}.property('controllers.adminSiteSettings.content', 'categoryNameKey')
});

View file

@ -3,17 +3,12 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
onlyOverridden: false,
filtered: Ember.computed.notEmpty('filter'),
/**
The list of settings based on the current filters
@property filterContent
**/
filterContent: Discourse.debounce(function() {
// If we have no content, don't bother filtering anything
if (!this.present('allSiteSettings')) return;
var filter;
let filter;
if (this.get('filter')) {
filter = this.get('filter').toLowerCase();
}
@ -24,12 +19,11 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
return;
}
var self = this,
matches,
matchesGroupedByCategory = Em.A([{nameKey: 'all_results', name: I18n.t('admin.site_settings.categories.all_results'), siteSettings: []}]);
const self = this,
matchesGroupedByCategory = [{nameKey: 'all_results', name: I18n.t('admin.site_settings.categories.all_results'), siteSettings: []}];
_.each(this.get('allSiteSettings'), function(settingsCategory) {
matches = settingsCategory.siteSettings.filter(function(item) {
this.get('allSiteSettings').forEach(function(settingsCategory) {
const matches = settingsCategory.siteSettings.filter(function(item) {
if (self.get('onlyOverridden') && !item.get('overridden')) return false;
if (filter) {
if (item.get('setting').toLowerCase().indexOf(filter) > -1) return true;
@ -51,7 +45,7 @@ export default Ember.ArrayController.extend(Discourse.Presence, {
}, 250).observes('filter', 'onlyOverridden'),
actions: {
clearFilter: function() {
clearFilter() {
this.setProperties({
filter: '',
onlyOverridden: false

View file

@ -0,0 +1,54 @@
const SiteSetting = Discourse.Model.extend({
overridden: function() {
let val = this.get('value'),
defaultVal = this.get('default');
if (val === null) val = '';
if (defaultVal === null) defaultVal = '';
return val.toString() !== defaultVal.toString();
}.property('value', 'default'),
validValues: function() {
const vals = [],
translateNames = this.get('translate_names');
this.get('valid_values').forEach(function(v) {
if (v.name && v.name.length > 0) {
vals.addObject(translateNames ? {name: I18n.t(v.name), value: v.value} : v);
}
});
return vals;
}.property('valid_values'),
allowsNone: function() {
if ( _.indexOf(this.get('valid_values'), '') >= 0 ) return 'admin.site_settings.none';
}.property('valid_values')
});
SiteSetting.reopenClass({
findAll() {
return Discourse.ajax("/admin/site_settings").then(function (settings) {
// Group the results by category
const categories = {};
settings.site_settings.forEach(function(s) {
if (!categories[s.category]) {
categories[s.category] = [];
}
categories[s.category].pushObject(Discourse.SiteSetting.create(s));
});
return Object.keys(categories).map(function(n) {
return {nameKey: n, name: I18n.t('admin.site_settings.categories.' + n), siteSettings: categories[n]};
});
});
},
update(key, value) {
const data = {};
data[key] = value;
return Discourse.ajax("/admin/site_settings/" + key, { type: 'PUT', data });
}
});
export default SiteSetting;

View file

@ -1,136 +0,0 @@
Discourse.SiteSetting = Discourse.Model.extend({
validationMessage: null,
/**
Is the boolean setting true?
@property enabled
**/
enabled: function(key, value) {
if (arguments.length > 1) {
this.set('value', value ? 'true' : 'false');
}
if (this.blank('value')) return false;
return this.get('value') === 'true';
}.property('value'),
/**
The name of the setting. Basically, underscores in the setting key are replaced with spaces.
@property settingName
**/
settingName: function() {
return this.get('setting').replace(/\_/g, ' ');
}.property('setting'),
/**
Has the user changed the setting? If so we should save it.
@property dirty
**/
dirty: function() {
return this.get('originalValue') !== this.get('value');
}.property('originalValue', 'value'),
overridden: function() {
var val = this.get('value'),
defaultVal = this.get('default');
if (val === null) val = '';
if (defaultVal === null) defaultVal = '';
return val.toString() !== defaultVal.toString();
}.property('value', 'default'),
/**
Reset the setting to its original value.
@method resetValue
**/
resetValue: function() {
this.set('value', this.get('originalValue'));
this.set('validationMessage', null);
},
/**
Save the setting's value.
@method save
**/
save: function() {
// Update the setting
var self = this, data = {};
data[this.get('setting')] = this.get('value');
return Discourse.ajax("/admin/site_settings/" + this.get('setting'), {
data: data,
type: 'PUT'
}).then(function() {
self.set('originalValue', self.get('value'));
self.set('validationMessage', null);
}, function(e) {
if (e.responseJSON && e.responseJSON.errors) {
self.set('validationMessage', e.responseJSON.errors[0]);
} else {
self.set('validationMessage', I18n.t('generic_error'));
}
});
},
validValues: function() {
var vals, setting;
vals = Em.A();
setting = this;
_.each(this.get('valid_values'), function(v) {
if (v.name && v.name.length > 0) {
if (setting.translate_names) {
vals.addObject({name: I18n.t(v.name), value: v.value});
} else {
vals.addObject(v);
}
}
});
return vals;
}.property('valid_values'),
allowsNone: function() {
if ( _.indexOf(this.get('valid_values'), '') >= 0 ) return 'admin.site_settings.none';
}.property('valid_values')
});
Discourse.SiteSetting.reopenClass({
findAll: function() {
return Discourse.ajax("/admin/site_settings").then(function (settings) {
// Group the results by category
var categoryNames = [],
categories = {},
result = Em.A();
_.each(settings.site_settings,function(s) {
s.originalValue = s.value;
if (!categoryNames.contains(s.category)) {
categoryNames.pushObject(s.category);
categories[s.category] = Em.A();
}
categories[s.category].pushObject(Discourse.SiteSetting.create(s));
});
_.each(categoryNames, function(n) {
result.pushObject({nameKey: n, name: I18n.t('admin.site_settings.categories.' + n), siteSettings: categories[n]});
});
return result;
});
},
update: function(key, value) {
return Discourse.ajax("/admin/site_settings/" + key, {
type: 'PUT',
data: { value: value }
});
}
});

View file

@ -1,16 +1,8 @@
/**
Handles routes related to viewing and editing site settings within one category.
@class AdminSiteSettingCategoryRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.AdminSiteSettingsCategoryRoute = Discourse.Route.extend({
model: function(params) {
export default Discourse.Route.extend({
model(params) {
// The model depends on user input, so let the controller do the work:
this.controllerFor('adminSiteSettingsCategory').set('categoryNameKey', params.category_id);
return Em.Object.create({
return Ember.Object.create({
nameKey: params.category_id,
name: I18n.t('admin.site_settings.categories.' + params.category_id),
siteSettings: this.controllerFor('adminSiteSettingsCategory').get('filteredContent')

View file

@ -0,0 +1,9 @@
/**
Handles when you click the Site Settings tab in admin, but haven't
chosen a category. It will redirect to the first category.
**/
export default Discourse.Route.extend({
beforeModel() {
this.replaceWith('adminSiteSettingsCategory', this.modelFor('adminSiteSettings')[0].nameKey);
}
});

View file

@ -0,0 +1,11 @@
import SiteSetting from 'admin/models/site-setting';
export default Discourse.Route.extend({
model() {
return SiteSetting.findAll();
},
afterModel(siteSettings) {
this.controllerFor('adminSiteSettings').set('allSiteSettings', siteSettings);
}
});

View file

@ -1,27 +0,0 @@
/**
Handles routes related to viewing and editing site settings.
@class AdminSiteSettingsRoute
@extends Discourse.Route
@namespace Discourse
@module Discourse
**/
Discourse.AdminSiteSettingsRoute = Discourse.Route.extend({
model: function() {
return Discourse.SiteSetting.findAll();
},
afterModel: function(siteSettings) {
this.controllerFor('adminSiteSettings').set('allSiteSettings', siteSettings);
}
});
/**
Handles when you click the Site Settings tab in admin, but haven't
chosen a category. It will redirect to the first category.
**/
Discourse.AdminSiteSettingsIndexRoute = Discourse.Route.extend({
model: function() {
this.replaceWith('adminSiteSettingsCategory', this.modelFor('adminSiteSettings')[0].nameKey);
}
});

View file

@ -0,0 +1,4 @@
<div {{bind-attr class=":validation-error message::hidden"}}>
{{fa-icon "times"}}
{{message}}
</div>

View file

@ -0,0 +1,16 @@
<div class='setting-label'>
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{partial partialName}}
</div>
{{#if dirty}}
<div class='setting-controls'>
{{d-button class="ok no-text" action="save" icon="check"}}
{{d-button class="cancel no-text" action="cancel" icon="times"}}
</div>
{{else}}
{{#if setting.overridden}}
{{d-button action="resetDefault" icon="undo" label="admin.site_settings.reset"}}
{{/if}}
{{/if}}

View file

@ -0,0 +1,18 @@
{{#if urls}}
<div class='urls'>
{{#each url in urls}}
<div class='url'>
{{d-button action="removeUrl"
actionParam=url
icon="times"
class="btn-small no-text"}}
<a href="{{unbound url}}" target="_blank">{{url}}</a>
</div>
{{/each}}
</div>
{{/if}}
<div class='input'>
{{text-field value=newUrl placeholderKey="admin.site_settings.add_url"}}
{{d-button action="addUrl" icon="plus" class="btn-primary btn-small no-text" disabled=urlInvalid}}
</div>

View file

@ -0,0 +1,10 @@
{{#if filteredContent}}
<div class='form-horizontal settings'>
{{#each setting in filteredContent}}
{{site-setting setting=setting saveAction="saveSetting"}}
{{/each}}
</div>
{{else}}
<br/>
{{i18n 'admin.site_settings.no_results'}}
{{/if}}

View file

@ -0,0 +1,4 @@
<label>
{{input type="checkbox" checked=enabled}}
{{unbound setting.description}}
</label>

View file

@ -0,0 +1,4 @@
{{combo-box valueAttribute="value" content=setting.validValues value=buffered.value none=setting.allowsNone}}
{{preview}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{unbound setting.description}}</div>

View file

@ -0,0 +1,3 @@
{{list-setting settingValue=buffered.value choices=setting.choices settingName=setting.setting}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{unbound setting.description}}</div>

View file

@ -0,0 +1,3 @@
{{text-field value=buffered.value classNames="input-setting-string"}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{unbound setting.description}}</div>

View file

@ -0,0 +1,3 @@
{{url-list value=buffered.value}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{unbound setting.description}}</div>

View file

@ -1,19 +0,0 @@
<div class='setting-label'>
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
<label>
{{input type="checkbox" checked=enabled}}
{{unbound description}}
</label>
</div>
{{#if dirty}}
<div class='setting-controls'>
<button class='btn ok no-text' {{action "save" this}}><i class='fa fa-check'></i></button>
<button class='btn cancel no-text' {{action "cancel" this}}><i class='fa fa-times'></i></button>
</div>
{{else}}
{{#if overridden}}
<button class='btn' href='#' {{action "resetDefault" this}}><i class="fa fa-undo"></i>{{i18n 'admin.site_settings.reset'}}</button>
{{/if}}
{{/if}}

View file

@ -1,18 +0,0 @@
<div class='setting-label'>
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{combo-box valueAttribute="value" content=validValues value=value none=allowsNone}}
{{view.preview}}
<div class='desc'>{{unbound description}}</div>
</div>
{{#if dirty}}
<div class='setting-controls'>
<button class='btn ok no-text' {{action "save" this}}><i class='fa fa-check'></i></button>
<button class='btn cancel no-text' {{action "cancel" this}}><i class='fa fa-times'></i></button>
</div>
{{else}}
{{#if overridden}}
<button class='btn' href='#' {{action "resetDefault" this}}><i class="fa fa-undo"></i>{{i18n 'admin.site_settings.reset'}}</button>
{{/if}}
{{/if}}

View file

@ -1,18 +0,0 @@
<div class='setting-label'>
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{list-setting settingValue=value choices=choices settingName=setting}}
<div {{bind-attr class=":validation-error validationMessage::hidden"}}><i class='fa fa-times'></i> {{validationMessage}}</div>
<div class='desc'>{{{unbound description}}}</div>
</div>
{{#if dirty}}
<div class='setting-controls'>
<button class='btn ok no-text' {{action "save" this}}><i class='fa fa-check'></i></button>
<button class='btn cancel no-text' {{action "cancel" this}}><i class='fa fa-times'></i></button>
</div>
{{else}}
{{#if overridden}}
<button class='btn' href='#' {{action "resetDefault" this}}><i class="fa fa-undo"></i>{{i18n 'admin.site_settings.reset'}}</button>
{{/if}}
{{/if}}

View file

@ -1,18 +0,0 @@
<div class='setting-label'>
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{text-field value=value classNames="input-setting-string"}}
<div {{bind-attr class=":validation-error validationMessage::hidden"}}><i class='fa fa-times'></i> {{validationMessage}}</div>
<div class='desc'>{{unbound description}}</div>
</div>
{{#if dirty}}
<div class='setting-controls'>
<button class='btn ok no-text' {{action "save" this}}><i class='fa fa-check'></i></button>
<button class='btn cancel no-text' {{action "cancel" this}}><i class='fa fa-times'></i></button>
</div>
{{else}}
{{#if overridden}}
<button class='btn' href='#' {{action "resetDefault" this}}><i class="fa fa-undo"></i>{{i18n 'admin.site_settings.reset'}}</button>
{{/if}}
{{/if}}

View file

@ -1,6 +0,0 @@
{{#if filteredContent.length}}
{{collection contentBinding="filteredContent" classNames="form-horizontal settings" itemView="site-setting"}}
{{else}}
<br/>
{{i18n 'admin.site_settings.no_results'}}
{{/if}}

View file

@ -1,3 +0,0 @@
Discourse.AdminSiteSettingsCategoryView = Discourse.View.extend({
templateName: 'admin/templates/site_settings_category'
});

View file

@ -1,45 +0,0 @@
export default Discourse.View.extend(Discourse.ScrollTop, {
classNameBindings: [':row', ':setting', 'content.overridden'],
preview: function() {
var preview = this.get('content.preview');
if(preview){
return new Handlebars.SafeString("<div class='preview'>" +
preview.replace("{{value}}",this.get('content.value')) +
"</div>"
);
}
}.property('content.value'),
templateName: function() {
// If we're editing a boolean, show a checkbox
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';
// If we're editing a list, show a list editor
if (this.get('content.type') === 'list') return 'admin/templates/site_settings/setting_list';
// Default to string editor
return 'admin/templates/site_settings/setting_string';
}.property('content.type'),
_watchEnterKey: function() {
var self = this;
this.$().on("keydown.site-setting-enter", ".input-setting-string", function (e) {
if (e.keyCode === 13) { // enter key
var setting = self.get('content');
if (setting.get('dirty')) {
setting.save();
}
}
});
}.on('didInsertElement'),
_removeBindings: function() {
this.$().off("keydown.site-setting-enter");
}.on("willDestroyElement")
});

View file

@ -52,11 +52,10 @@ export default Discourse.View.extend({
var $combo = this.$(),
val = this.get('value');
if (val !== undefined && val !== null) {
$combo.val(val.toString());
$combo.select2('val', val.toString());
} else {
$combo.val(null);
$combo.select2('val', null);
}
$combo.trigger("liszt:updated");
}.observes('value'),
contentChanged: function() {

View file

@ -1,5 +1,6 @@
//= require list-view
//= require admin/models/user-field
//= require admin/models/site-setting
//= require admin/controllers/admin-email-skipped
//= require admin/controllers/change-site-customization-details
//= require discourse/lib/export-result

View file

@ -282,15 +282,16 @@ td.flaggers td {
}
.setting.overridden {
input[type=text] {
background-color: dark-light-diff($highlight, $secondary, 50%, -60%);
}
h3 {
color: scale-color($highlight, $lightness: -50%);
}
}
.setting.overridden.string {
input[type=text] {
background-color: dark-light-diff($highlight, $secondary, 50%, -60%);
}
}
}
section.details {
@ -1446,3 +1447,23 @@ table#user-badges {
max-width: 200px;
}
}
.url-list {
.url {
border-bottom: 1px solid #ddd;
padding: 3px;
margin-right: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.urls {
margin-bottom: 10px;
}
input[type=text] {
width: 90%;
}
}

View file

@ -1,9 +1,7 @@
class Admin::SiteSettingsController < Admin::AdminController
def index
site_settings = SiteSetting.all_settings
info = {site_settings: site_settings, diags: SiteSetting.diags }
render_json_dump(info.as_json)
render_json_dump(site_settings: SiteSetting.all_settings, diags: SiteSetting.diags)
end
def update

View file

@ -2161,6 +2161,7 @@ en:
none: 'none'
no_results: "No results found."
clear_filter: "Clear"
add_url: "add URL"
categories:
all_results: 'All'
required: 'Required'

View file

@ -1067,6 +1067,7 @@ en:
allow_uploaded_avatars: "Allow users to upload custom avatars."
allow_animated_avatars: "Allow users to use animated gif avatars. WARNING: run the avatars:refresh rake task after changing this setting."
allow_animated_thumbnails: "Generates animated thumbnails of animated gifs."
default_avatars: "URLs to avatars that will be used by default for new users until they change them."
automatically_download_gravatars: "Download Gravatars for users upon account creation or email change."
digest_topics: "The maximum number of topics to display in the email digest."
digest_min_excerpt_length: "Minimum post excerpt in the email digest, in characters."

View file

@ -515,6 +515,10 @@ files:
client: true
default: false
allow_animated_thumbnails: false
avatars:
default_avatars:
default: ''
type: url_list
trust:
default_trust_level:

View file

@ -14,7 +14,7 @@ module SiteSettingExtension
end
def types
@types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list)
@types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list, :url_list)
end
def mutex
@ -38,8 +38,8 @@ module SiteSettingExtension
@enums ||= {}
end
def lists
@lists ||= []
def static_types
@static_types ||= {}
end
def choices
@ -73,9 +73,9 @@ module SiteSettingExtension
categories[name] = opts[:category] || :uncategorized
current_value = current.has_key?(name) ? current[name] : default
if opts[:enum]
enum = opts[:enum]
if enum = opts[:enum]
enums[name] = enum.is_a?(String) ? enum.constantize : enum
opts[:type] ||= :enum
end
if opts[:choices]
@ -84,8 +84,8 @@ module SiteSettingExtension
choices[name] = opts[:choices]
end
if opts[:type] == 'list'
lists << name
if type = opts[:type]
static_types[name.to_sym] = type.to_sym
end
if opts[:hidden]
@ -257,7 +257,7 @@ module SiteSettingExtension
clear_cache!
end
def add_override!(name,val)
def add_override!(name, val)
type = get_data_type(name, defaults[name])
if type == types[:bool] && val != true && val != false
@ -344,10 +344,14 @@ module SiteSettingExtension
[changes,deletions]
end
def get_data_type(name,val)
def get_data_type(name, val)
return types[:null] if val.nil?
return types[:enum] if enums[name]
return types[:list] if lists.include? name
# Some types are just for validations like email. Only consider
# it valid if includes in `types`
if static_type = static_types[name.to_sym]
return types[static_type] if types.keys.include?(static_type)
end
case val
when String
@ -369,13 +373,14 @@ module SiteSettingExtension
value.to_f
when types[:fixnum]
value.to_i
when types[:string], types[:list], types[:enum]
value
when types[:bool]
value == true || value == "t" || value == "true"
when types[:null]
nil
else
return value if types[type]
# Otherwise it's a type error
raise ArgumentError.new :type
end
end