diff --git a/nailgun/static/models.js b/nailgun/static/models.js index e3c5f1a024..8a3e5ccb1c 100644 --- a/nailgun/static/models.js +++ b/nailgun/static/models.js @@ -101,19 +101,22 @@ define([ models.cacheMixin = cacheMixin; var restrictionMixin = models.restrictionMixin = { - expandRestrictions: function(restrictions, path) { - path = path || 'restrictions'; + expandRestrictions: function(restrictions, path = 'restrictions') { this.expandedRestrictions = this.expandedRestrictions || {}; this.expandedRestrictions[path] = _.map(restrictions, utils.expandRestriction, this); }, - checkRestrictions: function(models, action, path) { - path = path || 'restrictions'; + checkRestrictions: function(models, action, path = 'restrictions') { var restrictions = (this.expandedRestrictions || {})[path]; - if (action) restrictions = _.where(restrictions, {action: action}); - var satisfiedRestrictions = _.filter(restrictions, function(restriction) { - return new Expression(restriction.condition, models, restriction).evaluate(); - }); - return {result: !!satisfiedRestrictions.length, message: _.compact(_.pluck(satisfiedRestrictions, 'message')).join(' ')}; + if (action) { + restrictions = _.where(restrictions, {action: action}); + } + var satisfiedRestrictions = _.filter(restrictions, + (restriction) => new Expression(restriction.condition, models, restriction).evaluate() + ); + return { + result: !!satisfiedRestrictions.length, + message: _.compact(_.pluck(satisfiedRestrictions, 'message')).join(' ') + }; }, expandLimits: function(limits) { this.expandedLimits = this.expandedLimits || {}; @@ -625,24 +628,61 @@ define([ isNew: function() { return false; }, + isPlugin: function(section) { + return (section.metadata || {}).class == 'plugin'; + }, parse: function(response) { return response[this.root]; }, + mergePluginSettings: function() { + _.each(this.attributes, (section, sectionName) => { + if (this.isPlugin(section)) { + var chosenVersionData = section.metadata.versions.find( + (version) => version.metadata.plugin_id == section.metadata.chosen_id + ); + // merge metadata of a chosen plugin version + _.extend(section.metadata, _.omit(chosenVersionData.metadata, 'plugin_id', 'plugin_version')); + // merge settings of a chosen plugin version + this.attributes[sectionName] = _.extend(_.pick(section, 'metadata'), _.omit(chosenVersionData, 'metadata')); + } + }, this); + }, toJSON: function() { - if (!this.root) return this._super('toJSON', arguments); - var data = {}; - data[this.root] = this._super('toJSON', arguments); - return data; + var settings = this._super('toJSON', arguments); + if (!this.root) return settings; + + // update plugin settings + _.each(settings, (section, sectionName) => { + if (this.isPlugin(section)) { + var chosenVersionData = section.metadata.versions.find( + (version) => version.metadata.plugin_id == section.metadata.chosen_id + ); + section.metadata = _.omit(section.metadata, _.without(_.keys(chosenVersionData.metadata), 'plugin_id', 'plugin_version')); + _.each(section, (setting, settingName) => { + if (settingName != 'metadata') chosenVersionData[settingName].value = setting.value; + }); + settings[sectionName] = _.pick(section, 'metadata'); + } + }); + return {[this.root]: settings}; }, processRestrictions: function() { - _.each(this.attributes, function(group, groupName) { - if (group.metadata) { - this.expandRestrictions(group.metadata.restrictions, groupName + '.metadata'); + _.each(this.attributes, function(section, sectionName) { + if (section.metadata) { + this.expandRestrictions(section.metadata.restrictions, this.makePath(sectionName, 'metadata')); + if (this.isPlugin(section)) { + _.each(section.metadata.versions, (version) => { + this.expandRestrictions(version.metadata.restrictions, this.makePath(sectionName, 'metadata')); + _.each(version, + (setting, settingName) => this.expandRestrictions(setting.restrictions, this.makePath(sectionName, settingName)) + ); + }, this); + } } - _.each(group, function(setting, settingName) { - this.expandRestrictions(setting.restrictions, this.makePath(groupName, settingName)); - _.each(setting.values, function(value) { - this.expandRestrictions(value.restrictions, this.makePath(groupName, settingName, value.data)); + _.each(section, (setting, settingName) => { + this.expandRestrictions(setting.restrictions, this.makePath(sectionName, settingName)); + _.each(setting.values, (value) => { + this.expandRestrictions(value.restrictions, this.makePath(sectionName, settingName, value.data)); }, this); }, this); }, this); @@ -650,14 +690,15 @@ define([ initialize: function() { // FIXME(vkramskikh): this will work only if there won't be // any restrictions added later in the same model - this.once('change', this.processRestrictions, this); + this.once('change', () => { + this.processRestrictions(); + this.mergePluginSettings(); + }, this); }, validate: function(attrs, options) { var errors = {}, models = options ? options.models : {}, - checkRestrictions = _.bind(function(path) { - return this.checkRestrictions(models, null, path); - }, this); + checkRestrictions = (path) => this.checkRestrictions(models, null, path); _.each(attrs, function(group, groupName) { if ((group.metadata || {}).enabled === false || checkRestrictions(this.makePath(groupName, 'metadata')).result) return; _.each(group, function(setting, settingName) { @@ -694,7 +735,7 @@ define([ } return result || _.any(group, function(setting, settingName) { if (this.checkRestrictions(models, null, this.makePath(groupName, settingName)).result) return false; - return !_.isEqual(setting.value, initialAttributes[groupName][settingName].value); + return !_.isEqual(setting.value, (initialAttributes[groupName][settingName] || {}).value); }, this); }, this); }, diff --git a/nailgun/static/styles/main.less b/nailgun/static/styles/main.less index fbd4afe035..37d9137f9c 100644 --- a/nailgun/static/styles/main.less +++ b/nailgun/static/styles/main.less @@ -3770,6 +3770,25 @@ input[type=range] { } } } + .plugin-versions { + margin-bottom: 25px; + .radio-group { + > h4, > div { + display: block; + float: left; + margin: 0; + } + h4 { + position: relative; + top: -2px; + } + .custom-tumbler + span { + position: relative; + top: 1px; + padding-right: 5px; + } + } + } } // Settings tab @@ -3782,6 +3801,11 @@ input[type=range] { padding-top: 0; } } + .plugin-versions { + .radio-group { + margin-left: 10px; + } + } } // Networks tab diff --git a/nailgun/static/translations/core.json b/nailgun/static/translations/core.json index 7607945390..4ad28e6726 100644 --- a/nailgun/static/translations/core.json +++ b/nailgun/static/translations/core.json @@ -575,7 +575,8 @@ "invalid_repo": "Invalid repo format", "invalid_priority": "Invalid priority" } - } + }, + "plugin_versions": "Versions" }, "dashboard_tab": { "delete_environment": "Delete Environment", diff --git a/nailgun/static/views/cluster_page_tabs/network_tab.js b/nailgun/static/views/cluster_page_tabs/network_tab.js index d488c40577..75d614ae6b 100644 --- a/nailgun/static/views/cluster_page_tabs/network_tab.js +++ b/nailgun/static/views/cluster_page_tabs/network_tab.js @@ -601,7 +601,10 @@ function($, _, i18n, Backbone, React, models, dispatcher, utils, dialogs, compon networkConfiguration.get('networking_parameters').set(_.cloneDeep(this.state.initialConfiguration.networking_parameters)); }, loadInitialSettings: function() { - this.props.cluster.get('settings').set(_.cloneDeep(this.state.initialSettingsAttributes)).isValid({models: this.state.configModels}); + var settings = this.props.cluster.get('settings'); + settings.set(_.cloneDeep(this.state.initialSettingsAttributes), {silent: true, validate: false}); + settings.mergePluginSettings(); + settings.isValid({models: this.state.configModels}); }, updateInitialConfiguration: function() { this.setState({initialConfiguration: _.cloneDeep(this.props.cluster.get('networkConfiguration').toJSON())}); @@ -1500,7 +1503,7 @@ function($, _, i18n, Backbone, React, models, dispatcher, utils, dialogs, compon .filter( (sectionName) => { var section = settings.get(sectionName); - return (section.metadata.group == 'network' || !section.metadata.group && _.any(section, {group: 'network'})) && + return (section.metadata.group == 'network' || _.any(section, {group: 'network'})) && !this.checkRestrictions('hide', settings.makePath(sectionName, 'metadata')).result; } ) @@ -1518,7 +1521,7 @@ function($, _, i18n, Backbone, React, models, dispatcher, utils, dialogs, compon !this.checkRestrictions('hide', settings.makePath(sectionName, settingName)).result ) return settingName; })); - if (_.isEmpty(settingsToDisplay)) return null; + if (_.isEmpty(settingsToDisplay) && !settings.isPlugin(section)) return null; return