Repository: ambari Updated Branches: refs/heads/trunk 8e85227f7 -> 2fb219fb3
AMBARI-14548 Can't save configs on service config page when recommendation popup shows up. (ababiichuk) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2fb219fb Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2fb219fb Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2fb219fb Branch: refs/heads/trunk Commit: 2fb219fb39d54f8e135e8b65833d3b56d7f7ea45 Parents: 8e85227 Author: ababiichuk <ababiic...@hortonworks.com> Authored: Tue Jan 5 13:20:30 2016 +0200 Committer: ababiichuk <ababiic...@hortonworks.com> Committed: Tue Jan 5 13:20:30 2016 +0200 ---------------------------------------------------------------------- .../controllers/main/service/info/configs.js | 4 +- .../app/controllers/wizard/step7_controller.js | 2 +- .../common/configs/config_recommendations.js | 335 ++++++++++--------- .../mixins/common/configs/enhanced_configs.js | 205 +++++------- ambari-web/app/mixins/common/serverValidator.js | 16 - .../modal_popups/dependent_configs_list.hbs | 26 +- ambari-web/app/utils/config.js | 23 ++ ambari-web/app/views/common/controls_view.js | 2 +- .../dependent_configs_list_popup.js | 48 ++- .../test/controllers/wizard/step7_test.js | 4 +- .../configs/widgets/config_widget_view_test.js | 4 +- .../dependent_configs_list_popup_test.js | 2 +- 12 files changed, 334 insertions(+), 337 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/controllers/main/service/info/configs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js index 85b4f60..97c8b4d 100644 --- a/ambari-web/app/controllers/main/service/info/configs.js +++ b/ambari-web/app/controllers/main/service/info/configs.js @@ -264,6 +264,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ConfigsLoader, A this.get('requestsInProgress').clear(); this.clearLoadInfo(); this.clearSaveInfo(); + this.clearRecommendationsInfo(); this.clearAllRecommendations(); this.setProperties({ saveInProgress: false, @@ -474,7 +475,6 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ConfigsLoader, A * @method onLoadOverrides */ onLoadOverrides: function (allConfigs) { - var self = this; this.get('servicesToLoad').forEach(function(serviceName) { var configGroups = serviceName == this.get('content.serviceName') ? this.get('configGroups') : this.get('dependentConfigGroups').filterProperty('serviceName', serviceName); var configTypes = App.StackService.find(serviceName).get('configTypeList'); @@ -494,7 +494,7 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ConfigsLoader, A } else { App.config.removeRangerConfigs(this.get('stepConfigs')); } - this.getRecommendationsForDependencies(null, true, function () {self._onLoadComplete();}); + this.getRecommendationsForDependencies(null, this._onLoadComplete.bind(this)); App.loadTimer.finish('Service Configs Page'); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/controllers/wizard/step7_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js index d10f348..a72c6d7 100644 --- a/ambari-web/app/controllers/wizard/step7_controller.js +++ b/ambari-web/app/controllers/wizard/step7_controller.js @@ -1535,7 +1535,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E showOozieDerbyWarningPopup: function(callback) { var self = this; if (this.get('selectedServiceNames').contains('OOZIE')) { - var databaseType = Em.getWithDefault(this.findConfigProperty('oozie_database', 'oozie-env.xml') || {}, 'value', ''); + var databaseType = Em.getWithDefault(App.config.findConfigProperty(this.get('stepConfigs'), 'oozie_database', 'oozie-env.xml') || {}, 'value', ''); if (databaseType == Em.I18n.t('installer.step7.oozie.database.new')) { return App.ModalPopup.show({ header: Em.I18n.t('common.warning'), http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/mixins/common/configs/config_recommendations.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/configs/config_recommendations.js b/ambari-web/app/mixins/common/configs/config_recommendations.js index 583e86d..7bf75fa 100644 --- a/ambari-web/app/mixins/common/configs/config_recommendations.js +++ b/ambari-web/app/mixins/common/configs/config_recommendations.js @@ -37,165 +37,182 @@ var App = require('app'); App.ConfigRecommendations = Em.Mixin.create({ - /** - * List of recommendations that was applied to configs - * - * @type {recommendation[]} - */ - recommendations: [], - - /** - * Update recommendation property if exists - * otherwise add new - * - * @param {string} name - * @param {string} fileName - * @param {string} configGroupName - * @param {string} recommendedValue - * @param {string} initialValue - * @param {Object[]}parentProperties - * @returns {recommendation} - */ - applyRecommendation: function(name, fileName, configGroupName, recommendedValue, initialValue, parentProperties) { - var parentPropertiesNames = parentProperties ? parentProperties.map(function(p) { - return App.config.configId(p.name, p.type); - }) : []; - var updated = this.updateRecommendation(name, fileName, configGroupName, recommendedValue, parentPropertiesNames); - if (!updated) - var added = this.addRecommendation(name, fileName, configGroupName, recommendedValue, initialValue, parentPropertiesNames); - return updated || added; - }, - - /** - * Add new recommendation - * - * @param {string} name - * @param {string} fileName - * @param {string} configGroupName - * @param {string} recommendedValue - * @param {string} initialValue - * @param {string[]} parentPropertiesNames - * @returns {recommendation} - */ - addRecommendation: function(name, fileName, configGroupName, recommendedValue, initialValue, parentPropertiesNames) { - Em.assert('name and fileName should be defined', name && fileName); - var site = App.config.getConfigTagFromFileName(fileName); - var service = App.config.get('serviceByConfigTypeMap')[site]; - var recommendation = { - saveRecommended: true, - saveRecommendedDefault: true, - propertyFileName: site, - propertyName: name, - - isDeleted: Em.isNone(recommendedValue), - notDefined: Em.isNone(initialValue), - - configGroup: configGroupName || "Default", - initialValue: initialValue, - parentConfigs: parentPropertiesNames || [], - serviceName: service.get('serviceName'), - allowChangeGroup: false,//TODO groupName!= "Default" && (service.get('serviceName') != this.get('selectedService.serviceName')) - //TODO&& (App.ServiceConfigGroup.find().filterProperty('serviceName', service.get('serviceName')).length > 1), //TODO - serviceDisplayName: service.get('displayName'), - recommendedValue: recommendedValue - }; - this.get('recommendations').pushObject(recommendation); - return recommendation; - }, - - /** - * Remove recommendation - * based on unique identifiers - * - * @param {string} name - * @param {string} fileName - * @param {string} configGroupName - */ - removeRecommendation: function(name, fileName, configGroupName) { - this.removeRecommendationObject(this.getRecommendation(name, fileName, configGroupName)); - }, - - /** - * Remove recommended Object - * - * @param {recommendation} recommendation - */ - removeRecommendationObject: function(recommendation) { - if (recommendation) - this.get('recommendations').removeObject(recommendation); - }, - - /** - * Update recommended object - * - * @param name - * @param fileName - * @param configGroupName - * @param recommendedValue - * @param parentPropertiesNames - * @returns {*|recommendation|null} - */ - updateRecommendation: function(name, fileName, configGroupName, recommendedValue, parentPropertiesNames) { - var recommendation = this.getRecommendation(name, fileName, configGroupName); - if (recommendation) { - Em.set(recommendation, 'recommendedValue', recommendedValue); - if (parentPropertiesNames && parentPropertiesNames.length) { - var mergedProperties = parentPropertiesNames.concat(Em.get(recommendation, 'parentPropertiesNames')); - Em.set(recommendation, 'parentPropertiesNames', mergedProperties); - } - } - return recommendation; - }, - - /** - * Get single recommendation - * - * @param name - * @param fileName - * @param configGroupName - * @returns {recommendation|null} - */ - getRecommendation: function(name, fileName, configGroupName) { - Em.assert('name and fileName should be defined', name && fileName); - return this.get('recommendations').find(function (dcv) { - return dcv.propertyName === name - && dcv.propertyFileName === App.config.getConfigTagFromFileName(fileName) - && dcv.configGroup === (configGroupName || "Default"); - }); - }, - - /** - * Clear recommendations that are - * same as initial value - * - * @method cleanUpRecommendations - */ - cleanUpRecommendations: function() { - var cleanDependentList = this.get('recommendations').filter(function(d) { - return !((Em.isNone(d.initialValue) && Em.isNone(d.recommendedValue)) || d.initialValue == d.recommendedValue); - }, this); - this.set('recommendations', cleanDependentList); - }, - - /** - * Remove all recommendations - * - * @method clearAllRecommendations - */ - clearAllRecommendations: function() { - this.set('recommendations', []); - }, - - /** - * Clear values for dependent configs for given services - * - * @method clearRecommendationsByServiceName - */ - clearRecommendationsByServiceName: function(serviceNames) { - var filteredRecommendations = this.get('recommendations').reject(function(c) { - return serviceNames.contains(c.serviceName); - }, this); - this.set('recommendations', filteredRecommendations); + /** + * List of recommendations that was applied to configs + * + * @type {recommendation[]} + */ + recommendations: [], + + /** + * Update recommendation property if exists + * otherwise add new + * + * @param {string} name + * @param {string} fileName + * @param {string} configGroupName + * @param {string} recommendedValue + * @param {string} initialValue + * @param {Object[]}parentProperties + * @returns {recommendation} + */ + applyRecommendation: function (name, fileName, configGroupName, recommendedValue, initialValue, parentProperties) { + var parentPropertiesNames = parentProperties ? parentProperties.map(function (p) { + return App.config.configId(p.name, p.type); + }) : []; + var updated = this.updateRecommendation(name, fileName, configGroupName, recommendedValue, parentPropertiesNames); + if (!updated) + var added = this.addRecommendation(name, fileName, configGroupName, recommendedValue, initialValue, parentPropertiesNames); + return updated || added; + }, + + /** + * Add new recommendation + * + * @param {string} name + * @param {string} fileName + * @param {string} configGroupName + * @param {string} recommendedValue + * @param {string} initialValue + * @param {string[]} parentPropertiesNames + * @returns {recommendation} + */ + addRecommendation: function (name, fileName, configGroupName, recommendedValue, initialValue, parentPropertiesNames) { + Em.assert('name and fileName should be defined', name && fileName); + var site = App.config.getConfigTagFromFileName(fileName); + var service = App.config.get('serviceByConfigTypeMap')[site]; + var recommendation = { + saveRecommended: true, + saveRecommendedDefault: true, + propertyFileName: site, + propertyName: name, + + isDeleted: Em.isNone(recommendedValue), + notDefined: Em.isNone(initialValue), + + configGroup: configGroupName || "Default", + initialValue: initialValue, + parentConfigs: parentPropertiesNames || [], + serviceName: service.get('serviceName'), + allowChangeGroup: false,//TODO groupName!= "Default" && (service.get('serviceName') != this.get('selectedService.serviceName')) + //TODO&& (App.ServiceConfigGroup.find().filterProperty('serviceName', service.get('serviceName')).length > 1), //TODO + serviceDisplayName: service.get('displayName'), + recommendedValue: recommendedValue + }; + this.get('recommendations').pushObject(recommendation); + return recommendation; + }, + + /** + * Remove recommendation + * based on unique identifiers + * + * @param {string} name + * @param {string} fileName + * @param {string} configGroupName + */ + removeRecommendation: function (name, fileName, configGroupName) { + this.removeRecommendationObject(this.getRecommendation(name, fileName, configGroupName)); + }, + + /** + * Remove recommended Object + * + * @param {recommendation} recommendation + */ + removeRecommendationObject: function (recommendation) { + if (recommendation) + this.get('recommendations').removeObject(recommendation); + }, + + /** + * Update recommended object + * + * @param name + * @param fileName + * @param configGroupName + * @param recommendedValue + * @param parentPropertiesNames + * @returns {*|recommendation|null} + */ + updateRecommendation: function (name, fileName, configGroupName, recommendedValue, parentPropertiesNames) { + var recommendation = this.getRecommendation(name, fileName, configGroupName); + if (recommendation) { + Em.set(recommendation, 'recommendedValue', recommendedValue); + if (parentPropertiesNames && parentPropertiesNames.length) { + var mergedProperties = parentPropertiesNames.concat(Em.get(recommendation, 'parentPropertiesNames')); + Em.set(recommendation, 'parentPropertiesNames', mergedProperties); + } } + return recommendation; + }, + + /** + * + * @param recommendation + * @param saveRecommendation + */ + saveRecommendation: function (recommendation, saveRecommendation) { + Em.assert('recommendation should be defined object', recommendation && typeof recommendation === 'object'); + if (recommendation.saveRecommended !== saveRecommendation) { + Em.setProperties(recommendation, { + 'saveRecommended': !!saveRecommendation, + 'saveRecommendedDefault': !!saveRecommendation + }); + return true; + } + return false; + }, + + /** + * Get single recommendation + * + * @param name + * @param fileName + * @param configGroupName + * @returns {recommendation|null} + */ + getRecommendation: function (name, fileName, configGroupName) { + Em.assert('name and fileName should be defined', name && fileName); + return this.get('recommendations').find(function (dcv) { + return dcv.propertyName === name + && dcv.propertyFileName === App.config.getConfigTagFromFileName(fileName) + && dcv.configGroup === (configGroupName || "Default"); + }); + }, + + /** + * Clear recommendations that are + * same as initial value + * + * @method cleanUpRecommendations + */ + cleanUpRecommendations: function () { + var cleanDependentList = this.get('recommendations').filter(function (d) { + return !((Em.isNone(d.initialValue) && Em.isNone(d.recommendedValue)) || d.initialValue == d.recommendedValue); + }, this); + this.set('recommendations', cleanDependentList); + }, + + /** + * Remove all recommendations + * + * @method clearAllRecommendations + */ + clearAllRecommendations: function () { + this.set('recommendations', []); + }, + + /** + * Clear values for dependent configs for given services + * + * @method clearRecommendationsByServiceName + */ + clearRecommendationsByServiceName: function (serviceNames) { + var filteredRecommendations = this.get('recommendations').reject(function (c) { + return serviceNames.contains(c.serviceName); + }, this); + this.set('recommendations', filteredRecommendations); + } }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/mixins/common/configs/enhanced_configs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/configs/enhanced_configs.js b/ambari-web/app/mixins/common/configs/enhanced_configs.js index 0d3f20a..ee7689e 100644 --- a/ambari-web/app/mixins/common/configs/enhanced_configs.js +++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js @@ -132,31 +132,18 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP } }, - /** - * disable saving recommended value for current config - * @param config - * @param {boolean} saveRecommended - * @method removeCurrentFromDependentList - */ - removeCurrentFromDependentList: function (config, saveRecommended) { - var current = this.getRecommendation(config.get('name'), config.get('filename'), config.get('group.name')); - if (current) { - Em.setProperties(current, { - 'saveRecommended': !!saveRecommended, - 'saveRecommendedDefault': !!saveRecommended - }); - } + clearRecommendationsInfo: function() { + this.set('recommendationsConfigs', null); }, /** * sends request to get values for dependent configs * @param {{type: string, name: string}[]} changedConfigs - list of changed configs to track recommendations - * @param {Boolean} initial * @param {Function} onComplete * @returns {$.ajax|null} */ - getRecommendationsForDependencies: function(changedConfigs, initial, onComplete) { - if (Em.isArray(changedConfigs) && changedConfigs.length > 0 || initial) { + getRecommendationsForDependencies: function(changedConfigs, onComplete) { + if ((Em.isArray(changedConfigs) && changedConfigs.length > 0) || Em.isNone(this.get('recommendationsConfigs'))) { var configGroup = this.get('selectedConfigGroup'); var recommendations = this.get('hostGroups'); delete recommendations.config_groups; @@ -168,7 +155,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP }; var clearConfigsOnAddService = configGroup.get('isDefault') && this.isConfigHasInitialState(); - if (clearConfigsOnAddService) { + if (clearConfigsOnAddService && !Em.isNone(this.get('initialConfigValues'))) { recommendations.blueprint.configurations = this.get('initialConfigValues'); } else { recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(this.get('services'), this.get('stepConfigs')); @@ -182,24 +169,28 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP recommendations.config_groups = [configGroups]; } dataToSend.recommendations = recommendations; + var self = this; return App.ajax.send({ name: 'config.recommendations', sender: this, data: { stackVersionUrl: App.get('stackVersionURL'), dataToSend: dataToSend, - notDefaultGroup: configGroup && !configGroup.get('isDefault'), clearConfigsOnAddService: clearConfigsOnAddService }, - success: 'dependenciesSuccess', - error: 'dependenciesError', + success: 'loadRecommendationsSuccess', + error: 'loadRecommendationsError', callback: function() { + self.set('recommendationTimeStamp', (new Date).getTime()); if (onComplete) { onComplete() } } }); } else { + if (onComplete) { + onComplete() + } return null; } }, @@ -277,14 +268,54 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP * @param params * @method dependenciesSuccess */ - dependenciesSuccess: function (data, opt, params) { - this._saveRecommendedValues(data, params.dataToSend.changed_configurations, params.notDefaultGroup); + loadRecommendationsSuccess: function (data, opt, params) { + this._saveRecommendedValues(data, params.dataToSend.changed_configurations); this.set("recommendationsConfigs", Em.get(data.resources[0] , "recommendations.blueprint.configurations")); if (params.clearConfigsOnAddService) { this.clearConfigValues(); this.clearAllRecommendations(); } - this.set('recommendationTimeStamp', (new Date).getTime()); + }, + + loadRecommendationsError: Em.K, + + changedDependentGroup: function() { + var dependentServices = this.get('stepConfigs').filter(function(stepConfig) { + return this.get('selectedService.dependentServiceNames').contains(stepConfig.get('serviceName')); + }, this); + App.showSelectGroupsPopup(this.get('selectedService.serviceName'), + this.get('selectedService.configGroups').findProperty('name', this.get('selectedConfigGroup.name')), + dependentServices, this.get('recommendations')) + }, + + /** + * saves values from response for dependent config properties to <code>recommendations<code> + * @param data + * @param [changedConfigs=null] + * @method saveRecommendedValues + * @private + */ + _saveRecommendedValues: function(data, changedConfigs) { + Em.assert('invalid data - `data.resources[0].recommendations.blueprint.configurations` not defined ', data && data.resources[0] && Em.get(data.resources[0], 'recommendations.blueprint.configurations')); + var recommendations = data.resources[0].recommendations; + if (recommendations['config-groups'] && this.get('selectedConfigGroup') && !this.get('selectedConfigGroup.isDefault')) { + var configFroGroup = recommendations['config-groups'][0]; + this.get('stepConfigs').forEach(function(stepConfig) { + var configGroup = this.getGroupForService(stepConfig.get('serviceName')); + if (configGroup) { + this.updateOverridesByRecommendations(configFroGroup.configurations, stepConfig.get('configs'), changedConfigs, configGroup); + this.updateOverridesByRecommendations(configFroGroup.dependent_configurations, stepConfig.get('configs'), changedConfigs, configGroup); + this.toggleProperty('forceUpdateBoundaries'); + } + }, this); + } else { + var configObject = recommendations.blueprint.configurations; + this.get('stepConfigs').forEach(function(stepConfig) { + this.updateConfigsByRecommendations(configObject, stepConfig.get('configs'), changedConfigs); + }, this); + this.addByRecommendations(configObject, changedConfigs); + } + this.cleanUpRecommendations(); }, /** @@ -292,16 +323,34 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP * @method showChangedDependentConfigs */ showChangedDependentConfigs: function(event, callback, secondary) { - if (this.get('recommendations.length') > 0) { - App.showDependentConfigsPopup(this.get('changedProperties'), this.onSaveRecommendedPopup.bind(this), secondary); + var self = this; + var recommendations = event ? this.get('changedProperties') : this.get('recommendations'); + if (recommendations.length > 0) { + App.showDependentConfigsPopup(recommendations, function() { + self.onSaveRecommendedPopup(recommendations); + if (callback) callback(); + }, secondary); } else { - if (callback) { - callback(); - } + if (callback) callback(); } }, /** + * update configs when toggle checkbox on dependent configs popup + */ + onSaveRecommendedPopup: function(recommendations) { + var propertiesToUpdate = recommendations.filter(function(c) { + return Em.get(c, 'saveRecommendedDefault') != Em.get(c, 'saveRecommended'); + }), + propertiesToUndo = propertiesToUpdate.filterProperty('saveRecommended', false), + propertiesToRedo = propertiesToUpdate.filterProperty('saveRecommended', true); + + this.undoRedoRecommended(propertiesToUndo, false); + this.undoRedoRecommended(propertiesToRedo, true); + this.set('recommendationTimeStamp', (new Date).getTime()); + }, + + /** * run through config properties list (form dependent popup) * and set value to default (undo) or recommended (redo) * this happens when toggle checkbox in popup @@ -341,92 +390,22 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP }, /** - * update configs when toggle checkbox on dependent configs popup - * @param propertiesToUndo - * @param propertiesToRedo - */ - onSaveRecommendedPopup: function(propertiesToUndo, propertiesToRedo) { - this.undoRedoRecommended(propertiesToUndo, false); - this.undoRedoRecommended(propertiesToRedo, true); - this.set('recommendationTimeStamp', (new Date).getTime()); - }, - - changedDependentGroup: function() { - var dependentServices = this.get('stepConfigs').filter(function(stepConfig) { - return this.get('selectedService.dependentServiceNames').contains(stepConfig.get('serviceName')); - }, this); - App.showSelectGroupsPopup(this.get('selectedService.serviceName'), - this.get('selectedService.configGroups').findProperty('name', this.get('selectedConfigGroup.name')), - dependentServices, this.get('recommendations')) - }, - - /** - * - * @param jqXHR - * @param ajaxOptions - * @param error - * @param opt - */ - dependenciesError: function(jqXHR, ajaxOptions, error, opt) { - this.set('recommendationTimeStamp', (new Date).getTime()); - // We do not want to show user dialogs of failed recommendations - }, - - /** - * saves values from response for dependent config properties to <code>recommendations<code> - * @param data - * @param [changedConfigs=null] - * @param notDefaultGroup - * @method saveRecommendedValues - * @private - */ - _saveRecommendedValues: function(data, changedConfigs, notDefaultGroup) { - Em.assert('invalid data - `data.resources[0].recommendations.blueprint.configurations` not defined ', data && data.resources[0] && Em.get(data.resources[0], 'recommendations.blueprint.configurations')); - var configObject = data.resources[0].recommendations.blueprint.configurations; - if (!notDefaultGroup) { - this.get('stepConfigs').forEach(function(stepConfig) { - this.updateConfigsByRecommendations(configObject, stepConfig.get('configs'), changedConfigs); - }, this); - this.addByRecommendations(configObject, changedConfigs); - } else if (data.resources[0].recommendations['config-groups']) { - var configFroGroup = data.resources[0].recommendations['config-groups'][0]; - this.get('stepConfigs').forEach(function(stepConfig) { - var configGroup = this.getGroupForService(stepConfig.get('serviceName')); - if (configGroup) { - this.updateOverridesByRecommendations(configFroGroup.configurations, stepConfig.get('configs'), changedConfigs, configGroup); - this.updateOverridesByRecommendations(configFroGroup.dependent_configurations, stepConfig.get('configs'), changedConfigs, configGroup); - this.toggleProperty('forceUpdateBoundaries'); - } - }, this); - } - this.cleanUpRecommendations(); - }, - - installedServices: function () { - return App.StackService.find().toArray().toMapByCallback('serviceName', function (item) { - return Em.get(item, 'isInstalled'); - }); - }.property(), - - /** - * Helper method to get property from the <code>stepConfigs</code> - * - * @param {String} name - config property name - * @param {String} fileName - config property filename - * @return {App.ServiceConfigProperty|Boolean} - App.ServiceConfigProperty instance or <code>false</code> when property not found + * disable saving recommended value for current config + * @param config + * @param {boolean} saveRecommended + * @method removeCurrentFromDependentList */ - findConfigProperty: function(name, fileName) { - if (!name && !fileName) return false; - if (this.get('stepConfigs') && this.get('stepConfigs.length')) { - return this.get('stepConfigs').mapProperty('configs').filter(function(item) { - return item.length; - }).reduce(function(p, c) { - if (p) { - return p.concat(c); + removeCurrentFromDependentList: function (config, saveRecommended) { + var recommendation = this.getRecommendation(config.get('name'), config.get('filename'), config.get('group.name')); + if (recommendation) { + try { + if (this.saveRecommendation(recommendation)) { + this.undoRedoRecommended([recommendation], saveRecommended); + this.set('recommendationTimeStamp', (new Date).getTime()); } - }).filterProperty('filename', fileName).findProperty('name', name); + } catch(e) { + console.warn(e.message); + } } - return false; } - }); http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/mixins/common/serverValidator.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/serverValidator.js b/ambari-web/app/mixins/common/serverValidator.js index 40dd054..3c7f3af 100644 --- a/ambari-web/app/mixins/common/serverValidator.js +++ b/ambari-web/app/mixins/common/serverValidator.js @@ -167,22 +167,6 @@ App.ServerValidatorMixin = Em.Mixin.create({ }); }, - /** - * @method loadRecommendationsSuccess - * success callback after loading recommendations - * (used only during install) - * @param data - */ - loadRecommendationsSuccess: function(data) { - this._saveRecommendedValues(data, null, false); - this.set("recommendationsConfigs", Em.get(data.resources[0] , "recommendations.blueprint.configurations")); - this.set('recommendationTimeStamp', (new Date).getTime()); - }, - - loadRecommendationsError: function(jqXHR, ajaxOptions, error, opt) { - - }, - serverSideValidation: function () { var deferred = $.Deferred(); this.set('configValidationFailed', false); http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs b/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs index cef7be2..fb3cbc5 100644 --- a/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs +++ b/ambari-web/app/templates/common/modal_popups/dependent_configs_list.hbs @@ -33,30 +33,30 @@ </tr> </thead> <tbody> - {{#each config in view.parentView.configs}} + {{#each recommendation in view.parentView.recommendations}} <tr> - <td class="check-box-col">{{view Em.Checkbox checkedBinding="config.saveRecommended"}}</td> - <td class="config-dependency-name">{{config.propertyName}}</td> - <td class="config-dependency-service">{{config.serviceDisplayName}}</td> + <td class="check-box-col">{{view Em.Checkbox checkedBinding="recommendation.saveRecommended"}}</td> + <td class="config-dependency-name">{{recommendation.propertyName}}</td> + <td class="config-dependency-service">{{recommendation.serviceDisplayName}}</td> <td class="config-dependency-group"> - <span {{bindAttr class="config.allowChangeGroup::not-active-link"}} ><a href="javascript:void(null);" class="black" - {{action showSelectGroupPopup config.serviceName target="App.router.mainServiceInfoConfigsController"}}> - {{config.configGroup}} + <span {{bindAttr class="recommendation.allowChangeGroup::not-active-link"}} ><a href="javascript:void(null);" class="black" + {{action showSelectGroupPopup recommendation.serviceName target="App.router.mainServiceInfoConfigsController"}}> + {{recommendation.configGroup}} </a></span> </td> - <td class="config-dependency-filename">{{config.propertyFileName}}</td> + <td class="config-dependency-filename">{{recommendation.propertyFileName}}</td> <td class="config-dependency-value"> - {{#if config.notDefined}} + {{#if recommendation.notDefined}} <i>{{t popup.dependent.configs.table.not.defined}}</i> {{else}} - {{config.initialValue}} + {{recommendation.initialValue}} {{/if}} </td> <td class="config-dependency-recommended-value"> - {{#if config.isDeleted}} - <i>{{t common.removed}}</i> + {{#if recommendation.isDeleted}} + <i>{{t recommendation.removed}}</i> {{else}} - {{config.recommendedValue}} + {{recommendation.recommendedValue}} {{/if}} </td> </tr> http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index a533994..263baa2 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -999,6 +999,29 @@ App.config = Em.Object.create({ } }, + + /** + * Helper method to get property from the <code>stepConfigs</code> + * + * @param {String} name - config property name + * @param {String} fileName - config property filename + * @param {Object[]} stepConfigs + * @return {App.ServiceConfigProperty|Boolean} - App.ServiceConfigProperty instance or <code>false</code> when property not found + */ + findConfigProperty: function(stepConfigs, name, fileName) { + if (!name && !fileName) return false; + if (stepConfigs && stepConfigs.length) { + return stepConfigs.mapProperty('configs').filter(function(item) { + return item.length; + }).reduce(function(p, c) { + if (p) { + return p.concat(c); + } + }).filterProperty('filename', fileName).findProperty('name', name); + } + return false; + }, + /** * Update config property value based on its current value and list of zookeeper server hosts. * Used to prevent sort order issues. http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/views/common/controls_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/controls_view.js b/ambari-web/app/views/common/controls_view.js index 367a7ee..a4b07d0 100644 --- a/ambari-web/app/views/common/controls_view.js +++ b/ambari-web/app/views/common/controls_view.js @@ -121,7 +121,7 @@ App.SupportsDependentConfigs = Ember.Mixin.create({ item.parentConfigs.removeObject(parentConfig.get('name')); } else { // reset property value - var property = controller.findConfigProperty(item.propertyName, App.config.getOriginalFileName(item.fileName)); + var property = App.config.findConfigProperty(controller.get('stepConfigs'), item.propertyName, App.config.getOriginalFileName(item.fileName)); if (property) { property.set('value', property.get('savedValue') || property.get('initialValue')); } http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js b/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js index 334ca75..bcd8b86 100644 --- a/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js +++ b/ambari-web/app/views/common/modal_popups/dependent_configs_list_popup.js @@ -20,18 +20,18 @@ var App = require('app'); /** * Show confirmation popup - * @param {[Object]} configs + * @param {[Object]} recommendations * @param {function} [primary=null] * @param {function} [secondary=null] * we use this parameter to defer saving configs before we make some decisions. * @return {App.ModalPopup} */ -App.showDependentConfigsPopup = function (configs, primary, secondary) { +App.showDependentConfigsPopup = function (recommendations, primary, secondary) { return App.ModalPopup.show({ encodeBody: false, header: Em.I18n.t('popup.dependent.configs.header'), classNames: ['sixty-percent-width-modal','modal-full-width'], - configs: configs, + recommendations: recommendations, secondaryClass: 'cancel-button', bodyClass: Em.View.extend({ templateName: require('templates/common/modal_popups/dependent_configs_list'), @@ -45,44 +45,38 @@ App.showDependentConfigsPopup = function (configs, primary, secondary) { }, updateCheckboxObserver: function () { Em.run.once(this, 'updateCheckbox'); - }.observes('parentView.parentView.configs.@each.saveRecommended'), + }.observes('parentView.parentView.recommendations.@each.saveRecommended'), updateCheckbox: function() { - this.set('checked', !(this.get('parentView.parentView.configs')|| []).someProperty('saveRecommended', false)); + this.set('checked', !(this.get('parentView.parentView.recommendations') || []).someProperty('saveRecommended', false)); }, updateSaveRecommended: function() { - this.get('parentView.parentView.configs').setEach('saveRecommended', this.get('checked')); + this.get('parentView.parentView.recommendations').setEach('saveRecommended', this.get('checked')); } }) }), - onPrimary: function () { - this._super(); - var propertiesToUpdate = this.get('configs').filter(function(c) { - return Em.get(c, 'saveRecommendedDefault') != Em.get(c, 'saveRecommended'); - }), - propertiesToUndo = propertiesToUpdate.filterProperty('saveRecommended', false), - propertiesToRedo = propertiesToUpdate.filterProperty('saveRecommended', true); - this.get('configs').forEach(function (c) { + saveChanges: function() { + this.get('recommendations').forEach(function (c) { Em.set(c, 'saveRecommendedDefault', Em.get(c, 'saveRecommended')); + }) + }, + discardChanges: function() { + this.get('recommendations').forEach(function(c) { + Em.set(c, 'saveRecommended', Em.get(c, 'saveRecommendedDefault')); }); - if (primary) { - primary(propertiesToUndo, propertiesToRedo); - } + }, + onPrimary: function () { + this._super(); + if (primary) primary(); + this.saveChanges(); }, onSecondary: function() { this._super(); - this.get('configs').forEach(function(c) { - Em.set(c, 'saveRecommended', Em.get(c, 'saveRecommendedDefault')); - }); - if (secondary) { - secondary(); - } + if (secondary) secondary(); + this.discardChanges(); }, onClose: function () { - this._super(); - if (secondary) { - secondary(); - } + this.onSecondary(); } }); }; http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/test/controllers/wizard/step7_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/wizard/step7_test.js b/ambari-web/test/controllers/wizard/step7_test.js index c6796aa..a54cc5d 100644 --- a/ambari-web/test/controllers/wizard/step7_test.js +++ b/ambari-web/test/controllers/wizard/step7_test.js @@ -1810,7 +1810,7 @@ describe('App.InstallerStep7Controller', function () { describe(test.m, function() { beforeEach(function () { - sinon.stub(controller, 'findConfigProperty').returns(Em.Object.create({ value: test.databaseType})); + sinon.stub(App.config, 'findConfigProperty').returns(Em.Object.create({ value: test.databaseType})); controller.reopen({ selectedServiceNames: test.selectedServiceNames }); @@ -1818,7 +1818,7 @@ describe('App.InstallerStep7Controller', function () { }); afterEach(function () { - controller.findConfigProperty.restore(); + App.config.findConfigProperty.restore(); }); it('modal popup is shown needed number of times', function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js index 3fc02a7..096918e 100644 --- a/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js +++ b/ambari-web/test/views/common/configs/widgets/config_widget_view_test.js @@ -261,12 +261,12 @@ describe('App.ConfigWidgetView', function () { }); it('dependent3 value is `1`', function () { - expect(view.get('controller').findConfigProperty('dependent3', 'some-file.xml').get('value')).to.be.equal('1'); + expect(App.config.findConfigProperty(ctrl.get('stepConfigs'), 'dependent3', 'some-file.xml').get('value')).to.be.equal('1'); }); it('dependent2 value is `10`', function () { // config with multi dependency should not be updated - expect(view.get('controller').findConfigProperty('dependent2', 'some-file.xml').get('value')).to.be.equal('10'); + expect(App.config.findConfigProperty(ctrl.get('stepConfigs'), 'dependent2', 'some-file.xml').get('value')).to.be.equal('10'); }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb219fb/ambari-web/test/views/common/modal_popups/dependent_configs_list_popup_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/common/modal_popups/dependent_configs_list_popup_test.js b/ambari-web/test/views/common/modal_popups/dependent_configs_list_popup_test.js index fde0512..9dc4bf6 100644 --- a/ambari-web/test/views/common/modal_popups/dependent_configs_list_popup_test.js +++ b/ambari-web/test/views/common/modal_popups/dependent_configs_list_popup_test.js @@ -40,7 +40,7 @@ describe('App.showDependentConfigsPopup', function () { beforeEach(function () { this.ff = function () {}; sinon.spy(this, 'ff'); - view = App.showDependentConfigsPopup({}, Em.K, this.ff); + view = App.showDependentConfigsPopup([], Em.K, this.ff); }); afterEach(function () {