diff --git a/app/assets/javascripts/admin/components/site-setting.js.es6 b/app/assets/javascripts/admin/components/site-setting.js.es6
new file mode 100644
index 00000000000..4703950d714
--- /dev/null
+++ b/app/assets/javascripts/admin/components/site-setting.js.es6
@@ -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("
" +
+ preview.replace("{{value}}", this.get('buffered.value')) +
+ "
");
+ }
+ }.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();
+ }
+ }
+
+});
diff --git a/app/assets/javascripts/admin/components/url-list.js.es6 b/app/assets/javascripts/admin/components/url-list.js.es6
new file mode 100644
index 00000000000..4562c4b20e6
--- /dev/null
+++ b/app/assets/javascripts/admin/components/url-list.js.es6
@@ -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);
+ }
+ }
+});
diff --git a/app/assets/javascripts/admin/controllers/admin-site-settings-category.js.es6 b/app/assets/javascripts/admin/controllers/admin-site-settings-category.js.es6
index 4f5fed4539a..37bc9b37650 100644
--- a/app/assets/javascripts/admin/controllers/admin-site-settings-category.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-site-settings-category.js.es6
@@ -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')
});
diff --git a/app/assets/javascripts/admin/controllers/admin-site-settings.js.es6 b/app/assets/javascripts/admin/controllers/admin-site-settings.js.es6
index a518c916795..95fdff940e9 100644
--- a/app/assets/javascripts/admin/controllers/admin-site-settings.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-site-settings.js.es6
@@ -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
diff --git a/app/assets/javascripts/admin/models/site-setting.js.es6 b/app/assets/javascripts/admin/models/site-setting.js.es6
new file mode 100644
index 00000000000..1d769369cab
--- /dev/null
+++ b/app/assets/javascripts/admin/models/site-setting.js.es6
@@ -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;
diff --git a/app/assets/javascripts/admin/models/site_setting.js b/app/assets/javascripts/admin/models/site_setting.js
deleted file mode 100644
index 0c32fcbabd2..00000000000
--- a/app/assets/javascripts/admin/models/site_setting.js
+++ /dev/null
@@ -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 }
- });
- }
-
-});
-
-
diff --git a/app/assets/javascripts/admin/routes/admin_site_settings_category_route.js b/app/assets/javascripts/admin/routes/admin-site-settings-category.js.es6
similarity index 54%
rename from app/assets/javascripts/admin/routes/admin_site_settings_category_route.js
rename to app/assets/javascripts/admin/routes/admin-site-settings-category.js.es6
index b07967e970b..cf4caf53295 100644
--- a/app/assets/javascripts/admin/routes/admin_site_settings_category_route.js
+++ b/app/assets/javascripts/admin/routes/admin-site-settings-category.js.es6
@@ -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')
diff --git a/app/assets/javascripts/admin/routes/admin-site-settings-index.js.es6 b/app/assets/javascripts/admin/routes/admin-site-settings-index.js.es6
new file mode 100644
index 00000000000..727615c4670
--- /dev/null
+++ b/app/assets/javascripts/admin/routes/admin-site-settings-index.js.es6
@@ -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);
+ }
+});
diff --git a/app/assets/javascripts/admin/routes/admin-site-settings.js.es6 b/app/assets/javascripts/admin/routes/admin-site-settings.js.es6
new file mode 100644
index 00000000000..ba6e7d8761a
--- /dev/null
+++ b/app/assets/javascripts/admin/routes/admin-site-settings.js.es6
@@ -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);
+ }
+});
diff --git a/app/assets/javascripts/admin/routes/admin_site_settings_route.js b/app/assets/javascripts/admin/routes/admin_site_settings_route.js
deleted file mode 100644
index 7af30081b71..00000000000
--- a/app/assets/javascripts/admin/routes/admin_site_settings_route.js
+++ /dev/null
@@ -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);
- }
-});
diff --git a/app/assets/javascripts/admin/templates/components/setting-validation-message.hbs b/app/assets/javascripts/admin/templates/components/setting-validation-message.hbs
new file mode 100644
index 00000000000..e60ffd471e5
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/components/setting-validation-message.hbs
@@ -0,0 +1,4 @@
+
+ {{fa-icon "times"}}
+ {{message}}
+
diff --git a/app/assets/javascripts/admin/templates/components/site-setting.hbs b/app/assets/javascripts/admin/templates/components/site-setting.hbs
new file mode 100644
index 00000000000..768be98e1cb
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/components/site-setting.hbs
@@ -0,0 +1,16 @@
+
+
{{unbound settingName}}
+
+
+ {{partial partialName}}
+
+{{#if dirty}}
+
+ {{d-button class="ok no-text" action="save" icon="check"}}
+ {{d-button class="cancel no-text" action="cancel" icon="times"}}
+
+{{else}}
+ {{#if setting.overridden}}
+ {{d-button action="resetDefault" icon="undo" label="admin.site_settings.reset"}}
+ {{/if}}
+{{/if}}
diff --git a/app/assets/javascripts/admin/templates/components/url-list.hbs b/app/assets/javascripts/admin/templates/components/url-list.hbs
new file mode 100644
index 00000000000..d313c5b30a8
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/components/url-list.hbs
@@ -0,0 +1,18 @@
+{{#if urls}}
+
+ {{#each url in urls}}
+
+ {{d-button action="removeUrl"
+ actionParam=url
+ icon="times"
+ class="btn-small no-text"}}
+
{{url}}
+
+ {{/each}}
+
+{{/if}}
+
+
+ {{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}}
+
diff --git a/app/assets/javascripts/admin/templates/site-settings-category.hbs b/app/assets/javascripts/admin/templates/site-settings-category.hbs
new file mode 100644
index 00000000000..8cb5aedaa3a
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings-category.hbs
@@ -0,0 +1,10 @@
+{{#if filteredContent}}
+
+ {{#each setting in filteredContent}}
+ {{site-setting setting=setting saveAction="saveSetting"}}
+ {{/each}}
+
+{{else}}
+
+ {{i18n 'admin.site_settings.no_results'}}
+{{/if}}
diff --git a/app/assets/javascripts/admin/templates/site_settings.hbs b/app/assets/javascripts/admin/templates/site-settings.hbs
similarity index 100%
rename from app/assets/javascripts/admin/templates/site_settings.hbs
rename to app/assets/javascripts/admin/templates/site-settings.hbs
diff --git a/app/assets/javascripts/admin/templates/site-settings/bool.hbs b/app/assets/javascripts/admin/templates/site-settings/bool.hbs
new file mode 100644
index 00000000000..bf51ed900d1
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings/bool.hbs
@@ -0,0 +1,4 @@
+
diff --git a/app/assets/javascripts/admin/templates/site-settings/enum.hbs b/app/assets/javascripts/admin/templates/site-settings/enum.hbs
new file mode 100644
index 00000000000..b6676e3c33e
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings/enum.hbs
@@ -0,0 +1,4 @@
+{{combo-box valueAttribute="value" content=setting.validValues value=buffered.value none=setting.allowsNone}}
+{{preview}}
+{{setting-validation-message message=validationMessage}}
+{{unbound setting.description}}
diff --git a/app/assets/javascripts/admin/templates/site-settings/list.hbs b/app/assets/javascripts/admin/templates/site-settings/list.hbs
new file mode 100644
index 00000000000..588d8d3388f
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings/list.hbs
@@ -0,0 +1,3 @@
+{{list-setting settingValue=buffered.value choices=setting.choices settingName=setting.setting}}
+{{setting-validation-message message=validationMessage}}
+{{unbound setting.description}}
diff --git a/app/assets/javascripts/admin/templates/site-settings/string.hbs b/app/assets/javascripts/admin/templates/site-settings/string.hbs
new file mode 100644
index 00000000000..9770efb755f
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings/string.hbs
@@ -0,0 +1,3 @@
+{{text-field value=buffered.value classNames="input-setting-string"}}
+{{setting-validation-message message=validationMessage}}
+{{unbound setting.description}}
diff --git a/app/assets/javascripts/admin/templates/site-settings/url_list.hbs b/app/assets/javascripts/admin/templates/site-settings/url_list.hbs
new file mode 100644
index 00000000000..e3751f3178e
--- /dev/null
+++ b/app/assets/javascripts/admin/templates/site-settings/url_list.hbs
@@ -0,0 +1,3 @@
+{{url-list value=buffered.value}}
+{{setting-validation-message message=validationMessage}}
+{{unbound setting.description}}
diff --git a/app/assets/javascripts/admin/templates/site_settings/setting_bool.hbs b/app/assets/javascripts/admin/templates/site_settings/setting_bool.hbs
deleted file mode 100644
index 84f07ce4cec..00000000000
--- a/app/assets/javascripts/admin/templates/site_settings/setting_bool.hbs
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
{{unbound settingName}}
-
-
-
-
-{{#if dirty}}
-
-
-
-
-{{else}}
- {{#if overridden}}
-
- {{/if}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/templates/site_settings/setting_enum.hbs b/app/assets/javascripts/admin/templates/site_settings/setting_enum.hbs
deleted file mode 100644
index b0f06e5b14e..00000000000
--- a/app/assets/javascripts/admin/templates/site_settings/setting_enum.hbs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
{{unbound settingName}}
-
-
- {{combo-box valueAttribute="value" content=validValues value=value none=allowsNone}}
- {{view.preview}}
-
{{unbound description}}
-
-{{#if dirty}}
-
-
-
-
-{{else}}
- {{#if overridden}}
-
- {{/if}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/templates/site_settings/setting_list.hbs b/app/assets/javascripts/admin/templates/site_settings/setting_list.hbs
deleted file mode 100644
index 2aadfd9845d..00000000000
--- a/app/assets/javascripts/admin/templates/site_settings/setting_list.hbs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
{{unbound settingName}}
-
-
- {{list-setting settingValue=value choices=choices settingName=setting}}
-
{{validationMessage}}
-
{{{unbound description}}}
-
-{{#if dirty}}
-
-
-
-
-{{else}}
- {{#if overridden}}
-
- {{/if}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/templates/site_settings/setting_string.hbs b/app/assets/javascripts/admin/templates/site_settings/setting_string.hbs
deleted file mode 100644
index 52279773b1b..00000000000
--- a/app/assets/javascripts/admin/templates/site_settings/setting_string.hbs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
{{unbound settingName}}
-
-
- {{text-field value=value classNames="input-setting-string"}}
-
{{validationMessage}}
-
{{unbound description}}
-
-{{#if dirty}}
-
-
-
-
-{{else}}
- {{#if overridden}}
-
- {{/if}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/templates/site_settings_category.hbs b/app/assets/javascripts/admin/templates/site_settings_category.hbs
deleted file mode 100644
index 002baae2e98..00000000000
--- a/app/assets/javascripts/admin/templates/site_settings_category.hbs
+++ /dev/null
@@ -1,6 +0,0 @@
-{{#if filteredContent.length}}
- {{collection contentBinding="filteredContent" classNames="form-horizontal settings" itemView="site-setting"}}
-{{else}}
-
- {{i18n 'admin.site_settings.no_results'}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/views/admin_site_settings_category_view.js b/app/assets/javascripts/admin/views/admin_site_settings_category_view.js
deleted file mode 100644
index f6ce4ee82a9..00000000000
--- a/app/assets/javascripts/admin/views/admin_site_settings_category_view.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Discourse.AdminSiteSettingsCategoryView = Discourse.View.extend({
- templateName: 'admin/templates/site_settings_category'
-});
diff --git a/app/assets/javascripts/admin/views/site-setting.js.es6 b/app/assets/javascripts/admin/views/site-setting.js.es6
deleted file mode 100644
index af12ff00b36..00000000000
--- a/app/assets/javascripts/admin/views/site-setting.js.es6
+++ /dev/null
@@ -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("" +
- preview.replace("{{value}}",this.get('content.value')) +
- "
"
- );
- }
- }.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")
-
-});
diff --git a/app/assets/javascripts/discourse/views/combo-box.js.es6 b/app/assets/javascripts/discourse/views/combo-box.js.es6
index 18668367355..7c4bea6c7d2 100644
--- a/app/assets/javascripts/discourse/views/combo-box.js.es6
+++ b/app/assets/javascripts/discourse/views/combo-box.js.es6
@@ -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() {
diff --git a/app/assets/javascripts/main_include_admin.js b/app/assets/javascripts/main_include_admin.js
index dd77d21b007..9a66a6965b5 100644
--- a/app/assets/javascripts/main_include_admin.js
+++ b/app/assets/javascripts/main_include_admin.js
@@ -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
diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss
index eb9b02fd34b..bb0591f5c63 100644
--- a/app/assets/stylesheets/common/admin/admin_base.scss
+++ b/app/assets/stylesheets/common/admin/admin_base.scss
@@ -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%;
+ }
+}
diff --git a/app/controllers/admin/site_settings_controller.rb b/app/controllers/admin/site_settings_controller.rb
index 7ed22e7e2ef..b8170147800 100644
--- a/app/controllers/admin/site_settings_controller.rb
+++ b/app/controllers/admin/site_settings_controller.rb
@@ -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
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index bdb4f0d77f4..db41b8a47b4 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -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'
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 52705befb2c..0986f87bf3a 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -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."
diff --git a/config/site_settings.yml b/config/site_settings.yml
index 7b464a84b80..e0c4778fcb4 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -515,6 +515,10 @@ files:
client: true
default: false
allow_animated_thumbnails: false
+avatars:
+ default_avatars:
+ default: ''
+ type: url_list
trust:
default_trust_level:
diff --git a/lib/site_setting_extension.rb b/lib/site_setting_extension.rb
index fab32a7136a..a3b655e99c9 100644
--- a/lib/site_setting_extension.rb
+++ b/lib/site_setting_extension.rb
@@ -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