From 84b84a9d7ca52373756fadd45a27cb12082b8ccb Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 2 Mar 2015 12:12:19 -0500 Subject: [PATCH] Support for `url_list` site setting. --- .../admin/components/site-setting.js.es6 | 91 ++++++++++++ .../admin/components/url-list.js.es6 | 32 +++++ .../admin-site-settings-category.js.es6 | 38 +---- .../controllers/admin-site-settings.js.es6 | 18 +-- .../admin/models/site-setting.js.es6 | 54 +++++++ .../javascripts/admin/models/site_setting.js | 136 ------------------ ...js => admin-site-settings-category.js.es6} | 14 +- .../routes/admin-site-settings-index.js.es6 | 9 ++ .../admin/routes/admin-site-settings.js.es6 | 11 ++ .../admin/routes/admin_site_settings_route.js | 27 ---- .../components/setting-validation-message.hbs | 4 + .../templates/components/site-setting.hbs | 16 +++ .../admin/templates/components/url-list.hbs | 18 +++ .../templates/site-settings-category.hbs | 10 ++ .../{site_settings.hbs => site-settings.hbs} | 0 .../admin/templates/site-settings/bool.hbs | 4 + .../admin/templates/site-settings/enum.hbs | 4 + .../admin/templates/site-settings/list.hbs | 3 + .../admin/templates/site-settings/string.hbs | 3 + .../templates/site-settings/url_list.hbs | 3 + .../templates/site_settings/setting_bool.hbs | 19 --- .../templates/site_settings/setting_enum.hbs | 18 --- .../templates/site_settings/setting_list.hbs | 18 --- .../site_settings/setting_string.hbs | 18 --- .../templates/site_settings_category.hbs | 6 - .../admin_site_settings_category_view.js | 3 - .../admin/views/site-setting.js.es6 | 45 ------ .../discourse/views/combo-box.js.es6 | 5 +- app/assets/javascripts/main_include_admin.js | 1 + .../stylesheets/common/admin/admin_base.scss | 31 +++- .../admin/site_settings_controller.rb | 4 +- config/locales/client.en.yml | 1 + config/locales/server.en.yml | 1 + config/site_settings.yml | 4 + lib/site_setting_extension.rb | 31 ++-- 35 files changed, 327 insertions(+), 373 deletions(-) create mode 100644 app/assets/javascripts/admin/components/site-setting.js.es6 create mode 100644 app/assets/javascripts/admin/components/url-list.js.es6 create mode 100644 app/assets/javascripts/admin/models/site-setting.js.es6 delete mode 100644 app/assets/javascripts/admin/models/site_setting.js rename app/assets/javascripts/admin/routes/{admin_site_settings_category_route.js => admin-site-settings-category.js.es6} (54%) create mode 100644 app/assets/javascripts/admin/routes/admin-site-settings-index.js.es6 create mode 100644 app/assets/javascripts/admin/routes/admin-site-settings.js.es6 delete mode 100644 app/assets/javascripts/admin/routes/admin_site_settings_route.js create mode 100644 app/assets/javascripts/admin/templates/components/setting-validation-message.hbs create mode 100644 app/assets/javascripts/admin/templates/components/site-setting.hbs create mode 100644 app/assets/javascripts/admin/templates/components/url-list.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings-category.hbs rename app/assets/javascripts/admin/templates/{site_settings.hbs => site-settings.hbs} (100%) create mode 100644 app/assets/javascripts/admin/templates/site-settings/bool.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings/enum.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings/list.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings/string.hbs create mode 100644 app/assets/javascripts/admin/templates/site-settings/url_list.hbs delete mode 100644 app/assets/javascripts/admin/templates/site_settings/setting_bool.hbs delete mode 100644 app/assets/javascripts/admin/templates/site_settings/setting_enum.hbs delete mode 100644 app/assets/javascripts/admin/templates/site_settings/setting_list.hbs delete mode 100644 app/assets/javascripts/admin/templates/site_settings/setting_string.hbs delete mode 100644 app/assets/javascripts/admin/templates/site_settings_category.hbs delete mode 100644 app/assets/javascripts/admin/views/admin_site_settings_category_view.js delete mode 100644 app/assets/javascripts/admin/views/site-setting.js.es6 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 000000000..4703950d7 --- /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 000000000..4562c4b20 --- /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 4f5fed453..37bc9b376 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 a518c9167..95fdff940 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 000000000..1d769369c --- /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 0c32fcbab..000000000 --- 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 b07967e97..cf4caf532 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 000000000..727615c46 --- /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 000000000..ba6e7d876 --- /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 7af30081b..000000000 --- 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 000000000..e60ffd471 --- /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 000000000..768be98e1 --- /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 000000000..d313c5b30 --- /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 000000000..8cb5aedaa --- /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 000000000..bf51ed900 --- /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 000000000..b6676e3c3 --- /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 000000000..588d8d338 --- /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 000000000..9770efb75 --- /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 000000000..e3751f317 --- /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 84f07ce4c..000000000 --- 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 b0f06e5b1..000000000 --- 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 2aadfd984..000000000 --- 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 52279773b..000000000 --- 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 002baae2e..000000000 --- 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 f6ce4ee82..000000000 --- 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 af12ff00b..000000000 --- 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 186683673..7c4bea6c7 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 dd77d21b0..9a66a6965 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 eb9b02fd3..bb0591f5c 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 7ed22e7e2..b81701478 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 bdb4f0d77..db41b8a47 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 52705befb..0986f87bf 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 7b464a84b..e0c4778fc 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 fab32a713..a3b655e99 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