Repository: ambari Updated Branches: refs/heads/trunk 0b18f023b -> 4245645c3
AMBARI-16461: PXF Agents Live Widget on Dashboard needs custom widget to display only single threshold i.e., Green/Red only (Goutam Tadi via mithmatt) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/4245645c Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/4245645c Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/4245645c Branch: refs/heads/trunk Commit: 4245645c375e958ad90c3c34f322e46c35768375 Parents: 0b18f02 Author: Matt <[email protected]> Authored: Fri May 13 10:29:43 2016 -0700 Committer: Matt <[email protected]> Committed: Fri May 13 10:29:43 2016 -0700 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 1 + ambari-web/app/messages.js | 7 +- ambari-web/app/mixins.js | 1 + .../dashboard/widgets/editable_with_limit.js | 2 +- .../widgets/single_numeric_threshold.js | 156 +++++++++++++++++++ ambari-web/app/styles/modal_popups.less | 2 +- .../edit_widget_popup_single_threshold.hbs | 53 +++++++ ambari-web/app/views.js | 1 + ambari-web/app/views/main/dashboard/widgets.js | 3 +- .../views/main/dashboard/widgets/pxf_live.js | 11 +- .../widgets/text_widget_single_threshold.js | 37 +++++ .../test/aliases/computed/gtProperties.js | 2 +- .../text_widget_single_threshold_test.js | 57 +++++++ 13 files changed, 319 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/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 eb2edf1..9af4663 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -255,6 +255,7 @@ var files = [ 'test/views/main/dashboard/widget_test', 'test/views/main/dashboard/widgets_test', 'test/views/main/dashboard/widgets/text_widget_test', + 'test/views/main/dashboard/widgets/text_widget_single_threshold_test', 'test/views/main/dashboard/widgets/uptime_text_widget_test', 'test/views/main/dashboard/widgets/node_managers_live_test', 'test/views/main/dashboard/widgets/datanode_live_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 46c073b..c3b8a5c 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -1796,7 +1796,6 @@ Em.I18n.translations = { // Node Manager custom command to refresh YARN Apps on Slider 'services.service.actions.run.createYARNDirectories':'Create YARN Directories', 'services.service.actions.run.createYARNDirectories.confirmation':'Please confirm. This will create necessary folders on the NodeManagers required for running YARN Apps on Slider, such as LLAP. This does not need to restart NodeManagers.', - 'services.service.actions.run.immediateStopHawqService.context':'Stop HAWQ Service (Immediate Mode)', 'services.service.actions.run.immediateStopHawqService.label':'Stop HAWQ Service (Immediate Mode)', 'services.service.actions.run.immediateStopHawqSegment.label':'Stop (Immediate Mode)', @@ -2654,7 +2653,8 @@ Em.I18n.translations = { 'dashboard.widgets.error.invalid': 'Invalid! Enter a number between 0 - {0}', 'dashboard.widgets.error.smaller': 'Threshold 1 should be smaller than threshold 2!', 'dashboard.widgets.HawqSegmentUp': 'HAWQ Segments Live', - 'dashboard.widgets.PxfUp': 'PXFs Live', + 'dashboard.widgets.PxfUp': 'PXF Agents Live', + 'dashboard.widgets.PXFAgents': 'PXF Agents', 'dashboard': { 'widgets': { @@ -2663,7 +2663,8 @@ Em.I18n.translations = { 'common': 'Edit the percentage thresholds to change the color of current pie chart. <br />Enter two numbers between 0 to {0}', 'hint1': 'Edit the percentage of thresholds to change the color of current widget. <br />Assume all components UP is 100, and all DOWN is 0. <br /> So enter two numbers between 0 to {0}', 'hint2': 'Edit the thresholds to change the color of current widget.<br /><br />So enter two numbers larger than 0.', - 'hint3': 'Edit the thresholds to change the color of current widget.<br />The unit is milli-second. <br />So enter two numbers larger than 0. ' + 'hint3': 'Edit the thresholds to change the color of current widget.<br />The unit is milli-second. <br />So enter two numbers larger than 0. ', + 'hint4': 'Edit the threshold value representing the number of {0} that are down to change the color of the widget. <br />If the number of {0} that are down is greater than the threshold, the widget will show warning in Red. <br />Choose a number between 0 and {1}. ' } } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/mixins.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js index cf8cef6..05f2421 100644 --- a/ambari-web/app/mixins.js +++ b/ambari-web/app/mixins.js @@ -30,6 +30,7 @@ require('mixins/common/table_server_view_mixin'); require('mixins/common/table_server_mixin'); require('mixins/main/dashboard/widgets/editable'); require('mixins/main/dashboard/widgets/editable_with_limit'); +require('mixins/main/dashboard/widgets/single_numeric_threshold'); require('mixins/main/host/details/host_components/decommissionable'); require('mixins/main/host/details/host_components/install_component'); require('mixins/main/host/details/actions/install_new_version'); http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/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 97b6330..b10d386 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 @@ -136,4 +136,4 @@ App.EditableWithLimitWidgetMixin = Em.Mixin.create({ }); } -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/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 new file mode 100644 index 0000000..cbb81b3 --- /dev/null +++ b/ambari-web/app/mixins/main/dashboard/widgets/single_numeric_threshold.js @@ -0,0 +1,156 @@ +/** + * 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'); + +/** + * @type {Em.Mixin} + */ +App.SingleNumericThresholdMixin = Em.Mixin.create({ + + /** + * @type {Em.Object} + * @class + */ + widgetConfig: Ember.Object.extend({ + thresh1: '', + hintInfo: '', + isThresh1Error: false, + errorMessage1: "", + + maxValue: 0, + observeThresh1Value: function () { + var thresh1 = this.get('thresh1'); + var maxValue = this.get('maxValue'); + + if (thresh1.trim() !== "") { + if (isNaN(thresh1) || thresh1 > maxValue || thresh1 < 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('thresh1', 'maxValue'), + + updateSlider: function () { + var thresh1 = this.get('thresh1'); + // update the slider handles and color + if (this.get('isThresh1Error') === false) { + $("#slider-range") + .slider('values', 0, parseFloat(thresh1)) + } + } + }), + + /** + * edit widget + * @param {object} event + */ + editWidget: function () { + var parent = this; + var maxTmp = parseFloat(this.get('maxValue')); + var configObj = this.get('widgetConfig').create({ + thresh1: this.get('thresh1') + '', + hintInfo: this.get('hintInfo') + '', + maxValue: parseFloat(this.get('maxValue')) + }); + + var browserVersion = this.getInternetExplorerVersion(); + App.ModalPopup.show({ + header: Em.I18n.t('dashboard.widgets.popupHeader'), + classNames: ['sixty-percent-width-modal-edit-widget'], + 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) { + parent.set('thresh1', parseFloat(configObj.get('thresh1'))); + if (!App.get('testMode')) { + // save to persist + var bigParent = parent.get('parentView'); + bigParent.getUserPref(bigParent.get('persistKey')).complete(function () { + var oldValue = bigParent.get('currentPrefObject'); + oldValue.threshold[parseInt(parent.id, 10)] = [configObj.get('thresh1')]; + bigParent.postUserPref(parent.get('persistKey'), oldValue); + }); + } + this.hide(); + } + }, + didInsertElement: function () { + this._super(); + var handlers = [configObj.get('thresh1')]; + var colors = [App.healthStatusGreen, App.healthStatusRed]; //color green,red + + if (browserVersion === -1 || browserVersion > 9) { + configObj.set('isIE9', false); + configObj.set('isGreenRed', true); + $("#slider-range").slider({ + range: false, + min: 0, + max: maxTmp, + values: handlers, + create: function () { + updateColors(handlers); + }, + slide: function (event, ui) { + updateColors(ui.values); + configObj.set('thresh1', ui.values[0] + ''); + }, + change: function (event, ui) { + updateColors(ui.values); + } + }); + + function updateColors(handlers) { + 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); + + sliderElement.find('.ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the original ranger color + } + } else { + configObj.set('isIE9', true); + configObj.set('isGreenRed', true); + } + } + + }); + + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/styles/modal_popups.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/modal_popups.less b/ambari-web/app/styles/modal_popups.less index 5e89dbc..762ea46 100644 --- a/ambari-web/app/styles/modal_popups.less +++ b/ambari-web/app/styles/modal_popups.less @@ -618,4 +618,4 @@ } } } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/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 new file mode 100644 index 0000000..d83d048 --- /dev/null +++ b/ambari-web/app/templates/main/dashboard/edit_widget_popup_single_threshold.hbs @@ -0,0 +1,53 @@ +{{! +* 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. +}} + +<form class="form-horizontal" autocomplete="off"> + <div class="each-row"> + <div class="alert alert-info"> + {{{view.configPropertyObj.hintInfo}}} + </div> + </div> + + <div class="row-fluid" id= "min-height-limit"> + {{#if view.configPropertyObj.isIE9}} + {{#if view.configPropertyObj.isGreenRed}} + <div class="progress span9"> + <div class="bar bar-success" style="width: 33%;"></div> + <div class="bar bar-danger" style="width: 34%;"></div> + </div> + {{else}} + <div class="progress span9"> + <div class="bar bar-danger" style="width: 33%;"></div> + <div class="bar bar-success" style="width: 34%;"></div> + </div> + {{/if}} + {{else}} + <div class="span9" id="slider-range"></div> + {{/if}} + </div> + + <div class="row-fluid"> + <div id="slider-value1" class="value-on-slider span2" style="margin-left: 20px">0</div> + <div id="slider-value2" style="margin-left: 100px"{{bindAttr class="view.configPropertyObj.isThresh1Error:slider-error :value-on-slider :span4"}}> + {{view Ember.TextField valueBinding="view.configPropertyObj.thresh1"}} + <span class="help-inline">{{view.configPropertyObj.errorMessage1}}</span> + </div> + <div id="slider-value3" style="margin-left: 150px" class="value-on-slider span2">{{view.configPropertyObj.maxValue}}</div> + </div> + +</form> http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/views.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js index 127a996..35f3969 100644 --- a/ambari-web/app/views.js +++ b/ambari-web/app/views.js @@ -226,6 +226,7 @@ require('views/main/dashboard/cluster_metrics/network'); require('views/main/dashboard/widget'); require('views/main/dashboard/widgets'); require('views/main/dashboard/widgets/text_widget'); +require('views/main/dashboard/widgets/text_widget_single_threshold'); require('views/main/dashboard/widgets/uptime_text_widget'); require('views/main/dashboard/widgets/links_widget'); require('views/main/dashboard/widgets/pie_chart_widget'); http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/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 38181c0..48293d3 100644 --- a/ambari-web/app/views/main/dashboard/widgets.js +++ b/ambari-web/app/views/main/dashboard/widgets.js @@ -491,7 +491,7 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap visible: [], hidden: [], threshold: {1: [80, 90], 2: [85, 95], 3: [90, 95], 4: [80, 90], 5: [1000, 3000], 6: [], 7: [], 8: [], 9: [], 10: [], 11: [], 12: [], 13: [70, 90], 14: [150, 250], 15: [3, 10], 16: [], - 17: [70, 90], 18: [], 19: [50, 75], 20: [50, 75], 21: [85, 95], 22: [85, 95], 23: [], 24: [75, 90], 25: [75, 90]} // id:[thresh1, thresh2] + 17: [70, 90], 18: [], 19: [50, 75], 20: [50, 75], 21: [85, 95], 22: [85, 95], 23: [], 24: [75, 90], 25: []} // id:[thresh1, thresh2] }), /** @@ -540,4 +540,3 @@ App.MainDashboardWidgetsView = Em.View.extend(App.UserPref, App.LocalStorage, Ap showAlertsPopup: Em.K }); - http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/views/main/dashboard/widgets/pxf_live.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/dashboard/widgets/pxf_live.js b/ambari-web/app/views/main/dashboard/widgets/pxf_live.js index 75f5886..74b2096 100644 --- a/ambari-web/app/views/main/dashboard/widgets/pxf_live.js +++ b/ambari-web/app/views/main/dashboard/widgets/pxf_live.js @@ -29,7 +29,7 @@ function counterOrNA(key) { }); } -App.PxfUpView = App.TextDashboardWidgetView.extend(App.EditableWithLimitWidgetMixin, { +App.PxfUpView = App.TextDashboardSingleThresholdWidgetView.extend(App.SingleNumericThresholdMixin,{ title: Em.I18n.t('dashboard.widgets.PxfUp'), id: '25', @@ -46,9 +46,8 @@ App.PxfUpView = App.TextDashboardWidgetView.extend(App.EditableWithLimitWidgetMi hiddenInfoClass: "hidden-info-three-line", - thresh1: 75, - thresh2: 90, - maxValue: 100, + thresh1: 0, + maxValue: counterOrNA('pxfsTotal'), pxfsStarted: counterOrNA('pxfsStarted'), @@ -63,7 +62,7 @@ App.PxfUpView = App.TextDashboardWidgetView.extend(App.EditableWithLimitWidgetMi if (this.get('someMetricsNA')) { return null; } - return (this.get('pxfsStarted') / this.get('model.pxfsTotal')).toFixed(2) * 100; + return (this.get('pxfsTotal') - this.get('pxfsStarted') ); }.property('model.pxfsTotal', 'pxfsStarted', 'someMetricsNA'), /** @@ -78,7 +77,7 @@ App.PxfUpView = App.TextDashboardWidgetView.extend(App.EditableWithLimitWidgetMi hintInfo: function () { var maxTmp = parseFloat(this.get('maxValue')); - return Em.I18n.t('dashboard.widgets.hintInfo.hint1').format(maxTmp); + return Em.I18n.t('dashboard.widgets.hintInfo.hint4').format(Em.I18n.t('dashboard.widgets.PXFAgents'),maxTmp); }.property('maxValue'), /** http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/app/views/main/dashboard/widgets/text_widget_single_threshold.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/dashboard/widgets/text_widget_single_threshold.js b/ambari-web/app/views/main/dashboard/widgets/text_widget_single_threshold.js new file mode 100644 index 0000000..69c5821 --- /dev/null +++ b/ambari-web/app/views/main/dashboard/widgets/text_widget_single_threshold.js @@ -0,0 +1,37 @@ +/** + * 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'); + +App.TextDashboardSingleThresholdWidgetView = App.DashboardWidgetView.extend({ + + templateName: require('templates/main/dashboard/widgets/simple_text'), + + classNameBindings: ['isRed', 'isGreen', 'isNA'], + isGreen: Em.computed.lteProperties('data', 'thresh1'), + isRed: Em.computed.gtProperties('data', 'thresh1'), + + isNA: function () { + return this.get('data') === null; + }.property('data'), + + hiddenInfo: [], + + maxValue: null, + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/test/aliases/computed/gtProperties.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/aliases/computed/gtProperties.js b/ambari-web/test/aliases/computed/gtProperties.js index f3f1def..b3982b0 100644 --- a/ambari-web/test/aliases/computed/gtProperties.js +++ b/ambari-web/test/aliases/computed/gtProperties.js @@ -69,4 +69,4 @@ App.TestAliases.testAsComputedGtProperties = function (context, propertyName, de }); -}; \ No newline at end of file +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/4245645c/ambari-web/test/views/main/dashboard/widgets/text_widget_single_threshold_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/dashboard/widgets/text_widget_single_threshold_test.js b/ambari-web/test/views/main/dashboard/widgets/text_widget_single_threshold_test.js new file mode 100644 index 0000000..e564922 --- /dev/null +++ b/ambari-web/test/views/main/dashboard/widgets/text_widget_single_threshold_test.js @@ -0,0 +1,57 @@ +/** + * 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'); + +require('views/main/dashboard/widget'); +require('views/main/dashboard/widgets/text_widget_single_threshold'); + +function getView() { + return App.TextDashboardSingleThresholdWidgetView.create({thresh1:0}); +} + +describe('App.TextDashboardSingleThresholdWidgetView', function() { + + var tests = [ + { + data: 1, + e: { + isNA: false + } + }, + { + data: null, + e: { + isNA: true + } + } + ]; + + tests.forEach(function(test) { + describe('data - ' + test.data + ' | thresh1 - 0', function() { + var textDashboardWidgetSingleThresholdView = App.TextDashboardSingleThresholdWidgetView.create({thresh1:0}); + textDashboardWidgetSingleThresholdView.set('data', test.data); + it('isNA', function() { + expect(textDashboardWidgetSingleThresholdView.get('isNA')).to.equal(test.e.isNA); + }); + }); + }); + + App.TestAliases.testAsComputedGtProperties(getView(), 'isRed', 'data', 'thresh1'); + App.TestAliases.testAsComputedLteProperties(getView(), 'isGreen', 'data', 'thresh1'); +});
