You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by xi...@apache.org on 2015/04/03 03:09:09 UTC
ambari git commit: AMBARI-10338. Create Widget wizard: Show threshold
and unit field for a widget type.(xiwang)
Repository: ambari
Updated Branches:
refs/heads/trunk 6d0eb71da -> ff4598373
AMBARI-10338. Create Widget wizard: Show threshold and unit field for a widget type.(xiwang)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ff459837
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ff459837
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ff459837
Branch: refs/heads/trunk
Commit: ff45983735c5346635af876233c9a02fcd8d247f
Parents: 6d0eb71
Author: Xi Wang <xi...@apache.org>
Authored: Thu Apr 2 15:30:20 2015 -0700
Committer: Xi Wang <xi...@apache.org>
Committed: Thu Apr 2 17:35:19 2015 -0700
----------------------------------------------------------------------
.../service/widgets/create/step2_controller.js | 112 ++++++++-
ambari-web/app/models.js | 1 +
ambari-web/app/models/widget.js | 10 +
ambari-web/app/models/widget_property.js | 249 +++++++++++++++++++
.../app/styles/enhanced_service_dashboard.less | 26 ++
.../main/service/widgets/create/step2.hbs | 16 ++
.../create/widget_property_threshold.hbs | 32 +++
.../main/service/widgets/create/step2_view.js | 18 ++
8 files changed, 461 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/controllers/main/service/widgets/create/step2_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/widgets/create/step2_controller.js b/ambari-web/app/controllers/main/service/widgets/create/step2_controller.js
index 2438a80..62d935a 100644
--- a/ambari-web/app/controllers/main/service/widgets/create/step2_controller.js
+++ b/ambari-web/app/controllers/main/service/widgets/create/step2_controller.js
@@ -21,14 +21,120 @@ var App = require('app');
App.WidgetWizardStep2Controller = Em.Controller.extend({
name: "widgetWizardStep2Controller",
+ widgetProperties: [],
+ widgetMetrics: {},
+ widgetValues: {},
//TODO: Following computed property needs to be implemented. Next button should be enabled when there is no validation error and all required fields are filled
- isSubmitDisabled: function() {
- return false;
- }.property(''),
+ isSubmitDisabled: function () {
+ return this.get('widgetProperties').someProperty('isValid', false);
+ }.property('widgetProperties.@each.isValid'),
+ /*
+ * Generate the thresholds, unit, time range.etc object based on the widget type selected in previous step.
+ */
+ renderProperties: function () {
+ var widgetType = this.get('content.widgetType');
+ this.set("widgetProperties", {});
+ var widgetProperties = App.WidgetType.find().findProperty('name', widgetType).get('properties');
+ var properties = [];
+ switch (widgetType) {
+ case 'GAUGE':
+ properties = this.renderGaugeProperties(widgetProperties);
+ break;
+ case 'NUMBER':
+ properties = this.renderNumberProperties(widgetProperties);
+ break;
+ case 'GRAPH':
+ properties = this.renderGraphProperties(widgetProperties);
+ break;
+ case 'TEMPLATE':
+ properties = this.renderTemplateProperties(widgetProperties);
+ break;
+ default:
+ console.error('Incorrect Widget Type: ', widgetType);
+ }
+ this.set('widgetProperties', properties);
+ },
+
+ /**
+ * Render properties for gauge-type widget
+ * @method renderGaugeProperties
+ * @returns {App.WidgetProperties[]}
+ */
+ renderGaugeProperties: function (widgetProperties) {
+ var result = [];
+ result = result.concat([
+ App.WidgetProperties.Thresholds.PercentageThreshold.create({
+ smallValue: '0.7',
+ bigValue: '0.9',
+ isRequired: true
+ })
+ ]);
+ return result;
+ },
+
+ /**
+ * Render properties for number-type widget
+ * @method renderNumberProperties
+ * @returns {App.WidgetProperties[]}
+ */
+ renderNumberProperties: function (widgetProperties) {
+ var result = [];
+
+ result = result.concat([
+ App.WidgetProperties.Threshold.create({
+ smallValue: '10',
+ bigValue: '20',
+ isRequired: false
+ }),
+ App.WidgetProperties.Unit.create({
+ value: 'MB',
+ isRequired: false
+ })
+ ]);
+ return result;
+ },
+ /**
+ * Render properties for template-type widget
+ * @method renderTemplateProperties
+ * @returns {App.WidgetProperties[]}
+ */
+ renderTemplateProperties: function (widgetProperties) {
+ var result = [];
+ result = result.concat([
+ App.WidgetProperties.Unit.create({
+ value: 'MB',
+ isRequired: false
+ })
+ ]);
+ return result;
+ },
+ /**
+ * Render properties for graph-type widget
+ * @method renderGraphProperties
+ * @returns {App.WidgetProperties[]}
+ */
+ renderGraphProperties: function (widgetProperties) {
+ var result = [];
+ result = result.concat([
+ App.WidgetProperties.GraphType.create({
+ value: 'LINE',
+ isRequired: true
+ }),
+ App.WidgetProperties.TimeRange.create({
+ value: 'Last 1 hour',
+ isRequired: true
+ }),
+ App.WidgetProperties.Unit.create({
+ value: 'MB',
+ isRequired: false
+ })
+ ]);
+ return result;
+ },
next: function () {
if (!this.get('isSubmitDisabled')) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/models.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models.js b/ambari-web/app/models.js
index e9de30f..f4e881e 100644
--- a/ambari-web/app/models.js
+++ b/ambari-web/app/models.js
@@ -69,4 +69,5 @@ require('models/configs/tab');
require('models/configs/section');
require('models/configs/sub_section');
require('models/widget');
+require('models/widget_property');
require('models/widget_layout');
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/models/widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/widget.js b/ambari-web/app/models/widget.js
index 88a80e3..6147bf5 100644
--- a/ambari-web/app/models/widget.js
+++ b/ambari-web/app/models/widget.js
@@ -132,6 +132,11 @@ App.WidgetType.FIXTURES = [
{
property_name : 'time_range',
isRequired: true
+ },
+ {
+ property_name : 'display_unit',
+ display_name: 'unit',
+ isRequired: false
}
]
},
@@ -141,6 +146,11 @@ App.WidgetType.FIXTURES = [
display_name: 'Template',
description: Em.I18n.t('widget.type.template.description'),
properties: [
+ {
+ property_name : 'display_unit',
+ display_name: 'unit',
+ isRequired: false
+ }
]
}
];
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/models/widget_property.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/widget_property.js b/ambari-web/app/models/widget_property.js
new file mode 100644
index 0000000..5b2db2d
--- /dev/null
+++ b/ambari-web/app/models/widget_property.js
@@ -0,0 +1,249 @@
+/**
+ * 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');
+var validator = require('utils/validator');
+var numericUtils = require('utils/number_utils');
+
+App.WidgetProperty = Ember.Object.extend({
+
+ /**
+ * label to be shown for property
+ * @type {String}
+ */
+ label: '',
+
+ /**
+ * PORT|METRIC|AGGREGATE
+ * @type {String}
+ */
+ type: '',
+
+ /**
+ * config property value
+ * @type {*}
+ */
+ value: null,
+
+
+ /**
+ * input displayType
+ * one of 'textFields', 'textArea', 'select' or 'threshold'
+ * @type {String}
+ */
+ displayType: '',
+
+
+ /**
+ * space separated list of css class names to use
+ * @type {String}
+ */
+ classNames: '',
+
+ /**
+ * view class according to <code>displayType</code>
+ * @type {Em.View}
+ */
+ viewClass: function () {
+ var displayType = this.get('displayType');
+ switch (displayType) {
+ case 'textField':
+ return App.WidgetPropertyTextFieldView;
+ case 'threshold':
+ return App.WidgetPropertyThresholdView;
+ case 'select':
+ return App.WidgetPropertySelectView;
+ default:
+ console.error('Parsing Widget Property: Unable to find viewClass for displayType ', displayType);
+ }
+ }.property('displayType'),
+
+ /**
+ * Define whether property is valid
+ * Computed property
+ * Should be defined in child class
+ * @type {Boolean}
+ */
+ isValid: function () {
+ return true;
+ }.property(),
+
+ /**
+ * Define whether property is required by user
+ * @type {Boolean}
+ */
+ isRequired: true
+});
+
+App.WidgetProperties = {
+
+ WidgetName: App.WidgetProperty.extend({
+ name: 'widget_name',
+ label: 'Widget Name',
+ displayType: 'textField',
+ classNames: 'widget-property-text-input'
+ }),
+
+ Description: App.WidgetProperty.extend({
+ name: 'description',
+ label: 'Description',
+ displayType: 'textArea',
+ classNames: 'widget-property-text-area'
+ }),
+
+ Unit: App.WidgetProperty.extend({
+ name: 'display-unit',
+ label: 'Unit',
+ displayType: 'textField',
+ classNames: 'widget-property-unit',
+ isValid: function () {
+ return this.get('isRequired') ? this.get('value') : true;
+ }.property('value')
+ }),
+
+ GraphType: App.WidgetProperty.extend({
+ name: 'graph_type',
+ label: 'Graph Type',
+ displayType: 'select',
+ options: ["LINE", "STACK"]
+ }),
+
+ TimeRange: App.WidgetProperty.extend({
+ name: 'time_range',
+ label: 'Time Range',
+ displayType: 'select',
+ options: ["Last 1 hour", "Last 2 hours", "Last 4 hours", "Last 12 hours", "Last 24 hours",
+ "Last 1 week", "Last 1 month", "Last 1 year"]
+ }),
+
+
+ Threshold: App.WidgetProperty.extend({
+
+ name: 'threshold',
+ label: 'Thresholds',
+
+ /**
+ * threshold-value
+ * @type {string}
+ */
+ smallValue: '',
+ bigValue: '',
+ badgeOK: 'OK',
+ badgeWarning: 'WARNING',
+ badgeCritical: 'CRITICAL',
+
+ displayType: 'threshold',
+
+ classNames: 'widget-property-threshold',
+
+ apiProperty: [],
+
+ init: function () {
+ this._super();
+ },
+
+ /**
+ * Check if <code>smallValue</code> is valid float number
+ * @return {boolean}
+ */
+ isSmallValueValid: function () {
+ var value = this.get('smallValue');
+ if (!this.get('isRequired') && !this.get('smallValue') && !this.get('bigValue')) {
+ return true;
+ } else if (!this.get('smallValue')) {
+ return false;
+ }
+ value = ('' + value).trim();
+ return validator.isValidFloat(value) && value > 0;
+ }.property('smallValue', 'bigValue'),
+
+ /**
+ * Check if <code>bigValue</code> is valid float number
+ * @return {boolean}
+ */
+ isBigValueValid: function () {
+ var value = this.get('bigValue');
+ if (!this.get('isRequired') && !this.get('smallValue') && !this.get('bigValue')) {
+ return true;
+ } else if (!this.get('bigValue')) {
+ return false;
+ }
+ value = ('' + value).trim();
+ return validator.isValidFloat(value) && value > 0;
+ }.property('bigValue', 'smallValue'),
+
+ thresholdError: function () {
+ if (this.get('isSmallValueValid') && this.get('isBigValueValid')) {
+ return Number(this.get('smallValue')) > Number(this.get('bigValue'));
+ } else {
+ return false;
+ }
+ }.property('smallValue', 'bigValue', 'isSmallValueValid', 'isBigValueValid'),
+
+ isValid: function () {
+ return this.get('isSmallValueValid') && this.get('isBigValueValid') && (!this.get('thresholdError'));
+ }.property( 'isSmallValueValid', 'isBigValueValid', 'thresholdError'),
+
+ /**
+ * Define whether warning threshold < critical threshold
+ * @type {Boolean}
+ */
+ errorMsg: function () {
+ return this.get('thresholdError') ? "Threshold 1 should be smaller than threshold 2" : null;
+ }.property('thresholdError')
+
+ })
+};
+
+App.WidgetProperties.Thresholds = {
+
+ PercentageThreshold: App.WidgetProperties.Threshold.extend({
+
+ /**
+ * Check if <code>smallValue</code> is valid float number
+ * @return {boolean}
+ */
+ isSmallValueValid: function () {
+ var value = this.get('smallValue');
+ if (!this.get('isRequired') && !this.get('smallValue') && !this.get('bigValue')) {
+ return true;
+ } else if (!this.get('smallValue')) {
+ return false;
+ }
+ value = ('' + value).trim();
+ return validator.isValidFloat(value) && value > 0 && value <=1;
+ }.property('smallValue', 'bigValue'),
+
+ /**
+ * Check if <code>bigValue</code> is valid float number
+ * @return {boolean}
+ */
+ isBigValueValid: function () {
+ var value = this.get('bigValue');
+ if (!this.get('isRequired') && !this.get('smallValue') && !this.get('bigValue')) {
+ return true;
+ } else if (!this.get('bigValue')) {
+ return false;
+ }
+ value = ('' + value).trim();
+ return validator.isValidFloat(value) && value > 0 && value <= 1;
+ }.property('bigValue', 'smallValue')
+
+ })
+}
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/styles/enhanced_service_dashboard.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/enhanced_service_dashboard.less b/ambari-web/app/styles/enhanced_service_dashboard.less
index 24e52a3..e2acbe2 100644
--- a/ambari-web/app/styles/enhanced_service_dashboard.less
+++ b/ambari-web/app/styles/enhanced_service_dashboard.less
@@ -108,3 +108,29 @@
}
}
}
+
+#add-widget-step2 {
+ .badge-container {
+ height: 26px;
+ .OK, .WARNING, .CRITICAL {
+ line-height: 26px;
+ height: 26px;
+ display: inline-block;
+ width: 70px;
+ text-align: center;
+ }
+ .OK {
+ background-color: @health-status-green;
+ }
+ .WARNING {
+ background-color: @health-status-orange;
+ }
+ .CRITICAL {
+ background-color: @health-status-red;
+ }
+ }
+ .icon-asterisk {
+ color: red;
+ font-size: 8px;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/templates/main/service/widgets/create/step2.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/service/widgets/create/step2.hbs b/ambari-web/app/templates/main/service/widgets/create/step2.hbs
index 50f7b86..8ab4c03 100644
--- a/ambari-web/app/templates/main/service/widgets/create/step2.hbs
+++ b/ambari-web/app/templates/main/service/widgets/create/step2.hbs
@@ -25,6 +25,22 @@
</div>
</div>
+ <div>
+ <form class="form-horizontal">
+ {{#each property in controller.widgetProperties}}
+ <div {{bindAttr class=":control-group property.name property.isValid::error"}}>
+ <label class="control-label">{{property.label}}
+ {{#if property.isRequired }}
+ <i class="icon-asterisk"></i>
+ {{/if}}
+ </label>
+ <div class="controls">
+ {{view property.viewClass propertyBinding="property"}}
+ </div>
+ </div>
+ {{/each}}
+ </form>
+ </div>
<div class="btn-area">
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/templates/main/service/widgets/create/widget_property_threshold.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/service/widgets/create/widget_property_threshold.hbs b/ambari-web/app/templates/main/service/widgets/create/widget_property_threshold.hbs
new file mode 100644
index 0000000..ac8b194
--- /dev/null
+++ b/ambari-web/app/templates/main/service/widgets/create/widget_property_threshold.hbs
@@ -0,0 +1,32 @@
+{{!
+* 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.
+}}
+
+<div>
+ <div class="span2 badge-container"><span {{bindAttr class=":label view.property.badgeOK"}}>{{view.property.badgeOK}}</span> </div>
+ <div {{bindAttr class=":span2 property.isSmallValueValid::error"}}>
+ {{view Em.TextField valueBinding="view.property.smallValue" class ="span10"}}
+ </div>
+ <div class="span2 badge-container"><span {{bindAttr class=":label view.property.badgeWarning"}}>{{view.property.badgeWarning}}</span> </div>
+ <div {{bindAttr class=":span2 property.isBigValueValid::error"}}>
+ {{view Em.TextField valueBinding="view.property.bigValue" class ="span10"}}
+ </div>
+ <div class="span3 badge-container"><span {{bindAttr class=":label view.property.badgeCritical"}}>{{view.property.badgeCritical}}</span> </div>
+ <div {{bindAttr class="property.threshold:error"}}>
+ {{view.property.errorMsg}}
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/ff459837/ambari-web/app/views/main/service/widgets/create/step2_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/widgets/create/step2_view.js b/ambari-web/app/views/main/service/widgets/create/step2_view.js
index 610e98c..4bbcd44 100644
--- a/ambari-web/app/views/main/service/widgets/create/step2_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/step2_view.js
@@ -22,8 +22,26 @@ App.WidgetWizardStep2View = Em.View.extend({
didInsertElement: function () {
var controller = this.get('controller');
+ controller.renderProperties();
}
+});
+
+
+App.WidgetPropertyTextFieldView = Em.TextField.extend({
+ valueBinding: 'property.value',
+ classNameBindings: ['property.classNames', 'parentView.basicClass']
+});
+App.WidgetPropertyThresholdView = Em.View.extend({
+ templateName: require('templates/main/service/widgets/create/widget_property_threshold'),
+ classNameBindings: ['property.classNames', 'parentView.basicClass']
});
+App.WidgetPropertySelectView = Em.Select.extend({
+ selectionBinding: 'property.value',
+ contentBinding: 'property.options',
+ classNameBindings: ['property.classNames', 'parentView.basicClass']
+});
+
+