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 () {

Reply via email to