You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/04/07 15:29:44 UTC
git commit: AMBARI-5371. Dashboard: dashboard actions do not work for
non-admin users. (onechiporenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 8ff1e60f1 -> e2b0e2ae7
AMBARI-5371. Dashboard: dashboard actions do not work for non-admin users. (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/e2b0e2ae
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/e2b0e2ae
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/e2b0e2ae
Branch: refs/heads/trunk
Commit: e2b0e2ae705844ea00397ac77ab31317a7d95e32
Parents: 8ff1e60
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Mon Apr 7 16:22:03 2014 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Mon Apr 7 16:22:03 2014 +0300
----------------------------------------------------------------------
ambari-web/app/controllers/wizard.js | 22 +-
ambari-web/app/mixins.js | 1 +
ambari-web/app/mixins/common/localStorage.js | 58 +++++
ambari-web/app/mixins/common/userPref.js | 37 ++-
ambari-web/app/utils/db.js | 6 +
ambari-web/app/views/main/dashboard.js | 253 +++++++++++++------
.../security/add/addSecurity_controller_test.js | 1 +
7 files changed, 280 insertions(+), 98 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/controllers/wizard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index 848a416..548edbb 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -20,7 +20,7 @@
var App = require('app');
require('models/host');
-App.WizardController = Em.Controller.extend({
+App.WizardController = Em.Controller.extend(App.LocalStorage, {
isStepDisabled: null,
@@ -46,26 +46,6 @@ App.WizardController = Em.Controller.extend({
});
}.property(),
- dbNamespace: function(){
- return this.get('name').capitalize().replace('Controller', "");
- }.property('name'),
- /**
- * get property from local storage
- * @param key
- * @return {*}
- */
- getDBProperty: function(key){
- return App.db.get(this.get('dbNamespace'), key);
- },
- /**
- * set property to local storage
- * @param key
- * @param value
- */
- setDBProperty: function(key, value){
- App.db.set(this.get('dbNamespace'), key, value);
- },
-
allHosts: App.Host.find(),
setStepsEnable: function () {
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/mixins.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js
index c437c2a..6feed84 100644
--- a/ambari-web/app/mixins.js
+++ b/ambari-web/app/mixins.js
@@ -19,5 +19,6 @@
// load all mixins here
+require('mixins/common/localStorage');
require('mixins/common/userPref');
require('mixins/main/host/details/host_components/decommissionable');
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/mixins/common/localStorage.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/localStorage.js b/ambari-web/app/mixins/common/localStorage.js
new file mode 100644
index 0000000..ed78f9a
--- /dev/null
+++ b/ambari-web/app/mixins/common/localStorage.js
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+/**
+ * Fast save/load value to Local Storage
+ * Object that impements it should have property <code>name</code> defined
+ * @type {Ember.Mixin}
+ */
+App.LocalStorage = Em.Mixin.create({
+
+ /**
+ * <code>App.db.data</code> key
+ * @returns {String}
+ */
+ dbNamespace: function() {
+ var name = this.get('name');
+ if (Em.isNone(name)) {
+ name = this.get('controller.name');
+ }
+ return name.capitalize().replace('Controller', '');
+ }.property('name'),
+
+ /**
+ * get property from local storage
+ * @param {String} key
+ * @return {*}
+ */
+ getDBProperty: function(key){
+ return App.db.get(this.get('dbNamespace'), key);
+ },
+
+ /**
+ * set property to local storage
+ * @param {String} key
+ * @param {*} value
+ */
+ setDBProperty: function(key, value){
+ App.db.set(this.get('dbNamespace'), key, value);
+ }
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/mixins/common/userPref.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/userPref.js b/ambari-web/app/mixins/common/userPref.js
index ea8c358..5ecef1c 100644
--- a/ambari-web/app/mixins/common/userPref.js
+++ b/ambari-web/app/mixins/common/userPref.js
@@ -21,10 +21,13 @@ var App = require('app');
/**
* Small mixin for processing user preferences
* Provide methods to save/load some values in <code>persist</code> storage
+ * Save available only for admin users!
* When using this mixin you should redeclare methods:
* <ul>
* <li>getUserPrefSuccessCallback</li>
* <li>getUserPrefErrorCallback</li>
+ * <li>postuserPrefSuccessCallback</li>
+ * <li>postuserPrefErrorCallback</li>
* </ul>
* @type {Em.Mixin}
*/
@@ -37,6 +40,12 @@ App.UserPref = Em.Mixin.create({
makeRequestAsync: true,
/**
+ * Additional to request data
+ * @type {object}
+ */
+ additionalData: {},
+
+ /**
* Get persist value from server with persistKey
* @param {String} key
*/
@@ -46,7 +55,8 @@ App.UserPref = Em.Mixin.create({
sender: this,
data: {
key: key,
- async: this.get('makeRequestAsync')
+ async: this.get('makeRequestAsync'),
+ data: this.get('additionalData')
},
success: 'getUserPrefSuccessCallback',
error: 'getUserPrefErrorCallback'
@@ -72,10 +82,12 @@ App.UserPref = Em.Mixin.create({
/**
* Post persist key/value to server, value is object
+ * Only for admin users!
* @param {String} key
* @param {Object} value
*/
postUserPref: function (key, value) {
+ if(!App.get('isAdmin')) return;
var keyValuePair = {};
keyValuePair[key] = JSON.stringify(value);
App.ajax.send({
@@ -85,11 +97,30 @@ App.UserPref = Em.Mixin.create({
'data': {
'async': this.get('makeRequestAsync'),
'keyValuePair': keyValuePair
- }
+ },
+ 'success': 'postUserPrefSuccessCallback',
+ 'error': 'postUserPrefErrorCallback'
});
},
/**
+ * Should be redeclared in objects that use this mixin
+ * @param {*} response
+ * @param {Object} request
+ * @param {Object} data
+ * @returns {*}
+ */
+ postUserPrefSuccessCallback: function (response, request, data) {},
+
+ /**
+ * Should be redeclared in objects that use this mixin
+ * @param {Object} request
+ * @param {Object} ajaxOptions
+ * @param {String} error
+ */
+ postUserPrefErrorCallback: function(request, ajaxOptions, error) {},
+
+ /**
* Little log before post request
* @param {Object} request
* @param {Object} ajaxOptions
@@ -99,4 +130,4 @@ App.UserPref = Em.Mixin.create({
console.log('BeforeSend to persist: persistKeyValues', data.keyValuePair);
}
-});
\ No newline at end of file
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/utils/db.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/db.js b/ambari-web/app/utils/db.js
index c8cc976..24f95d0 100644
--- a/ambari-web/app/utils/db.js
+++ b/ambari-web/app/utils/db.js
@@ -106,12 +106,18 @@ if (localStorage.getObject('ambari') == null) {
App.db.get = function (namespace, key) {
console.log('TRACE: Entering db:get' + key);
App.db.data = localStorage.getObject('ambari');
+ if (!App.db.data[namespace]) {
+ App.db.data[namespace] = {};
+ }
return App.db.data[namespace][key];
};
App.db.set = function (namespace, key, value) {
console.log('TRACE: Entering db:set' + key + ';value: ', value);
App.db.data = localStorage.getObject('ambari');
+ if (!App.db.data[namespace]) {
+ App.db.data[namespace] = {};
+ }
App.db.data[namespace][key] = value;
localStorage.setObject('ambari', App.db.data);
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/app/views/main/dashboard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard.js b/ambari-web/app/views/main/dashboard.js
index ad49d27..fbee8fa 100644
--- a/ambari-web/app/views/main/dashboard.js
+++ b/ambari-web/app/views/main/dashboard.js
@@ -19,20 +19,41 @@
var App = require('app');
var filters = require('views/common/filter_view');
-App.MainDashboardView = Em.View.extend(App.UserPref, {
+App.MainDashboardView = Em.View.extend(App.UserPref, App.LocalStorage, {
+
+ name: 'mainDashboardView',
+
templateName:require('templates/main/dashboard'),
+
didInsertElement:function () {
- this.services();
+ this.loadServices();
this.setWidgetsDataModel();
this.setInitPrefObject();
this.setOnLoadVisibleWidgets();
this.set('isDataLoaded',true);
- Ember.run.next(this, 'makeSortable');
+ Em.run.next(this, 'makeSortable');
},
+
+ /**
+ * List of services
+ * @type {Ember.Enumerable}
+ */
content:[],
+
+ /**
+ * @type {bool}
+ */
isDataLoaded: false,
+
+ /**
+ * Is Classic Dashboard style used
+ * @type {bool}
+ */
isClassicDashboard: false,
+ /**
+ * Make widgets' list sortable on New Dashboard style
+ */
makeSortable: function () {
var self = this;
$( "#sortable" ).sortable({
@@ -44,7 +65,7 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
// update persist then translate to real
var widgetsArray = $('div[viewid]'); // get all in DOM
self.getUserPref(self.get('persistKey'));
- var oldValue = self.get('currentPrefObject');
+ var oldValue = self.get('currentPrefObject') || self.getDBProperty(self.get('persistKey'));
var newValue = Em.Object.create({
dashboardVersion: oldValue.dashboardVersion,
visible: [],
@@ -58,12 +79,16 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
newValue.visible.push(id);
}
self.postUserPref(self.get('persistKey'), newValue);
+ self.setDBProperty(self.get('persistKey'), newValue);
//self.translateToReal(newValue);
}
}
}).disableSelection();
},
+ /**
+ * Set Service model values
+ */
setWidgetsDataModel: function () {
var services = App.Service.find();
var self = this;
@@ -88,6 +113,9 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}, this);
},
+ /**
+ * Load widget statuses to <code>initPrefObject</code>
+ */
setInitPrefObject: function() {
//in case of some service not installed
var visibleFull = [
@@ -137,14 +165,33 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
},
hdfs_model: null,
+
mapreduce_model: null,
+
mapreduce2_model: null,
+
yarn_model: null,
+
hbase_model: null,
+
storm_model: null,
+
+ /**
+ * List of visible widgets
+ * @type {Ember.Enumerable}
+ */
visibleWidgets: [],
+
+ /**
+ * List of hidden widgets
+ * @type {Ember.Enumerable}
+ */
hiddenWidgets: [], // widget child view will push object in this array if deleted
+ /**
+ * Submenu view for New Dashboard style
+ * @type {Ember.View}
+ */
plusButtonFilterView: filters.createComponentView({
/**
* Base methods was implemented in <code>filters.componentFieldView</code>
@@ -174,7 +221,7 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
} else {
//save in persist
parent.getUserPref(parent.get('persistKey'));
- var oldValue = parent.get('currentPrefObject');
+ var oldValue = parent.get('currentPrefObject') || parent.getDbProperty(parent.get('persistKey'));
var newValue = Em.Object.create({
dashboardVersion: oldValue.dashboardVersion,
visible: oldValue.visible,
@@ -188,8 +235,8 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
hiddenWidgets.forEach(function(item){
newValue.hidden.push([item.id, item.displayName]);
}, this);
-
parent.postUserPref(parent.get('persistKey'), newValue);
+ parent.setDBProperty(parent.get('persistKey'), newValue);
parent.translateToReal(newValue);
}
}
@@ -197,7 +244,7 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}),
/**
- * translate from Json value got from persist to real widgets view
+ * Translate from Json value got from persist to real widgets view
*/
translateToReal: function (value) {
var version = value.dashboardVersion;
@@ -234,51 +281,72 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}
},
+ /**
+ * Set visibility-status for widgets
+ */
setOnLoadVisibleWidgets: function () {
if (App.testMode) {
this.translateToReal(this.get('initPrefObject'));
} else {
// called when first load/refresh/jump back page
this.getUserPref(this.get('persistKey'));
- var currentPrefObject = this.get('currentPrefObject');
+ var currentPrefObject = this.get('currentPrefObject') || this.getDBProperty(this.get('persistKey'));
if (currentPrefObject) { // fit for no dashboard version
if (!currentPrefObject.dashboardVersion) {
currentPrefObject.dashboardVersion = 'new';
this.postUserPref(this.get('persistKey'), currentPrefObject);
+ this.setDBProperty(this.get('persistKey'), currentPrefObject);
}
this.set('currentPrefObject', this.checkServicesChange(currentPrefObject));
this.translateToReal(this.get('currentPrefObject'));
- } else {
+ }
+ else {
// post persist then translate init object
- if(App.get('isAdmin')) {
- this.postUserPref(this.get('persistKey'), this.get('initPrefObject'));
- }
+ this.postUserPref(this.get('persistKey'), this.get('initPrefObject'));
+ this.setDBProperty(this.get('persistKey'), this.get('initPrefObject'));
this.translateToReal(this.get('initPrefObject'));
}
}
},
- removeWidget: function (value, itemToRemove) {
- value.visible = value.visible.without(itemToRemove);
+
+ /**
+ * Remove widget from visible and hidden lists
+ * @param {Object} value
+ * @param {Object} widget
+ * @returns {*}
+ */
+ removeWidget: function (value, widget) {
+ value.visible = value.visible.without(widget);
for (var j = 0; j <= value.hidden.length -1; j++) {
- if (value.hidden[j][0] == itemToRemove) {
+ if (value.hidden[j][0] == widget) {
value.hidden.splice(j, 1);
}
}
return value;
},
- containsWidget: function (value, item) {
- var flag = value.visible.contains (item);
+
+ /**
+ * Check if widget is in visible or hidden list
+ * @param {Object} value
+ * @param {Object} widget
+ * @returns {bool}
+ */
+ containsWidget: function (value, widget) {
+ var flag = value.visible.contains (widget);
for (var j = 0; j <= value.hidden.length -1; j++) {
- if ( !flag && value.hidden[j][0] == item) {
+ if ( !flag && value.hidden[j][0] == widget) {
flag = true;
break;
}
}
return flag;
},
+
/**
* check if stack has upgraded from HDP 1.0 to 2.0 OR add/delete services.
* Update the value on server if true.
+ * @param {Object} currentPrefObject
+ * @return {Object}
*/
checkServicesChange: function (currentPrefObject) {
var toDelete = $.extend(true, {}, currentPrefObject);
@@ -357,40 +425,52 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
return value;
},
+ /**
+ * Get view for widget by widget's id
+ * @param {string} id
+ * @returns {Ember.View}
+ */
widgetsMapper: function (id) {
- switch(id){
- case '1': return App.NameNodeHeapPieChartView;
- case '2': return App.NameNodeCapacityPieChartView;
- case '3': return App.NameNodeCpuPieChartView;
- case '4': return App.DataNodeUpView;
- case '5': return App.NameNodeRpcView;
- case '6': return App.JobTrackerHeapPieChartView;
- case '7': return App.JobTrackerCpuPieChartView;
- case '8': return App.TaskTrackerUpView;
- case '9': return App.JobTrackerRpcView;
- case '10': return App.MapReduceSlotsView;
- case '11': return App.ChartClusterMetricsMemoryWidgetView;
- case '12': return App.ChartClusterMetricsNetworkWidgetView;
- case '13': return App.ChartClusterMetricsCPUWidgetView;
- case '14': return App.ChartClusterMetricsLoadWidgetView;
- case '15': return App.NameNodeUptimeView;
- case '16': return App.JobTrackerUptimeView;
- case '17': return App.HDFSLinksView;
- case '18': return App.MapReduceLinksView;
- case '19': return App.HBaseLinksView;
- case '20': return App.HBaseMasterHeapPieChartView;
- case '21': return App.HBaseAverageLoadView;
- case '22': return App.HBaseRegionsInTransitionView;
- case '23': return App.HBaseMasterUptimeView;
- case '24': return App.ResourceManagerHeapPieChartView;
- case '25': return App.ResourceManagerUptimeView;
- case '26': return App.NodeManagersLiveView;
- case '27': return App.YARNMemoryPieChartView;
- case '28': return App.SuperVisorUpView;
- }
+ return Em.get({
+ '1': App.NameNodeHeapPieChartView,
+ '2': App.NameNodeCapacityPieChartView,
+ '3': App.NameNodeCpuPieChartView,
+ '4': App.DataNodeUpView,
+ '5': App.NameNodeRpcView,
+ '6': App.JobTrackerHeapPieChartView,
+ '7': App.JobTrackerCpuPieChartView,
+ '8': App.TaskTrackerUpView,
+ '9': App.JobTrackerRpcView,
+ '10': App.MapReduceSlotsView,
+ '11': App.ChartClusterMetricsMemoryWidgetView,
+ '12': App.ChartClusterMetricsNetworkWidgetView,
+ '13': App.ChartClusterMetricsCPUWidgetView,
+ '14': App.ChartClusterMetricsLoadWidgetView,
+ '15': App.NameNodeUptimeView,
+ '16': App.JobTrackerUptimeView,
+ '17': App.HDFSLinksView,
+ '18': App.MapReduceLinksView,
+ '19': App.HBaseLinksView,
+ '20': App.HBaseMasterHeapPieChartView,
+ '21': App.HBaseAverageLoadView,
+ '22': App.HBaseRegionsInTransitionView,
+ '23': App.HBaseMasterUptimeView,
+ '24': App.ResourceManagerHeapPieChartView,
+ '25': App.ResourceManagerUptimeView,
+ '26': App.NodeManagersLiveView,
+ '27': App.YARNMemoryPieChartView,
+ '28': App.SuperVisorUpView
+ }, id);
},
+ /**
+ * @type {Object|null}
+ */
currentPrefObject: null,
+
+ /**
+ * @type {Ember.Object}
+ */
initPrefObject: Em.Object.create({
dashboardVersion: 'new',
visible: [],
@@ -399,10 +479,14 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
10: [], 11: [], 12: [], 13: [], 14: [], 15: [], 16: [], 17: [], 18: [], 19: [], 20: [70, 90], 21: [10, 19.2], 22: [3, 10], 23: [],
24: [70, 90], 25: [], 26: [50, 75], 27: [50, 75], 28: [85, 95]} // id:[thresh1, thresh2]
}),
+
+ /**
+ * Key-name to store data in Local Storage and Persist
+ * @type {string}
+ */
persistKey: function () {
- var loginName = App.router.get('loginName');
- return 'user-pref-' + loginName + '-dashboard';
- }.property(''),
+ return 'user-pref-' + App.router.get('loginName') + '-dashboard';
+ }.property(),
makeRequestAsync: false,
@@ -413,51 +497,65 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}
},
- getUserPrefErrorCallback: function (request, ajaxOptions, error) {
+ getUserPrefErrorCallback: function (request) {
// this user is first time login
if (request.status == 404) {
console.log('Persist did NOT find the key');
- return null;
}
},
- resetAllWidgets: function(){
+ /**
+ * Reset widgets visibility-status
+ */
+ resetAllWidgets: function() {
var self = this;
App.showConfirmationPopup(function() {
- if(!App.testMode){
+ if(!App.testMode) {
self.postUserPref(self.get('persistKey'), self.get('initPrefObject'));
+ self.setDBProperty(self.get('persistKey'), self.get('initPrefObject'));
}
self.translateToReal(self.get('initPrefObject'));
});
},
+ /**
+ * Use Classic Dashboard style
+ */
switchToClassic: function () {
- if(!App.testMode){
- this.getUserPref(this.get('persistKey'));
- var oldValue = this.get('currentPrefObject');
- oldValue.dashboardVersion = 'classic';
- this.postUserPref(this.get('persistKey'), oldValue);
- }else{
- var oldValue = this.get('initPrefObject');
- oldValue.dashboardVersion = 'classic';
- }
- this.translateToReal(oldValue);
+ this.switchTo('classic');
},
+ /**
+ * Use New Dashboard style
+ */
switchToNew: function () {
- if(!App.testMode){
+ this.switchTo('new');
+ },
+
+ /**
+ * Switch Dashboard to New or Classic style
+ * @param {string} type
+ */
+ switchTo: function(type) {
+ var oldValue;
+ if(App.testMode) {
+ oldValue = this.get('initPrefObject');
+ oldValue.dashboardVersion = type;
+ this.translateToReal(oldValue);
+ }
+ else {
this.getUserPref(this.get('persistKey'));
- var oldValue = this.get('currentPrefObject');
- oldValue.dashboardVersion = 'new';
+ oldValue = this.get('currentPrefObject') || this.getDBProperty(this.get('persistKey'));
+ oldValue.dashboardVersion = type;
this.postUserPref(this.get('persistKey'), oldValue);
+ this.setDBProperty(this.get('persistKey'), oldValue);
this.didInsertElement();
- }else{
- var oldValue = this.get('initPrefObject');
- oldValue.dashboardVersion = 'new';
- this.translateToReal(oldValue);
}
},
+ /**
+ * Update list of services in the <code>content</code>
+ */
updateServices: function(){
var services = App.Service.find();
services.forEach(function (item) {
@@ -478,10 +576,13 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}, this);
}.observes('App.router.updateController.isUpdate'),
- services: function () {
+ /**
+ * Load Services data to <code>content</code>
+ */
+ loadServices: function () {
var services = App.Service.find();
if (this.get('content').length > 0) {
- return false
+ return;
}
services.forEach(function (item) {
var vName;
@@ -525,6 +626,9 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
}, this);
},
+ /**
+ * @type {string}
+ */
gangliaUrl: function () {
return App.router.get('clusterController.gangliaUrl') + "/?r=hour&cs=&ce=&m=&s=by+name&c=HDPSlaves&tab=m&vn=";
}.property('App.router.clusterController.gangliaUrl'),
@@ -577,4 +681,5 @@ App.MainDashboardView = Em.View.extend(App.UserPref, {
});
event.stopPropagation();
}
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/e2b0e2ae/ambari-web/test/controllers/main/admin/security/add/addSecurity_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/admin/security/add/addSecurity_controller_test.js b/ambari-web/test/controllers/main/admin/security/add/addSecurity_controller_test.js
index 2996579..e2c5ff9 100644
--- a/ambari-web/test/controllers/main/admin/security/add/addSecurity_controller_test.js
+++ b/ambari-web/test/controllers/main/admin/security/add/addSecurity_controller_test.js
@@ -19,6 +19,7 @@
var App = require('app');
require('models/host');
+require('mixins/common/localStorage');
require('controllers/wizard');
require('controllers/main/admin/security/add/addSecurity_controller');
require('models/host_component');