You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2017/02/17 21:30:02 UTC
[04/15] ambari git commit: AMBARI-20043. Don't rerender all widgets
when one of them is changed (onechiporenko)
AMBARI-20043. Don't rerender all widgets when one of them is changed (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/05c76ed6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/05c76ed6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/05c76ed6
Branch: refs/heads/branch-feature-AMBARI-20053
Commit: 05c76ed609dfcf75e0ff211aa8032834ef8e9f73
Parents: 984b35e
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Thu Feb 16 15:25:48 2017 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Fri Feb 17 10:26:47 2017 +0200
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 1 +
ambari-web/app/data/dashboard_widgets.js | 196 +++++++++
ambari-web/app/messages.js | 2 +-
.../app/mixins/common/track_request_mixin.js | 6 +-
.../mixins/main/dashboard/widgets/editable.js | 91 +---
.../dashboard/widgets/editable_with_limit.js | 106 +----
.../widgets/single_numeric_threshold.js | 127 +-----
.../main/dashboard/edit_widget_popup.hbs | 20 +-
.../edit_widget_popup_single_threshold.hbs | 12 +-
ambari-web/app/views.js | 1 +
.../modal_popups/edit_dashboard_widget_popup.js | 436 +++++++++++++++++++
ambari-web/app/views/main/dashboard/widget.js | 173 ++------
ambari-web/app/views/main/dashboard/widgets.js | 266 ++---------
.../views/main/dashboard/widgets/text_widget.js | 23 +-
.../edit_dashboard_widget_popup_test.js | 214 +++++++++
.../test/views/main/dashboard/widget_test.js | 112 +----
.../test/views/main/dashboard/widgets_test.js | 10 +-
17 files changed, 968 insertions(+), 828 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index d47d558..05c1657 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -253,6 +253,7 @@ var files = [
'test/views/common/widget/template_widget_view_test',
'test/views/common/widget/heatmap_widget_view_test',
'test/views/common/modal_popups/cluster_check_popup_test',
+ 'test/views/common/modal_popups/edit_dashboard_widget_popup_test',
'test/views/common/modal_popups/hosts_table_list_popup_test',
'test/views/common/modal_popups/dependent_configs_list_popup_test',
'test/views/main/admin_test',
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/data/dashboard_widgets.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/dashboard_widgets.js b/ambari-web/app/data/dashboard_widgets.js
new file mode 100644
index 0000000..d58b0e2
--- /dev/null
+++ b/ambari-web/app/data/dashboard_widgets.js
@@ -0,0 +1,196 @@
+/**
+ * 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.
+ */
+
+module.exports = [
+ {
+ id: 1,
+ viewName: 'NameNodeHeapPieChartView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.NameNodeHeap'),
+ threshold: [80, 90]
+ },
+ {
+ id: 2,
+ viewName: 'NameNodeCapacityPieChartView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.HDFSDiskUsage'),
+ threshold: [85, 95]
+ },
+ {
+ id: 3,
+ viewName: 'NameNodeCpuPieChartView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.NameNodeCpu'),
+ threshold: [90, 95]
+ },
+ {
+ id: 4,
+ viewName: 'DataNodeUpView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.DataNodeUp'),
+ threshold: [80, 90]
+ },
+ {
+ id: 5,
+ viewName: 'NameNodeRpcView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.NameNodeRpc'),
+ threshold: [1000, 3000]
+ },
+ {
+ id: 6,
+ viewName: 'ChartClusterMetricsMemoryWidgetView',
+ sourceName: 'HOST_METRICS',
+ title: Em.I18n.t('dashboard.clusterMetrics.memory'),
+ threshold: []
+ },
+ {
+ id: 7,
+ viewName: 'ChartClusterMetricsNetworkWidgetView',
+ sourceName: 'HOST_METRICS',
+ title: Em.I18n.t('dashboard.clusterMetrics.network'),
+ threshold: []
+ },
+ {
+ id: 8,
+ viewName: 'ChartClusterMetricsCPUWidgetView',
+ sourceName: 'HOST_METRICS',
+ title: Em.I18n.t('dashboard.clusterMetrics.cpu'),
+ threshold: []
+ },
+ {
+ id: 9,
+ viewName: 'ChartClusterMetricsLoadWidgetView',
+ sourceName: 'HOST_METRICS',
+ title: Em.I18n.t('dashboard.clusterMetrics.load'),
+ threshold: []
+ },
+ {
+ id: 10,
+ viewName: 'NameNodeUptimeView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.NameNodeUptime'),
+ threshold: []
+ },
+ {
+ id: 11,
+ viewName: 'HDFSLinksView',
+ sourceName: 'HDFS',
+ title: Em.I18n.t('dashboard.widgets.HDFSLinks'),
+ threshold: []
+ },
+ {
+ id: 12,
+ viewName: 'HBaseLinksView',
+ sourceName: 'HBASE',
+ title: Em.I18n.t('dashboard.widgets.HBaseLinks'),
+ threshold: []
+ },
+ {
+ id: 13,
+ viewName: 'HBaseMasterHeapPieChartView',
+ sourceName: 'HBASE',
+ title: Em.I18n.t('dashboard.widgets.HBaseMasterHeap'),
+ threshold: [70, 90]
+ },
+ {
+ id: 14,
+ viewName: 'HBaseAverageLoadView',
+ sourceName: 'HBASE',
+ title: Em.I18n.t('dashboard.widgets.HBaseAverageLoad'),
+ threshold: [150, 250]
+ },
+ {
+ id: 15,
+ viewName: 'HBaseRegionsInTransitionView',
+ sourceName: 'HBASE',
+ title: Em.I18n.t('dashboard.widgets.HBaseRegionsInTransition'),
+ threshold: [3, 10],
+ isHiddenByDefault: true
+ },
+ {
+ id: 16,
+ viewName: 'HBaseMasterUptimeView',
+ sourceName: 'HBASE',
+ title: Em.I18n.t('dashboard.widgets.HBaseMasterUptime'),
+ threshold: []
+ },
+ {
+ id: 17,
+ viewName: 'ResourceManagerHeapPieChartView',
+ sourceName: 'YARN',
+ title: Em.I18n.t('dashboard.widgets.ResourceManagerHeap'),
+ threshold: [70, 90]
+ },
+ {
+ id: 18,
+ viewName: 'ResourceManagerUptimeView',
+ sourceName: 'YARN',
+ title: Em.I18n.t('dashboard.widgets.ResourceManagerUptime'),
+ threshold: []
+ },
+ {
+ id: 19,
+ viewName: 'NodeManagersLiveView',
+ sourceName: 'YARN',
+ title: Em.I18n.t('dashboard.widgets.NodeManagersLive'),
+ threshold: [50, 75]
+ },
+ {
+ id: 20,
+ viewName: 'YARNMemoryPieChartView',
+ sourceName: 'YARN',
+ title: Em.I18n.t('dashboard.widgets.YARNMemory'),
+ threshold: [50, 75]
+ },
+ {
+ id: 21,
+ viewName: 'SuperVisorUpView',
+ sourceName: 'STORM',
+ title: Em.I18n.t('dashboard.widgets.SuperVisorUp'),
+ threshold: [85, 95]
+ },
+ {
+ id: 22,
+ viewName: 'FlumeAgentUpView',
+ sourceName: 'FLUME',
+ title: Em.I18n.t('dashboard.widgets.FlumeAgentUp'),
+ threshold: [85, 95]
+ },
+ {
+ id: 23,
+ viewName: 'YARNLinksView',
+ sourceName: 'YARN',
+ title: Em.I18n.t('dashboard.widgets.YARNLinks'),
+ threshold: []
+ },
+ {
+ id: 24,
+ viewName: 'HawqSegmentUpView',
+ sourceName: 'HAWQ',
+ title: Em.I18n.t('dashboard.widgets.HawqSegmentUp'),
+ threshold: [75, 90]
+ },
+ {
+ id: 25,
+ viewName: 'PxfUpView',
+ sourceName: 'PXF',
+ title: Em.I18n.t('dashboard.widgets.PxfUp'),
+ threshold: []
+ }
+];
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 81833f3..5d69b53 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2860,7 +2860,7 @@ Em.I18n.translations = {
'dashboard.widgets.NodeManagersLive': 'NodeManagers Live',
'dashboard.widgets.YARNMemory': 'YARN Memory',
'dashboard.widgets.YARNLinks': 'YARN Links',
- 'dashboard.widgets.error.invalid': 'Invalid! Enter a number between 0 - {0}',
+ 'dashboard.widgets.error.invalid': 'Invalid! Enter a number between {0} - {1}',
'dashboard.widgets.error.smaller': 'Threshold 1 should be smaller than threshold 2!',
'dashboard.widgets.HawqSegmentUp': 'HAWQ Segments Live',
'dashboard.widgets.PxfUp': 'PXF Agents Live',
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/mixins/common/track_request_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/track_request_mixin.js b/ambari-web/app/mixins/common/track_request_mixin.js
index c665253..dd97b97 100644
--- a/ambari-web/app/mixins/common/track_request_mixin.js
+++ b/ambari-web/app/mixins/common/track_request_mixin.js
@@ -38,14 +38,14 @@ App.TrackRequestMixin = Em.Mixin.create({
this.get('requestsInProgress').pushObject({
request: request,
id: requestId,
- status: request.state(),
- completed: ['resolved', 'rejected'].contains(request.state())
+ status: Em.tryInvoke(request, 'state'),
+ completed: ['resolved', 'rejected'].contains(Em.tryInvoke(request, 'state'))
});
request.always(function() {
var requestInProgress = self.get('requestsInProgress').findProperty('id', requestId) || {};
Em.setProperties(requestInProgress, {
completed: true,
- status: request.state()
+ status: Em.tryInvoke(request, 'state')
});
});
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/mixins/main/dashboard/widgets/editable.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/dashboard/widgets/editable.js b/ambari-web/app/mixins/main/dashboard/widgets/editable.js
index fcb6bfb..482ff6a 100644
--- a/ambari-web/app/mixins/main/dashboard/widgets/editable.js
+++ b/ambari-web/app/mixins/main/dashboard/widgets/editable.js
@@ -20,93 +20,22 @@ var App = require('app');
App.EditableWidgetMixin = Em.Mixin.create({
- hintInfo: '',
-
editWidget: function () {
- var self = this;
- var configObj = Ember.Object.create({
- thresholdMin: self.get('thresholdMin') + '',
- thresholdMax: self.get('thresholdMax') + '',
- hintInfo: self.get('hintInfo'),
- isThresh1Error: false,
- isThresh2Error: false,
- errorMessage1: "",
- errorMessage2: "",
- maxValue: 'infinity',
- observeNewThresholdValue: function () {
- var thresholdMin = this.get('thresholdMin');
- var thresholdMax = this.get('thresholdMax');
- if (thresholdMin.trim() !== "") {
- if (isNaN(thresholdMin) || thresholdMin < 0) {
- this.set('isThresh1Error', true);
- this.set('errorMessage1', 'Invalid! Enter a number larger than 0');
- } else if ( this.get('isThresh2Error') === false && parseFloat(thresholdMax)<= parseFloat(thresholdMin)){
- this.set('isThresh1Error', true);
- this.set('errorMessage1', 'Threshold 1 should be smaller than threshold 2 !');
- } else {
- this.set('isThresh1Error', false);
- this.set('errorMessage1', '');
- }
- } else {
- this.set('isThresh1Error', true);
- this.set('errorMessage1', 'This is required');
- }
-
- if (thresholdMax.trim() !== "") {
- if (isNaN(thresholdMax) || thresholdMax < 0) {
- this.set('isThresh2Error', true);
- this.set('errorMessage2', 'Invalid! Enter a number larger than 0');
- } else {
- this.set('isThresh2Error', false);
- this.set('errorMessage2', '');
- }
- } else {
- this.set('isThresh2Error', true);
- this.set('errorMessage2', 'This is required');
- }
+ return App.EditDashboardWidgetPopup.show({
- }.observes('thresholdMin', 'thresholdMax')
+ widgetView: this,
- });
-
- App.ModalPopup.show({
- header: Em.I18n.t('dashboard.widgets.popupHeader'),
- classNames: [ 'modal-edit-widget'],
- modalDialogClasses: ['modal-lg'],
- bodyClass: Ember.View.extend({
- templateName: require('templates/main/dashboard/edit_widget_popup'),
- configPropertyObj: configObj
+ sliderHandlersManager: App.EditDashboardWidgetPopup.DoubleHandlers.create({
+ maxValue: 'infinity',
+ thresholdMin: this.get('thresholdMin'),
+ thresholdMax: this.get('thresholdMax')
}),
- primary: Em.I18n.t('common.apply'),
- onPrimary: function () {
- configObj.observeNewThresholdValue();
- if (!configObj.isThresh1Error && !configObj.isThresh2Error) {
-
- var parent = self.get('parentView');
- var userPreferences = parent.get('userPreferences');
- userPreferences.threshold[Number(self.get('id'))] = [configObj.get('thresholdMin'), configObj.get('thresholdMax')];
- parent.saveWidgetsSettings(userPreferences);
- parent.renderWidgets();
- this.hide();
- }
- },
- didInsertElement: function () {
- this._super();
- var colors = [App.healthStatusGreen, App.healthStatusOrange, App.healthStatusRed]; //color green, orange ,red
- var handlers = [33, 66]; //fixed value
+ sliderDisabled: true,
+ sliderHandlers: [33, 66],
+ sliderMaxValue: 100,
+ sliderColors: [App.healthStatusGreen, App.healthStatusOrange, App.healthStatusRed]
- $("#slider-range").slider({
- range: true,
- disabled: true, //handlers cannot move
- min: 0,
- max: 100,
- values: handlers,
- create: function (event, ui) {
- self.updateColors(handlers, colors);
- }
- });
- }
});
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/mixins/main/dashboard/widgets/editable_with_limit.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/dashboard/widgets/editable_with_limit.js b/ambari-web/app/mixins/main/dashboard/widgets/editable_with_limit.js
index ddf2a26..1cb96df 100644
--- a/ambari-web/app/mixins/main/dashboard/widgets/editable_with_limit.js
+++ b/ambari-web/app/mixins/main/dashboard/widgets/editable_with_limit.js
@@ -23,110 +23,18 @@ var App = require('app');
*/
App.EditableWithLimitWidgetMixin = Em.Mixin.create({
- hintInfo: '',
-
editWidget: function () {
- var parent = this;
- var maxTmp = parseFloat(parent.get('maxValue'));
- var configObj = Ember.Object.create({
- thresholdMin: parent.get('thresholdMin') + '',
- thresholdMax: parent.get('thresholdMax') + '',
- hintInfo: parent.get('hintInfo'),
- thresholdMinError: false,
- thresholdMaxError: false,
- thresholdMinErrorMessage: '',
- thresholdMaxErrorMessage: '',
- maxValue: maxTmp,
- observeNewThresholdValue: function () {
- var thresholdMin = this.get('thresholdMin');
- var thresholdMax = this.get('thresholdMax');
- if (thresholdMin.trim() !== '') {
- if (isNaN(thresholdMin) || thresholdMin > maxTmp || thresholdMin < 0){
- this.set('thresholdMinError', true);
- this.set('thresholdMinErrorMessage', 'Invalid! Enter a number between 0 - ' + maxTmp);
- } else if ( this.get('thresholdMaxError') === false && parseFloat(thresholdMax)<= parseFloat(thresholdMin)) {
- this.set('thresholdMinError', true);
- this.set('thresholdMinErrorMessage', 'Threshold 1 should be smaller than threshold 2 !');
- } else {
- this.set('thresholdMinError', false);
- this.set('thresholdMinErrorMessage', '');
- }
- } else {
- this.set('thresholdMinError', true);
- this.set('thresholdMinErrorMessage', 'This is required');
- }
-
- if (thresholdMax.trim() !== '') {
- if (isNaN(thresholdMax) || thresholdMax > maxTmp || thresholdMax < 0) {
- this.set('thresholdMaxError', true);
- this.set('thresholdMaxErrorMessage', 'Invalid! Enter a number between 0 - ' + maxTmp);
- } else {
- this.set('thresholdMaxError', false);
- this.set('thresholdMaxErrorMessage', '');
- }
- } else {
- this.set('thresholdMaxError', true);
- this.set('thresholdMaxErrorMessage', 'This is required');
- }
-
- // update the slider handles and color
- if (!this.get('thresholdMinError') && !this.get('thresholdMaxError')) {
- $("#slider-range").slider('values', 0 , parseFloat(thresholdMin));
- $("#slider-range").slider('values', 1 , parseFloat(thresholdMax));
- }
- }.observes('thresholdMin', 'thresholdMax')
-
- });
- App.ModalPopup.show({
- header: Em.I18n.t('dashboard.widgets.popupHeader'),
- classNames: ['modal-edit-widget'],
- modalDialogClasses: ['modal-lg'],
- bodyClass: Ember.View.extend({
- templateName: require('templates/main/dashboard/edit_widget_popup'),
- configPropertyObj: configObj
- }),
- primary: Em.I18n.t('common.apply'),
- onPrimary: function () {
- configObj.observeNewThresholdValue();
- if (!configObj.thresholdMinError && !configObj.thresholdMaxError) {
- parent.set('thresholdMin', parseFloat(configObj.get('thresholdMin')) );
- parent.set('thresholdMax', parseFloat(configObj.get('thresholdMax')) );
- if (!App.get('testMode')) {
- var bigParent = parent.get('parentView');
- bigParent.getUserPref(bigParent.get('persistKey'));
- var oldValue = bigParent.get('currentPrefObject');
- oldValue.threshold[parseInt(parent.id, 10)] = [configObj.get('thresholdMin'), configObj.get('thresholdMax')];
- bigParent.postUserPref(bigParent.get('persistKey'),oldValue);
- }
- this.hide();
- }
- },
+ return App.EditDashboardWidgetPopup.show({
- didInsertElement: function () {
- this._super();
- var handlers = [configObj.get('thresholdMin'), configObj.get('thresholdMax')];
- var colors = [App.healthStatusRed, App.healthStatusOrange, App.healthStatusGreen]; //color red, orange, green
+ widgetView: this,
- $("#slider-range").slider({
- range: true,
- min: 0,
- max: maxTmp,
- values: handlers,
- create: function () {
- parent.updateColors(handlers, colors);
- },
- slide: function (event, ui) {
- parent.updateColors(ui.values, colors);
- configObj.set('thresholdMin', ui.values[0] + '');
- configObj.set('thresholdMax', ui.values[1] + '');
- },
- change: function (event, ui) {
- parent.updateColors(ui.values, colors);
- }
- });
+ sliderHandlersManager: App.EditDashboardWidgetPopup.DoubleHandlers.create({
+ maxValue: parseFloat(this.get('maxValue')),
+ thresholdMin: this.get('thresholdMin'),
+ thresholdMax: this.get('thresholdMax')
+ })
- }
});
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js b/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js
index 06bcffe..36172b7 100644
--- a/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js
+++ b/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js
@@ -23,126 +23,25 @@ var App = require('app');
*/
App.SingleNumericThresholdMixin = Em.Mixin.create({
- /**
- * @type {Em.Object}
- * @class
- */
- widgetConfig: Ember.Object.extend({
- thresholdMin: '',
- hintInfo: '',
- isThresh1Error: false,
- errorMessage1: "",
-
- maxValue: 0,
- observeThresh1Value: function () {
- var thresholdMin = this.get('thresholdMin');
- var maxValue = this.get('maxValue');
-
- if (thresholdMin.trim() !== "") {
- if (isNaN(thresholdMin) || thresholdMin > maxValue || thresholdMin < 0) {
- this.set('isThresh1Error', true);
- this.set('errorMessage1', Em.I18n.t('dashboard.widgets.error.invalid').format(maxValue));
- } else {
- this.set('isThresh1Error', false);
- this.set('errorMessage1', '');
- }
- } else {
- this.set('isThresh1Error', true);
- this.set('errorMessage1', Em.I18n.t('admin.users.editError.requiredField'));
- }
- this.updateSlider();
- }.observes('thresholdMin', 'maxValue'),
-
- updateSlider: function () {
- var thresholdMin = this.get('thresholdMin');
- // update the slider handles and color
- if (this.get('isThresh1Error') === false) {
- $("#slider-range")
- .slider('values', 0, parseFloat(thresholdMin))
- }
- }
- }),
-
- /**
- * edit widget
- * @param {object} event
- */
editWidget: function () {
- var parent = this;
- var maxTmp = parseFloat(this.get('maxValue'));
- var configObj = this.get('widgetConfig').create({
- thresholdMin: this.get('thresholdMin') + '',
- hintInfo: this.get('hintInfo') + '',
- maxValue: parseFloat(this.get('maxValue'))
- });
+ return App.EditDashboardWidgetPopup.show({
+
+ widgetView: this,
- App.ModalPopup.show({
- header: Em.I18n.t('dashboard.widgets.popupHeader'),
- classNames: ['modal-edit-widget'],
- modalDialogClasses: ['modal-lg'],
- bodyClass: Ember.View.extend({
- templateName: require('templates/main/dashboard/edit_widget_popup_single_threshold'),
- configPropertyObj: configObj
- }),
- primary: Em.I18n.t('common.apply'),
- onPrimary: function () {
- configObj.observeThresh1Value();
- if (!configObj.isThresh1Error) {
- var bigParent = parent.get('parentView');
- parent.set('thresholdMin', parseFloat(configObj.get('thresholdMin')));
- if (!App.get('testMode')) {
- // save to persist
- var userPreferences = bigParent.get('userPreferences');
- userPreferences.threshold[parseInt(parent.get('id'), 10)] = [configObj.get('thresholdMin')];
- bigParent.saveWidgetsSettings(userPreferences);
- bigParent.renderWidgets();
- }
- this.hide();
- }
- },
- didInsertElement: function () {
- this._super();
- var handlers = [configObj.get('thresholdMin')];
- var _this = this;
+ sliderHandlersManager: App.EditDashboardWidgetPopup.SingleHandler.create({
+ thresholdMin: this.get('thresholdMin'),
+ maxValue: parseFloat(this.get('maxValue'))
+ }),
- $("#slider-range").slider({
- range: false,
- min: 0,
- max: maxTmp,
- values: handlers,
- create: function () {
- _this.updateColors(handlers);
- },
- slide: function (event, ui) {
- _this.updateColors(ui.values);
- configObj.set('thresholdMin', ui.values[0] + '');
- },
- change: function (event, ui) {
- _this.updateColors(ui.values);
- }
- });
- },
+ bodyClass: App.EditDashboardWidgetPopup.EditDashboardWidgetPopupBody.extend({
+ templateName: require('templates/main/dashboard/edit_widget_popup_single_threshold')
+ }),
- updateColors: function (handlers) {
- var colors = [App.healthStatusGreen, App.healthStatusRed]; //color green,red
- var colorstops = colors[0] + ", "; // start with the first color
- for (var i = 0; i < handlers.length; i++) {
- colorstops += colors[i] + " " + handlers[i] * 100 / maxTmp + "%,";
- colorstops += colors[i + 1] + " " + handlers[i] * 100 / maxTmp + "%,";
- }
- colorstops += colors[colors.length - 1];
- var sliderElement = $('#slider-range');
- var css1 = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
- sliderElement.css('background-image', css1);
- var css2 = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
- sliderElement.css('background-image', css2);
- var css3 = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
- sliderElement.css('background-image', css3);
+ sliderIsRange: false,
- sliderElement.find('.ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the original ranger color
- }
+ sliderColors: [App.healthStatusGreen, App.healthStatusRed]
- });
+ });
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs b/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
index 7caf085..60c9741 100644
--- a/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
+++ b/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
@@ -18,7 +18,7 @@
<form class="form-horizontal" autocomplete="off">
<div class="each-row">
<div class="alert alert-info">
- {{{view.configPropertyObj.hintInfo}}}
+ {{{view.parentView.widgetView.hintInfo}}}
</div>
</div>
@@ -32,20 +32,20 @@
<div id="slider-value1" class="value-on-slider col-md-2">
<input type="text" value="0" disabled="disabled" class="form-control" />
</div>
- <div id="slider-value2" {{bindAttr class="view.configPropertyObj.thresholdMinError:slider-error :value-on-slider :col-md-4 view.configPropertyObj.thresholdMinError:has-error"}}>
- {{view Ember.TextField class="form-control" valueBinding="view.configPropertyObj.thresholdMin"}}
- {{#if view.configPropertyObj.thresholdMinErrorMessage}}
- <span class="help-block validation-block">{{view.configPropertyObj.thresholdMinErrorMessage}}</span>
+ <div id="slider-value2" {{bindAttr class="view.parentView.sliderHandlersManager.thresholdMinError:slider-error :value-on-slider :col-md-4 view.parentView.sliderHandlersManager.thresholdMinError:has-error"}}>
+ {{view Ember.TextField class="form-control" valueBinding="view.parentView.sliderHandlersManager.thresholdMin"}}
+ {{#if view.parentView.sliderHandlersManager.thresholdMinError}}
+ <span class="help-block validation-block">{{view.parentView.sliderHandlersManager.thresholdMinErrorMessage}}</span>
{{/if}}
</div>
- <div id="slider-value3" {{bindAttr class="view.configPropertyObj.thresholdMaxError:slider-error :value-on-slider :col-md-4 view.configPropertyObj.thresholdMaxError:has-error"}}>
- {{view Ember.TextField class="form-control" valueBinding="view.configPropertyObj.thresholdMax"}}
- {{#if view.configPropertyObj.thresholdMaxErrorMessage}}
- <span class="help-block validation-block">{{view.configPropertyObj.thresholdMaxErrorMessage}}</span>
+ <div id="slider-value3" {{bindAttr class="view.parentView.sliderHandlersManager.thresholdMaxError:slider-error :value-on-slider :col-md-4 view.parentView.sliderHandlersManager.thresholdMaxError:has-error"}}>
+ {{view Ember.TextField class="form-control" valueBinding="view.parentView.sliderHandlersManager.thresholdMax"}}
+ {{#if view.parentView.sliderHandlersManager.thresholdMaxError}}
+ <span class="help-block validation-block">{{view.parentView.sliderHandlersManager.thresholdMaxErrorMessage}}</span>
{{/if}}
</div>
<div id="slider-value4" class="value-on-slider col-md-2">
- {{view Em.TextField valueBinding="view.configPropertyObj.maxValue" classNames="form-control" disabled="disabled"}}
+ {{view Em.TextField valueBinding="view.parentView.sliderHandlersManager.maxValue" classNames="form-control" disabled="disabled"}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs b/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs
index 86ffb47..416852e 100644
--- a/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs
+++ b/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs
@@ -19,7 +19,7 @@
<form class="form-horizontal" autocomplete="off">
<div class="each-row">
<div class="alert alert-info">
- {{{view.configPropertyObj.hintInfo}}}
+ {{{view.parentView.widgetView.hintInfo}}}
</div>
</div>
@@ -33,14 +33,14 @@
<div id="slider-value1" class="value-on-slider col-md-2">
<input type="text" value="0" disabled="disabled" class="form-control" />
</div>
- <div id="slider-value2" {{bindAttr class="view.configPropertyObj.isThresh1Error:slider-error :value-on-slider :col-md-4 :col-md-offset-2 :col-sm-offset-2 view.configPropertyObj.isThresh1Error:has-error"}}>
- {{view Ember.TextField valueBinding="view.configPropertyObj.thresholdMin" class="form-control"}}
- {{#if view.configPropertyObj.errorMessage1}}
- <span class="help-block validation-block">{{view.configPropertyObj.errorMessage1}}</span>
+ <div id="slider-value2" {{bindAttr class="view.parentView.sliderHandlersManager.thresholdMinError:slider-error :value-on-slider :col-md-4 :col-md-offset-2 :col-sm-offset-2 view.parentView.sliderHandlersManager.thresholdMinError:has-error"}}>
+ {{view Ember.TextField valueBinding="view.parentView.sliderHandlersManager.thresholdMin" class="form-control"}}
+ {{#if view.parentView.sliderHandlersManager.thresholdMinErrorMessage}}
+ <span class="help-block validation-block">{{view.parentView.sliderHandlersManager.thresholdMinErrorMessage}}</span>
{{/if}}
</div>
<div id="slider-value3" class="value-on-slider col-md-2 col-md-offset-2 col-sm-offset-2">
- {{view Em.TextField valueBinding="view.configPropertyObj.maxValue" classNames="form-control" disabled="disabled"}}
+ {{view Em.TextField valueBinding="view.parentView.sliderHandlersManager.maxValue" classNames="form-control" disabled="disabled"}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 77b5d5a..6972d2a 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -33,6 +33,7 @@ require('views/common/chart/linear');
require('views/common/chart/linear_time');
require('views/common/modal_popup');
require('views/common/modal_popups/alert_popup');
+require('views/common/modal_popups/edit_dashboard_widget_popup');
require('views/common/modal_popups/manage_kdc_credentials_popup');
require('views/common/modal_popups/confirmation_feedback_popup');
require('views/common/modal_popups/confirmation_popup');
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/views/common/modal_popups/edit_dashboard_widget_popup.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/modal_popups/edit_dashboard_widget_popup.js b/ambari-web/app/views/common/modal_popups/edit_dashboard_widget_popup.js
new file mode 100644
index 0000000..7ea1b32
--- /dev/null
+++ b/ambari-web/app/views/common/modal_popups/edit_dashboard_widget_popup.js
@@ -0,0 +1,436 @@
+/**
+ * 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');
+const {isValidFloat} = require('utils/validator');
+
+/**
+ * Thresholds manager for sliders with single value
+ * Usage:
+ * <pre>
+ * SingleHandler.create({
+ * thresholdMin: 12,
+ * minValue: 10,
+ * maxValue: 100
+ * });
+ * </pre>
+ *
+ * @class SingleHandler
+ */
+const SingleHandler = Em.Object.extend({
+
+ /**
+ * @type {number}
+ */
+ thresholdMin: null,
+
+ /**
+ * @type {number}
+ * @default 0
+ */
+ minValue: 0,
+
+ /**
+ * @type {number}
+ */
+ maxValue: null,
+
+ /**
+ * Is <code>thresholdMin</code> invalid
+ * true - invalid
+ * false - valid
+ *
+ * @type {boolean}
+ */
+ thresholdMinError: Em.computed.bool('thresholdMinErrorMessage'),
+
+ /**
+ * Alias for <code>thresholdMinError</code>
+ *
+ * @type {boolean}
+ */
+ hasErrors: Em.computed.alias('thresholdMinError'),
+
+ /**
+ * Error message for <code>thresholdMin</code>
+ * <ul>
+ * <li>Value is not a number</li>
+ * <li>Value is out of range <code>(minValue - maxValue)</code></li>
+ * </ul>
+ * Empty message means that <code>thresholdMin</code> has valid value
+ *
+ * @type {string}
+ */
+ thresholdMinErrorMessage: function () {
+ var thresholdMin = this.get('thresholdMin');
+ var maxValue = this.get('maxValue');
+ var minValue = this.get('minValue');
+ if (!isValidFloat(thresholdMin) || thresholdMin > maxValue || thresholdMin < minValue) {
+ return Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+ }
+ return '';
+ }.property('thresholdMin', 'maxValue'),
+
+ /**
+ * Formatted threshold value
+ *
+ * @type {number[]}
+ */
+ preparedThresholds: function () {
+ return [parseFloat(this.get('thresholdMin'))];
+ }.property('thresholdMin'),
+
+ /**
+ * Force set new values for threshold
+ *
+ * @param {number[]} newValues
+ */
+ updateThresholds(newValues) {
+ this.set('thresholdMin', newValues[0]);
+ }
+
+});
+
+/**
+ * Thresholds manager for sliders with double values
+ * Usage:
+ * <pre>
+ * SingleHandler.create({
+ * thresholdMin: 12,
+ * thresholdMax: 40,
+ * minValue: 10,
+ * maxValue: 100
+ * });
+ * </pre>
+ *
+ * @class DoubleHandlers
+ */
+const DoubleHandlers = SingleHandler.extend({
+
+ /**
+ * @type {number}
+ */
+ thresholdMax: null,
+
+ /**
+ * Is <code>thresholdMax</code> invalid
+ * true - invalid
+ * false - valid
+ *
+ * @type {boolean}
+ */
+ thresholdMaxError: Em.computed.bool('thresholdMaxErrorMessage'),
+
+ /**
+ * Is some threshold invalid
+ * true - some one is invalid
+ * false - thresholds are valid
+ *
+ * @type {boolean}
+ */
+ hasErrors: Em.computed.or('thresholdMinError', 'thresholdMaxError'),
+
+ /**
+ * Error message for <code>thresholdMin</code>
+ * <ul>
+ * <li>Value is not a number</li>
+ * <li>Value is out of range <code>(minValue - maxValue)</code></li>
+ * <li><code>thresholdMin</code>-value greater than <code>thresholdMax</code>-value</li>
+ * </ul>
+ * Empty message means that <code>thresholdMin</code> has valid value
+ *
+ * @type {string}
+ */
+ thresholdMinErrorMessage: function () {
+ var thresholdMin = this.get('thresholdMin');
+ var thresholdMax = this.get('thresholdMax');
+ var maxValue = this.get('maxValue');
+ var minValue = this.get('minValue');
+ if (!isValidFloat(thresholdMin) || thresholdMin > maxValue || thresholdMin < minValue) {
+ return Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+ }
+ if (this.get('thresholdMaxError') === false && thresholdMax <= thresholdMin) {
+ return Em.I18n.t('dashboard.widgets.error.smaller');
+ }
+ return '';
+ }.property('thresholdMin', 'thresholdMax'),
+
+ /**
+ * Error message for <code>thresholdMax</code>
+ * <ul>
+ * <li>Value is not a number</li>
+ * <li>Value is out of range <code>(minValue - maxValue)</code></li>
+ * </ul>
+ * Empty message means that <code>thresholdMax</code> has valid value
+ *
+ * @type {string}
+ */
+ thresholdMaxErrorMessage: function () {
+ var thresholdMax = this.get('thresholdMax');
+ var maxValue = this.get('maxValue');
+ var minValue = this.get('minValue');
+ if (!isValidFloat(thresholdMax) || thresholdMax > maxValue || thresholdMax < minValue) {
+ return Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+ }
+ return '';
+ }.property('thresholdMax'),
+
+ /**
+ * Threshold values ready to save
+ *
+ * @type {number[]}
+ */
+ preparedThresholds: function () {
+ return [parseFloat(this.get('thresholdMin')), parseFloat(this.get('thresholdMax'))];
+ }.property('thresholdMin', 'thresholdMax'),
+
+ /**
+ * Force set new values for threshold
+ *
+ * @param {number[]} newValues
+ */
+ updateThresholds(newValues) {
+ this.set('thresholdMin', newValues[0]);
+ this.set('thresholdMax', newValues[1]);
+ }
+
+});
+
+/**
+ * Common body-view for popup with sliders
+ *
+ * @class EditDashboardWidgetPopupBody
+ */
+const EditDashboardWidgetPopupBody = Em.View.extend({
+ templateName: require('templates/main/dashboard/edit_widget_popup')
+});
+
+/**
+ * Popup with slider to edit dashboard widget
+ * Usage:
+ * <pre>
+ * App.EditDashboardWidgetPopup.show({
+ * widgetView: this,
+ * sliderHandlersManager: App.EditDashboardWidgetPopup.DoubleHandlers.create({
+ * maxValue: 100,
+ * thresholdMin: this.get('thresholdMin'),
+ * thresholdMax: this.get('thresholdMax')
+ * })
+ * });
+ * </pre>
+ *
+ * <code>widgetView</code> should be set to view with widget.
+ * Usually you will use <code>App.EditDashboardWidgetPopup</code> inside of some <code>App.DashboardWidgetView</code> instance,
+ * so <code>widgetView</code> may be set to <code>this</code>
+ * <code>sliderHandlersManager</code> should be set to some of the <code>App.EditDashboardWidgetPopup.SingleHandler</code>
+ * or <code>App.EditDashboardWidgetPopup.DoubleHandler</code>
+ *
+ * You can't use <code>App.EditDashboardWidgetPopup</code> without setting this two properties!
+ *
+ * @class App.EditDashboardWidgetPopup
+ */
+App.EditDashboardWidgetPopup = App.ModalPopup.extend({
+
+ header: Em.I18n.t('dashboard.widgets.popupHeader'),
+ classNames: ['modal-edit-widget'],
+ modalDialogClasses: ['modal-lg'],
+ primary: Em.I18n.t('common.apply'),
+ disablePrimary: Em.computed.alias('sliderHandlersManager.hasErrors'),
+
+ /**
+ * Can't be null or undefined
+ *
+ * @type {SingleHandler|DoubleHandlers}
+ */
+ sliderHandlersManager: null,
+
+ /**
+ * Widget view
+ * Can't be not a view. Used to save Thresholds. Normally it's an instance of <code>App.DashboardWidgetView</code>
+ *
+ * @type {Em.View}
+ */
+ widgetView: null,
+
+ /**
+ * Determines if slider is enabled for slide
+ * true - don't enabled
+ * false - enabled
+ *
+ * Determines if slider handlers should be updated with Threshold values
+ * true - don't update
+ * false - update
+ *
+ * Used as option <code>disabled</code> for $.ui.slider
+ *
+ * @type {boolean}
+ */
+ sliderDisabled: false,
+
+ /**
+ * Slider "ticks"
+ * Used as option <code>values</code> for $.ui.slider
+ *
+ * @type {number[]}
+ */
+ sliderHandlers: function () {
+ return this.get('sliderHandlersManager.preparedThresholds');
+ }.property('sliderHandlersManager.preparedThresholds.[]'),
+
+ /**
+ * Colors used for slider ranges
+ * @type {string[]}
+ */
+ sliderColors: [App.healthStatusRed, App.healthStatusOrange, App.healthStatusGreen],
+
+ /**
+ * Maximum value for slider
+ * Used as option <code>max</code> for $.ui.slider
+ *
+ * @type {number}
+ */
+ sliderMaxValue: Em.computed.alias('sliderHandlersManager.maxValue'),
+
+ /**
+ * Minimum value for slider
+ * Used as option <code>min</code> for $.ui.slider
+ *
+ * @type {number}
+ */
+ sliderMinValue: 0,
+
+ /**
+ * Check how many handlers has slider
+ * true - 2 handlers
+ * false - 1 handler
+ *
+ * Used as option <code>range</code> for $.ui.slider
+ *
+ * @type {boolean}
+ */
+ sliderIsRange: true,
+
+ bodyClass: EditDashboardWidgetPopupBody,
+
+ init() {
+ Em.assert('`widgetView` should be valid view', this.get('widgetView.isView'));
+ Em.assert('`sliderHandlersManager` should be set', !!this.get('sliderHandlersManager'));
+ return this._super(...arguments);
+ },
+
+ /**
+ * Save new threshold value on popup-close (means Primary click)
+ * Use <code>widgetView</code> to get <code>widgetsView</code> and save new values
+ * Current widget is updated too (without redrawing)
+ */
+ saveThreshold () {
+ let preparedThresholds = this.get('sliderHandlersManager.preparedThresholds');
+ this.get('widgetView').saveWidgetThresholds(preparedThresholds);
+ },
+
+ /**
+ * Update slider values when new threshold values are provided
+ * Don't do anything if some value is invalid or slider is disabled
+ *
+ * @private
+ */
+ _updateSliderValues: function() {
+ var sliderHandlersManager = this.get('sliderHandlersManager');
+ if (!sliderHandlersManager.get('hasErrors') && !this.get('sliderDisabled')) {
+ $('#slider-range').slider('values', sliderHandlersManager.get('preparedThresholds'));
+ }
+ }.observes('sliderDisabled', 'sliderHandlersManager.preparedThresholds.[]', 'sliderHandlersManager.hasErrors'),
+
+ onPrimary () {
+ let sliderHandlersManager = this.get('sliderHandlersManager');
+ if (!sliderHandlersManager.get('hasErrors')) {
+ this.saveThreshold();
+ this.hide();
+ }
+ },
+
+ /**
+ * Create slider in the popup when it's opened
+ */
+ createSlider() {
+ var self = this;
+ let sliderHandlersManager = this.get('sliderHandlersManager');
+ var handlers = this.get('sliderHandlers');
+
+ $('#slider-range').slider({
+ range: this.get('sliderIsRange'),
+ min: this.get('sliderMinValue'),
+ max: this.get('sliderMaxValue'),
+ disabled: this.get('sliderDisabled'),
+ values: handlers,
+ create: function () {
+ self.updateSliderColors(handlers);
+ },
+ slide: function (event, ui) {
+ self.updateSliderColors(ui.values);
+ sliderHandlersManager.updateThresholds(ui.values);
+ },
+ change: function (event, ui) {
+ self.updateSliderColors(ui.values);
+ }
+ });
+ },
+
+ didInsertElement: function () {
+ this._super();
+ this.createSlider();
+ },
+
+ /**
+ * Update colors on slider using <code>sliderColors</code> theme when user interacts with it
+ *
+ * @param {number[]} handlers
+ */
+ updateSliderColors(handlers) {
+ let gradient = this._getGradientStr(handlers);
+ $('#slider-range')
+ .css('background-image', '-webkit-' + gradient)
+ .css('background-image', '-ms-' + gradient)
+ .css('background-image', '-moz-' + gradient)
+ .find('.ui-widget-header').css({
+ 'background-color': App.healthStatusOrange,
+ 'background-image': 'none'
+ });
+ },
+
+ /**
+ * @param {number[]} handlers
+ * @returns {string}
+ * @private
+ */
+ _getGradientStr(handlers) {
+ let maxValue = this.get('sliderMaxValue');
+ let colors = this.get('sliderColors');
+ let gradient = colors[0] + ', ' + handlers.map((handler, i) => {
+ return `${colors[i]} ${handlers[i] * 100 / maxValue}%, ${colors[i + 1]} ${handlers[i] * 100 / maxValue}%,`;
+ }).join('') + colors[colors.length - 1];
+ return `linear-gradient(left,${gradient})`;
+ }
+
+});
+
+App.EditDashboardWidgetPopup.reopenClass({
+ SingleHandler,
+ DoubleHandlers,
+ EditDashboardWidgetPopupBody
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/views/main/dashboard/widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widget.js b/ambari-web/app/views/main/dashboard/widget.js
index e7a626c..9fba906 100644
--- a/ambari-web/app/views/main/dashboard/widget.js
+++ b/ambari-web/app/views/main/dashboard/widget.js
@@ -30,9 +30,19 @@ App.DashboardWidgetView = Em.View.extend({
sourceName: Em.computed.alias('widget.sourceName'),
+ /**
+ * Bound from template
+ *
+ * @type {object}
+ */
widget: null,
/**
+ * @type {Em.View}
+ */
+ widgetsView: Em.computed.alias('parentView'),
+
+ /**
* @type {object} - record from model that serve as data source
*/
model: function () {
@@ -79,6 +89,11 @@ App.DashboardWidgetView = Em.View.extend({
hiddenInfoClass: "hidden-info-two-line",
/**
+ * @type {string}
+ */
+ hintInfo: Em.computed.i18nFormat('dashboard.widgets.hintInfo.common', 'maxValue'),
+
+ /**
* @type {number}
* @default 0
*/
@@ -100,61 +115,6 @@ App.DashboardWidgetView = Em.View.extend({
*/
isDataLoadedBinding: 'App.router.clusterController.isServiceContentFullyLoaded',
- /**
- * @type {Em.Object}
- * @class
- */
- widgetConfig: Ember.Object.extend({
- thresholdMin: '',
- thresholdMax: '',
- hintInfo: Em.computed.i18nFormat('dashboard.widgets.hintInfo.common', 'maxValue'),
- thresholdMinError: false,
- thresholdMaxError: false,
- thresholdMinErrorMessage: "",
- thresholdMaxErrorMessage: "",
- maxValue: 0,
- validateThreshold: function(thresholdName) {
- var thresholdMin = this.get('thresholdMin'),
- thresholdMax = this.get('thresholdMax'),
- maxValue = this.get('maxValue'),
- currentThreshold = this.get(thresholdName),
- isError = false,
- errorMessage = '';
-
- if (currentThreshold.trim() !== "") {
- if (isNaN(currentThreshold) || currentThreshold > maxValue || currentThreshold < 0) {
- isError = true;
- errorMessage = Em.I18n.t('dashboard.widgets.error.invalid').format(maxValue);
- } else if (parseFloat(thresholdMax) <= parseFloat(thresholdMin)) {
- isError = true;
- errorMessage = Em.I18n.t('dashboard.widgets.error.smaller');
- } else {
- isError = false;
- errorMessage = '';
- }
- } else {
- isError = true;
- errorMessage = Em.I18n.t('admin.users.editError.requiredField');
- }
- this.set(thresholdName + 'ErrorMessage', errorMessage);
- this.set(thresholdName + 'Error', isError);
- this.updateSlider();
- },
- observeThreshMinValue: function () {
- this.validateThreshold('thresholdMin');
- }.observes('thresholdMin', 'maxValue'),
- observeThreshMaxValue: function () {
- this.validateThreshold('thresholdMax');
- }.observes('thresholdMax', 'maxValue'),
- updateSlider: function () {
- if (this.get('thresholdMinError') === false && this.get('thresholdMaxError') === false) {
- $("#slider-range")
- .slider('values', 0, parseFloat(this.get('thresholdMin')))
- .slider('values', 1, parseFloat(this.get('thresholdMax')));
- }
- }
- }),
-
didInsertElement: function () {
App.tooltip(this.$("[rel='ZoomInTooltip']"), {
placement: 'left',
@@ -190,97 +150,36 @@ App.DashboardWidgetView = Em.View.extend({
},
/**
- * edit widget
+ * Update thresholds for widget and save this them to persist
+ *
+ * @param {number[]} preparedThresholds
*/
- editWidget: function () {
- var configObj = this.get('widgetConfig').create({
- thresholdMin: this.get('thresholdMin') + '',
- thresholdMax: this.get('thresholdMax') + '',
- maxValue: parseFloat(this.get('maxValue'))
- });
- this.showEditDialog(configObj);
+ saveWidgetThresholds(preparedThresholds) {
+ const widgetsView = this.get('widgetsView');
+ const userPreferences = widgetsView.get('userPreferences');
+ const widgetId = Number(this.get('id'));
+ userPreferences.threshold[widgetId] = preparedThresholds;
+ this.set('widget.threshold', userPreferences.threshold[widgetId]);
+ widgetsView.saveWidgetsSettings(userPreferences);
},
/**
- * show edit dialog
- * @param {Em.Object} configObj
- * @returns {App.ModalPopup}
+ * edit widget
*/
- showEditDialog: function (configObj) {
- var self = this;
- var maxValue = this.get('maxValue');
-
- return App.ModalPopup.show({
- header: Em.I18n.t('dashboard.widgets.popupHeader'),
- classNames: ['modal-edit-widget'],
- modalDialogClasses: ['modal-lg'],
- bodyClass: Ember.View.extend({
- templateName: require('templates/main/dashboard/edit_widget_popup'),
- configPropertyObj: configObj
- }),
- configObj: configObj,
- disablePrimary: Em.computed.or('configObj.thresholdMinError', 'configObj.thresholdMaxError'),
- primary: Em.I18n.t('common.apply'),
- onPrimary: function () {
- configObj.observeThreshMinValue();
- configObj.observeThreshMaxValue();
- if (!configObj.thresholdMinError && !configObj.thresholdMaxError) {
- self.set('thresholdMin', parseFloat(configObj.get('thresholdMin')));
- self.set('thresholdMax', parseFloat(configObj.get('thresholdMax')));
-
- var parent = self.get('parentView');
- var userPreferences = parent.get('userPreferences');
- userPreferences.threshold[Number(self.get('id'))] = [configObj.get('thresholdMin'), configObj.get('thresholdMax')];
- parent.saveWidgetsSettings(userPreferences);
- parent.renderWidgets();
-
- this.hide();
- }
- },
+ editWidget: function () {
+ return App.EditDashboardWidgetPopup.show({
- didInsertElement: function () {
- this._super();
- var _this = this;
- var handlers = [configObj.get('thresholdMin'), configObj.get('thresholdMax')];
+ widgetView: this,
- $("#slider-range").slider({
- range: true,
- min: 0,
- max: maxValue,
- values: handlers,
- create: function () {
- _this.updateColors(handlers);
- },
- slide: function (event, ui) {
- _this.updateColors(ui.values);
- configObj.set('thresholdMin', ui.values[0] + '');
- configObj.set('thresholdMax', ui.values[1] + '');
- },
- change: function (event, ui) {
- _this.updateColors(ui.values);
- }
- });
- },
- updateColors: function (handlers) {
- var colors = [App.healthStatusGreen, App.healthStatusOrange, App.healthStatusRed];
- var colorStops = colors[0] + ", ";
+ sliderHandlersManager: App.EditDashboardWidgetPopup.DoubleHandlers.create({
+ thresholdMin: this.get('thresholdMin'),
+ thresholdMax: this.get('thresholdMax'),
+ maxValue: parseFloat(this.get('maxValue'))
+ }),
- for (var i = 0; i < handlers.length; i++) {
- colorStops += colors[i] + " " + handlers[i] * 100 / maxValue + "%,";
- colorStops += colors[i + 1] + " " + handlers[i] * 100 / maxValue + "%,";
- }
- colorStops += colors[colors.length - 1];
- var sliderElement = $('#slider-range');
- var gradient = 'linear-gradient(left,' + colorStops + ')';
+ sliderColors: [App.healthStatusGreen, App.healthStatusOrange, App.healthStatusRed]
- sliderElement.css('background-image', '-webkit-' + gradient);
- sliderElement.css('background-image', '-ms-' + gradient);
- sliderElement.css('background-image', '-moz-' + gradient);
- sliderElement.find('.ui-widget-header').css({
- 'background-color': '#FF8E00',
- 'background-image': 'none'
- });
- }
});
}
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/views/main/dashboard/widgets.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets.js b/ambari-web/app/views/main/dashboard/widgets.js
index 572625d..16840a5 100644
--- a/ambari-web/app/views/main/dashboard/widgets.js
+++ b/ambari-web/app/views/main/dashboard/widgets.js
@@ -32,184 +32,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
name: 'mainDashboardWidgetsView',
templateName: require('templates/main/dashboard/widgets'),
- widgetsDefinition: [
- {
- id: 1,
- viewName: 'NameNodeHeapPieChartView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.NameNodeHeap'),
- threshold: [80, 90]
- },
- {
- id: 2,
- viewName: 'NameNodeCapacityPieChartView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.HDFSDiskUsage'),
- threshold: [85, 95]
- },
- {
- id: 3,
- viewName: 'NameNodeCpuPieChartView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.NameNodeCpu'),
- threshold: [90, 95]
- },
- {
- id: 4,
- viewName: 'DataNodeUpView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.DataNodeUp'),
- threshold: [80, 90]
- },
- {
- id: 5,
- viewName: 'NameNodeRpcView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.NameNodeRpc'),
- threshold: [1000, 3000]
- },
- {
- id: 6,
- viewName: 'ChartClusterMetricsMemoryWidgetView',
- sourceName: 'HOST_METRICS',
- title: Em.I18n.t('dashboard.clusterMetrics.memory'),
- threshold: []
- },
- {
- id: 7,
- viewName: 'ChartClusterMetricsNetworkWidgetView',
- sourceName: 'HOST_METRICS',
- title: Em.I18n.t('dashboard.clusterMetrics.network'),
- threshold: []
- },
- {
- id: 8,
- viewName: 'ChartClusterMetricsCPUWidgetView',
- sourceName: 'HOST_METRICS',
- title: Em.I18n.t('dashboard.clusterMetrics.cpu'),
- threshold: []
- },
- {
- id: 9,
- viewName: 'ChartClusterMetricsLoadWidgetView',
- sourceName: 'HOST_METRICS',
- title: Em.I18n.t('dashboard.clusterMetrics.load'),
- threshold: []
- },
- {
- id: 10,
- viewName: 'NameNodeUptimeView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.NameNodeUptime'),
- threshold: []
- },
- {
- id: 11,
- viewName: 'HDFSLinksView',
- sourceName: 'HDFS',
- title: Em.I18n.t('dashboard.widgets.HDFSLinks'),
- threshold: []
- },
- {
- id: 12,
- viewName: 'HBaseLinksView',
- sourceName: 'HBASE',
- title: Em.I18n.t('dashboard.widgets.HBaseLinks'),
- threshold: []
- },
- {
- id: 13,
- viewName: 'HBaseMasterHeapPieChartView',
- sourceName: 'HBASE',
- title: Em.I18n.t('dashboard.widgets.HBaseMasterHeap'),
- threshold: [70, 90]
- },
- {
- id: 14,
- viewName: 'HBaseAverageLoadView',
- sourceName: 'HBASE',
- title: Em.I18n.t('dashboard.widgets.HBaseAverageLoad'),
- threshold: [150, 250]
- },
- {
- id: 15,
- viewName: 'HBaseRegionsInTransitionView',
- sourceName: 'HBASE',
- title: Em.I18n.t('dashboard.widgets.HBaseRegionsInTransition'),
- threshold: [3, 10],
- isHiddenByDefault: true
- },
- {
- id: 16,
- viewName: 'HBaseMasterUptimeView',
- sourceName: 'HBASE',
- title: Em.I18n.t('dashboard.widgets.HBaseMasterUptime'),
- threshold: []
- },
- {
- id: 17,
- viewName: 'ResourceManagerHeapPieChartView',
- sourceName: 'YARN',
- title: Em.I18n.t('dashboard.widgets.ResourceManagerHeap'),
- threshold: [70, 90]
- },
- {
- id: 18,
- viewName: 'ResourceManagerUptimeView',
- sourceName: 'YARN',
- title: Em.I18n.t('dashboard.widgets.ResourceManagerUptime'),
- threshold: []
- },
- {
- id: 19,
- viewName: 'NodeManagersLiveView',
- sourceName: 'YARN',
- title: Em.I18n.t('dashboard.widgets.NodeManagersLive'),
- threshold: [50, 75]
- },
- {
- id: 20,
- viewName: 'YARNMemoryPieChartView',
- sourceName: 'YARN',
- title: Em.I18n.t('dashboard.widgets.YARNMemory'),
- threshold: [50, 75]
- },
- {
- id: 21,
- viewName: 'SuperVisorUpView',
- sourceName: 'STORM',
- title: Em.I18n.t('dashboard.widgets.SuperVisorUp'),
- threshold: [85, 95]
- },
- {
- id: 22,
- viewName: 'FlumeAgentUpView',
- sourceName: 'FLUME',
- title: Em.I18n.t('dashboard.widgets.FlumeAgentUp'),
- threshold: [85, 95]
- },
- {
- id: 23,
- viewName: 'YARNLinksView',
- sourceName: 'YARN',
- title: Em.I18n.t('dashboard.widgets.YARNLinks'),
- threshold: []
- },
- {
- id: 24,
- viewName: 'HawqSegmentUpView',
- sourceName: 'HAWQ',
- title: Em.I18n.t('dashboard.widgets.HawqSegmentUp'),
- threshold: [75, 90]
- },
- {
- id: 25,
- viewName: 'PxfUpView',
- sourceName: 'PXF',
- title: Em.I18n.t('dashboard.widgets.PxfUp'),
- threshold: []
- }
- ],
+ widgetsDefinition: require('data/dashboard_widgets'),
widgetsDefinitionMap: function () {
return this.get('widgetsDefinition').toMapByProperty('id');
@@ -275,15 +98,13 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
userPreferences: null,
didInsertElement: function () {
- var self = this;
-
this._super();
- this.loadWidgetsSettings().complete(function() {
- self.checkServicesChange();
- self.renderWidgets();
- self.set('isDataLoaded', true);
+ this.loadWidgetsSettings().complete(() => {
+ this.checkServicesChange();
+ this.renderWidgets();
+ this.set('isDataLoaded', true);
App.loadTimer.finish('Dashboard Metrics Page');
- Em.run.next(self, 'makeSortable');
+ Em.run.next(this, 'makeSortable');
});
},
@@ -337,11 +158,10 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
resolveConfigDependencies: function(widgetsDefinition) {
var clusterEnv = App.router.get('clusterController.clusterEnv').properties;
- var yarnMemoryWidget = widgetsDefinition.findProperty('id', 20);
-
if (clusterEnv.hide_yarn_memory_widget === 'true') {
- yarnMemoryWidget.isHiddenByDefault = true;
+ widgetsDefinition.findProperty('id', 20).isHiddenByDefault = true;
}
+ return widgetsDefinition;
},
generateDefaultUserPreferences: function() {
@@ -353,14 +173,10 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
};
this.resolveConfigDependencies(widgetsDefinition);
-
widgetsDefinition.forEach(function(widget) {
if (App.Service.find(widget.sourceName).get('isLoaded') || widget.sourceName === 'HOST_METRICS') {
- if (widget.isHiddenByDefault) {
- preferences.hidden.push(widget.id);
- } else {
- preferences.visible.push(widget.id);
- }
+ let state = widget.isHiddenByDefault ? 'hidden' : 'visible';
+ preferences[state].push(widget.id);
}
preferences.threshold[widget.id] = widget.threshold;
});
@@ -421,18 +237,13 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
};
var isChanged = false;
- defaultPreferences.visible.forEach(function(id) {
- if (!userPreferences.visible.contains(id) && !userPreferences.hidden.contains(id)) {
- isChanged = true;
- newValue.visible.push(id);
- }
- });
-
- defaultPreferences.hidden.forEach(function(id) {
- if (!userPreferences.visible.contains(id) && !userPreferences.hidden.contains(id)) {
- isChanged = true;
- newValue.hidden.push(id);
- }
+ ['visible', 'hidden'].forEach(state => {
+ defaultPreferences[state].forEach(id => {
+ if (!userPreferences.visible.contains(id) && !userPreferences.hidden.contains(id)) {
+ isChanged = true;
+ newValue[state].push(id);
+ }
+ });
});
if (isChanged) {
this.saveWidgetsSettings(newValue);
@@ -443,15 +254,14 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
* Reset widgets visibility-status
*/
resetAllWidgets: function () {
- var self = this;
- App.showConfirmationPopup(function () {
- self.saveWidgetsSettings(self.generateDefaultUserPreferences());
- self.setProperties({
+ App.showConfirmationPopup(() => {
+ this.saveWidgetsSettings(this.generateDefaultUserPreferences());
+ this.setProperties({
currentTimeRangeIndex: 0,
customStartTime: null,
customEndTime: null
});
- self.renderWidgets();
+ this.renderWidgets();
});
},
@@ -469,23 +279,21 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
var widgetsArray = $('div[viewid]');
var userPreferences = self.get('userPreferences') || self.getDBProperty(self.get('persistKey'));
- var newValue = Em.Object.create({
+ var newValue = {
visible: [],
hidden: userPreferences.hidden,
threshold: userPreferences.threshold
+ };
+ newValue.visible = userPreferences.visible.map((item, index) => {
+ var viewID = widgetsArray.get(index).getAttribute('viewid');
+ return Number(viewID.split('-')[1]);
});
- var size = userPreferences.visible.length;
- for (var j = 0; j <= size - 1; j++) {
- var viewID = widgetsArray.get(j).getAttribute('viewid');
- var id = Number(viewID.split("-").get(1));
- newValue.visible.push(id);
- }
self.saveWidgetsSettings(newValue);
},
- activate: function (event, ui) {
+ activate: function () {
self.set('isMoving', true);
},
- deactivate: function (event, ui) {
+ deactivate: function () {
self.set('isMoving', false);
}
}).disableSelection();
@@ -511,21 +319,9 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap
}),
applyFilter: function () {
var parent = this.get('parentView'),
- hiddenWidgets = this.get('hiddenWidgets'),
- userPreferences = parent.get('userPreferences'),
- newValue = {
- visible: userPreferences.visible.slice(0),
- hidden: userPreferences.hidden.slice(0),
- threshold: userPreferences.threshold
- };
-
- hiddenWidgets.filterProperty('checked').forEach(function (item) {
- newValue.visible.push(item.id);
- newValue.hidden = newValue.hidden.without(item.id);
- hiddenWidgets.removeObject(item);
- }, this);
- parent.saveWidgetsSettings(newValue);
- parent.renderWidgets();
+ hiddenWidgets = this.get('hiddenWidgets');
+ hiddenWidgets.filterProperty('checked').setEach('isVisible', true);
+ parent.saveWidgetsSettings();
}
}),
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/app/views/main/dashboard/widgets/text_widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/text_widget.js b/ambari-web/app/views/main/dashboard/widgets/text_widget.js
index daa354c..79f0573 100644
--- a/ambari-web/app/views/main/dashboard/widgets/text_widget.js
+++ b/ambari-web/app/views/main/dashboard/widgets/text_widget.js
@@ -32,26 +32,5 @@ App.TextDashboardWidgetView = App.DashboardWidgetView.extend({
return this.get('data') === null;
}.property('data'),
- hiddenInfo: [],
-
- maxValue: null,
-
- updateColors: function (handlers, colors) {
- var colorstops = colors[0] + ", "; // start with the first color
- for (var i = 0; i < handlers.length; i++) {
- colorstops += colors[i] + " " + handlers[i] + "%,";
- colorstops += colors[i + 1] + " " + handlers[i] + "%,";
- }
- colorstops += colors[colors.length - 1];
- var cssForChromeAndSafari = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
- var slider = $('#slider-range');
- slider.css('background-image', cssForChromeAndSafari);
- var cssForIE = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
- slider.css('background-image', cssForIE);
- //$('#slider-range').css('filter', 'progid:DXImageTransform.Microsoft.gradient( startColorStr= ' + colors[0] + ', endColorStr= ' + colors[2] +', GradientType=1 )' ); // IE 10-
- var cssForFireFox = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
- slider.css('background-image', cssForFireFox);
-
- slider.find('.ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the original ranger color
- }
+ hiddenInfo: []
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/test/views/common/modal_popups/edit_dashboard_widget_popup_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/modal_popups/edit_dashboard_widget_popup_test.js b/ambari-web/test/views/common/modal_popups/edit_dashboard_widget_popup_test.js
new file mode 100644
index 0000000..3335cf3
--- /dev/null
+++ b/ambari-web/test/views/common/modal_popups/edit_dashboard_widget_popup_test.js
@@ -0,0 +1,214 @@
+/**
+ * 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');
+
+function getView() {
+ return App.EditDashboardWidgetPopup.create({
+ widgetView: Em.View.create(),
+ sliderHandlersManager: {}
+ });
+}
+
+describe('App.EditDashboardWidgetPopup', function () {
+
+ App.TestAliases.testAsComputedAlias(getView(), 'disablePrimary', 'sliderHandlersManager.hasErrors');
+
+ App.TestAliases.testAsComputedAlias(getView(), 'sliderMaxValue', 'sliderHandlersManager.maxValue');
+
+ describe('#init', function () {
+
+ it('should throw an Error if no `widgetView` provided', function () {
+ expect(function () {
+ App.EditDashboardWidgetPopup.create({
+ sliderHandlersManager: {}
+ });
+ }).to.throw(/`widgetView` should be valid view/);
+ });
+
+ it('should throw an Error if no `sliderHandlersManager` provided', function () {
+ expect(function () {
+ App.EditDashboardWidgetPopup.create({
+ widgetView: Em.View.create(),
+ });
+ }).to.throw(/`sliderHandlersManager` should be set/);
+ });
+
+ });
+
+});
+
+describe('App.EditDashboardWidgetPopup.SingleHandler', function () {
+
+ var handler;
+
+ function getSingleHandler() {
+ return App.EditDashboardWidgetPopup.SingleHandler.create();
+ }
+
+ beforeEach(function () {
+ handler = getSingleHandler();
+ });
+
+ App.TestAliases.testAsComputedAlias(getSingleHandler(), 'hasErrors', 'thresholdMinError');
+
+ describe('#updateThresholds', function () {
+
+ it('should update `thresholdMin`', function () {
+ handler.set('thresholdMin', -1);
+ handler.updateThresholds([100500]);
+ expect(handler.get('thresholdMin')).to.be.equal(100500);
+ });
+
+ });
+
+ describe('#thresholdMinErrorMessage', function() {
+
+ var minValue = 0;
+ var maxValue = 100;
+ var msg = Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+
+ beforeEach(function() {
+ handler.setProperties({
+ minValue: minValue,
+ maxValue: maxValue
+ });
+ });
+
+ [
+ {thresholdMin: -1, e: msg},
+ {thresholdMin: 101, e: msg},
+ {thresholdMin: 'abc', e: msg},
+ {thresholdMin: 60, e: ''}
+ ].forEach(function(test) {
+ it('thresholdMin: ' + JSON.stringify(test.thresholdMin), function () {
+ handler.set('thresholdMin', test.thresholdMin);
+ expect(handler.get('thresholdMinErrorMessage')).to.be.equal(test.e);
+ });
+ });
+
+ });
+
+ describe('#preparedThresholds', function () {
+
+ it('mapped to array threshold values', function () {
+ handler.setProperties({
+ thresholdMin: 1
+ });
+ expect(handler.get('preparedThresholds')).to.be.eql([1]);
+ });
+
+ });
+
+});
+
+describe('App.EditDashboardWidgetPopup.DoubleHandlers', function () {
+
+ var handler;
+
+ function getDoubleHandlers() {
+ return App.EditDashboardWidgetPopup.DoubleHandlers.create();
+ }
+
+ beforeEach(function () {
+ handler = getDoubleHandlers();
+ });
+
+ App.TestAliases.testAsComputedOr(getDoubleHandlers(), 'hasErrors', ['thresholdMinError', 'thresholdMaxError']);
+
+ describe('#updateThresholds', function () {
+
+ it('should update `thresholdMin` and `thresholdMax`', function () {
+ handler.set('thresholdMin', -1);
+ handler.set('thresholdMax', 1);
+ handler.updateThresholds([1234, 4321]);
+ expect(handler.get('thresholdMin')).to.be.equal(1234);
+ expect(handler.get('thresholdMax')).to.be.equal(4321);
+ });
+
+ });
+
+ describe('#thresholdMinErrorMessage', function() {
+
+ var minValue = 0;
+ var maxValue = 100;
+ var msg = Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+ var msg2 = Em.I18n.t('dashboard.widgets.error.smaller');
+
+ beforeEach(function() {
+ handler.setProperties({
+ minValue: minValue,
+ maxValue: maxValue
+ });
+ });
+
+ [
+ {thresholdMin: -1, e: msg},
+ {thresholdMin: 101, e: msg},
+ {thresholdMin: 'abc', e: msg},
+ {thresholdMin: 60, e: ''},
+ {thresholdMin: 99, e: msg2}
+ ].forEach(function(test) {
+ it('thresholdMin: ' + JSON.stringify(test.thresholdMin), function () {
+ handler.set('thresholdMin', test.thresholdMin);
+ handler.set('thresholdMax', 98);
+ expect(handler.get('thresholdMinErrorMessage')).to.be.equal(test.e);
+ });
+ });
+
+ });
+
+ describe('#thresholdMaxErrorMessage', function () {
+ var minValue = 0;
+ var maxValue = 100;
+ var msg = Em.I18n.t('dashboard.widgets.error.invalid').format(minValue, maxValue);
+
+ beforeEach(function() {
+ handler.setProperties({
+ minValue: minValue,
+ maxValue: maxValue
+ });
+ });
+
+ [
+ {thresholdMax: -1, e: msg},
+ {thresholdMax: 101, e: msg},
+ {thresholdMax: 'abc', e: msg},
+ {thresholdMax: 60, e: ''}
+ ].forEach(function(test) {
+ it('thresholdMax: ' + JSON.stringify(test.thresholdMax), function () {
+ handler.set('thresholdMax', test.thresholdMax);
+ expect(handler.get('thresholdMaxErrorMessage')).to.be.equal(test.e);
+ });
+ });
+ });
+
+ describe('#preparedThresholds', function () {
+
+ it('mapped to array threshold values', function () {
+ handler.setProperties({
+ thresholdMin: 1,
+ thresholdMax: 2
+ });
+ expect(handler.get('preparedThresholds')).to.be.eql([1, 2]);
+ });
+
+ });
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/test/views/main/dashboard/widget_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/widget_test.js b/ambari-web/test/views/main/dashboard/widget_test.js
index a504c6d..8e10cef 100644
--- a/ambari-web/test/views/main/dashboard/widget_test.js
+++ b/ambari-web/test/views/main/dashboard/widget_test.js
@@ -89,97 +89,6 @@ describe('App.DashboardWidgetView', function () {
});
});
- describe('#widgetConfig', function () {
- var widgetConfig;
-
- beforeEach(function() {
- widgetConfig = view.get('widgetConfig').create();
- });
-
- describe('#validateThreshold()', function () {
-
- beforeEach(function () {
- sinon.stub(widgetConfig, 'updateSlider');
- });
-
- afterEach(function () {
- widgetConfig.updateSlider.restore();
- });
-
- it('updateSlider should be called', function () {
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.updateSlider).to.be.called;
- });
-
- it('thresholdMin is empty', function () {
- widgetConfig.set('thresholdMin', '');
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.get('thresholdMinError')).to.be.true;
- expect(widgetConfig.get('thresholdMinErrorMessage')).to.be.equal(Em.I18n.t('admin.users.editError.requiredField'));
- });
-
- it('thresholdMin is NaN', function () {
- widgetConfig.set('thresholdMin', 'a');
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.get('thresholdMinError')).to.be.true;
- expect(widgetConfig.get('thresholdMinErrorMessage')).to.be.equal(Em.I18n.t('dashboard.widgets.error.invalid').format(0));
- });
-
- it('thresholdMin bigger than maxValue', function () {
- widgetConfig.set('thresholdMin', '1');
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.get('thresholdMinError')).to.be.true;
- expect(widgetConfig.get('thresholdMinErrorMessage')).to.be.equal(Em.I18n.t('dashboard.widgets.error.invalid').format(0));
- });
-
- it('thresholdMin less than 0', function () {
- widgetConfig.set('thresholdMin', '-1');
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.get('thresholdMinError')).to.be.true;
- expect(widgetConfig.get('thresholdMinErrorMessage')).to.be.equal(Em.I18n.t('dashboard.widgets.error.invalid').format(0));
- });
-
- it('thresholdMin bigger than thresholdMax', function () {
- widgetConfig.set('thresholdMin', '2');
- widgetConfig.set('thresholdMax', '1');
- widgetConfig.set('maxValue', 100);
- widgetConfig.validateThreshold('thresholdMin');
- expect(widgetConfig.get('thresholdMinError')).to.be.true;
- expect(widgetConfig.get('thresholdMinErrorMessage')).to.be.equal(Em.I18n.t('dashboard.widgets.error.smaller'));
- });
- });
-
- describe('#observeThreshMinValue()', function() {
-
- beforeEach(function() {
- sinon.stub(widgetConfig, 'validateThreshold');
- });
- afterEach(function() {
- widgetConfig.validateThreshold.restore();
- });
-
- it('validateThreshold should be called', function() {
- widgetConfig.observeThreshMinValue();
- expect(widgetConfig.validateThreshold.calledWith('thresholdMin')).to.be.true;
- });
- });
-
- describe('#observeThreshMaxValue()', function() {
-
- beforeEach(function() {
- sinon.stub(widgetConfig, 'validateThreshold');
- });
- afterEach(function() {
- widgetConfig.validateThreshold.restore();
- });
-
- it('validateThreshold should be called', function() {
- widgetConfig.observeThreshMaxValue();
- expect(widgetConfig.validateThreshold.calledWith('thresholdMax')).to.be.true;
- });
- });
- });
-
describe('#didInsertElement()', function() {
beforeEach(function() {
@@ -250,25 +159,6 @@ describe('App.DashboardWidgetView', function () {
describe('#editWidget()', function() {
beforeEach(function() {
- sinon.stub(view, 'showEditDialog');
- });
-
- afterEach(function() {
- view.showEditDialog.restore();
- });
-
- it('showEditDialog should be called', function() {
- view.reopen({
- widgetConfig: Em.Object.extend()
- });
- view.editWidget();
- expect(view.showEditDialog).to.be.calledOnce;
- });
- });
-
- describe('#showEditDialog()', function() {
-
- beforeEach(function() {
sinon.stub(App.ModalPopup, 'show');
});
@@ -277,7 +167,7 @@ describe('App.DashboardWidgetView', function () {
});
it('App.ModalPopup.show should be called', function() {
- view.showEditDialog();
+ view.editWidget();
expect(App.ModalPopup.show).to.be.calledOnce;
});
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/05c76ed6/ambari-web/test/views/main/dashboard/widgets_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/widgets_test.js b/ambari-web/test/views/main/dashboard/widgets_test.js
index 5d1ddb2..4700ac8 100644
--- a/ambari-web/test/views/main/dashboard/widgets_test.js
+++ b/ambari-web/test/views/main/dashboard/widgets_test.js
@@ -426,15 +426,7 @@ describe('App.MainDashboardWidgetsView', function () {
});
it('saveWidgetsSettings should be called', function() {
- expect(plusButtonFilterView.get('parentView').saveWidgetsSettings.getCall(0).args[0]).to.be.eql({
- visible: [2, 1],
- hidden: [3],
- threshold: {}
- });
- });
-
- it('renderWidgets should be called', function() {
- expect(plusButtonFilterView.get('parentView').renderWidgets).to.be.calledOnce;
+ expect(plusButtonFilterView.get('parentView').saveWidgetsSettings.calledOnce).to.be.true;
});
});
});