You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2016/04/28 10:53:21 UTC
ambari git commit: AMBARI-15979 Provide UI validation for widget_name
and description fields in Create/Edit Widget pop-up. (Keta Patel via atkach)
Repository: ambari
Updated Branches:
refs/heads/trunk e74bfa4a4 -> 9bef76ba0
AMBARI-15979 Provide UI validation for widget_name and description fields in Create/Edit Widget pop-up. (Keta Patel via atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9bef76ba
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9bef76ba
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9bef76ba
Branch: refs/heads/trunk
Commit: 9bef76ba08fe190ad40d128cf317dce0df36f7f4
Parents: e74bfa4
Author: Andrii Tkach <at...@apache.org>
Authored: Thu Apr 28 11:53:07 2016 +0300
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Apr 28 11:53:07 2016 +0300
----------------------------------------------------------------------
.../service/widgets/create/step3_controller.js | 58 +++++++++++-
ambari-web/app/messages.js | 2 +
.../main/service/widgets/create/step3.hbs | 6 +-
ambari-web/app/utils/validator.js | 20 +++++
.../widgets/create/step3_controller_test.js | 92 +++++++++++++++++++-
5 files changed, 169 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bef76ba/ambari-web/app/controllers/main/service/widgets/create/step3_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/widgets/create/step3_controller.js b/ambari-web/app/controllers/main/service/widgets/create/step3_controller.js
index dd7a93f..eebe1f5 100644
--- a/ambari-web/app/controllers/main/service/widgets/create/step3_controller.js
+++ b/ambari-web/app/controllers/main/service/widgets/create/step3_controller.js
@@ -18,6 +18,8 @@
var App = require('app');
+var validator = require('utils/validator');
+
App.WidgetWizardStep3Controller = Em.Controller.extend({
name: "widgetWizardStep3Controller",
@@ -29,11 +31,26 @@ App.WidgetWizardStep3Controller = Em.Controller.extend({
widgetName: '',
/**
+ * @type {boolean}
+ */
+ isNameInvalid: false,
+
+ /**
* @type {string}
*/
widgetAuthor: '',
/**
+ * @type {string}
+ */
+ widgetNameErrorMessage: '',
+
+ /**
+ * @type {string}
+ */
+ descriptionErrorMessage: '',
+
+ /**
* @type {boolean}
*/
isSharedChecked: false,
@@ -54,6 +71,11 @@ App.WidgetWizardStep3Controller = Em.Controller.extend({
widgetDescription: '',
/**
+ * @type {boolean}
+ */
+ isDescriptionInvalid: false,
+
+ /**
* actual values of properties in API format
* @type {object}
*/
@@ -82,14 +104,42 @@ App.WidgetWizardStep3Controller = Em.Controller.extend({
isSubmitDisabled: Em.computed.or('widgetNameEmpty', 'isNameInvalid', 'isDescriptionInvalid'),
/**
- * @type {boolean}
+ * validates the name on 3rd step
*/
- isNameInvalid: Em.computed.gte('widgetName.length', 129),
+ validateName: function(){
+ var errorMessage='';
+ var widgetName = this.get('widgetName');
+ this.set("isNameInvalid",false);
+ if(widgetName && widgetName.length > 128){
+ errorMessage = Em.I18n.t("widget.create.wizard.step3.name.invalid.msg");
+ this.set("isNameInvalid",true);
+ }
+
+ if(widgetName && !validator.isValidWidgetName(widgetName)){
+ errorMessage = Em.I18n.t("widget.create.wizard.step3.name.invalidCharacter.msg");
+ this.set("isNameInvalid",true);
+ }
+ this.set('widgetNameErrorMessage',errorMessage);
+ }.observes('widgetName'),
/**
- * @type {boolean}
+ * validates the description on 3rd step
*/
- isDescriptionInvalid: Em.computed.gte('widgetDescription.length', 2049),
+ validateDescription: function(){
+ var errorMessage='';
+ var widgetDescription = this.get('widgetDescription');
+ this.set("isDescriptionInvalid",false);
+ if(widgetDescription && widgetDescription.length > 2048){
+ errorMessage = Em.I18n.t("widget.create.wizard.step3.description.invalid.msg");
+ this.set("isDescriptionInvalid",true);
+ }
+
+ if(widgetDescription && !validator.isValidWidgetDescription(widgetDescription)){
+ errorMessage = Em.I18n.t("widget.create.wizard.step3.description.invalidCharacter.msg");
+ this.set("isDescriptionInvalid",true);
+ }
+ this.set('descriptionErrorMessage',errorMessage);
+ }.observes('widgetDescription'),
/**
* restore widget data set on 2nd step
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bef76ba/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 8c8b9e5..eea0e2a 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -2844,7 +2844,9 @@ Em.I18n.translations = {
'widget.create.wizard.step3.sharing.msg': 'Share this widget in the widget library',
'widget.create.wizard.step3.header': 'Name and Description',
'widget.create.wizard.step3.name.invalid.msg': 'Widget name is too long. Please enter a widget name less than 129 characters.',
+ 'widget.create.wizard.step3.name.invalidCharacter.msg': 'Invalid widget name. Only alphanumerics, underscores, hyphens, percentage and spaces are allowed.',
'widget.create.wizard.step3.description.invalid.msg': 'Description is too long. Please enter a description less than 2049 characters.',
+ 'widget.create.wizard.step3.description.invalidCharacter.msg': 'Invalid input. Only alphanumerics, underscores, hyphens, percentage and spaces are allowed.',
'widget.edit.wizard.header': 'Edit Widget',
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bef76ba/ambari-web/app/templates/main/service/widgets/create/step3.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/service/widgets/create/step3.hbs b/ambari-web/app/templates/main/service/widgets/create/step3.hbs
index 9f431af..81177bc 100644
--- a/ambari-web/app/templates/main/service/widgets/create/step3.hbs
+++ b/ambari-web/app/templates/main/service/widgets/create/step3.hbs
@@ -25,7 +25,7 @@
<div {{bindAttr class=":span10 isNameInvalid:error"}}>
{{view Ember.TextField valueBinding="widgetName"}}
{{#if isNameInvalid}}
- <div>{{t widget.create.wizard.step3.name.invalid.msg}}</div>
+ <div>{{widgetNameErrorMessage}}</div>
{{/if}}
</div>
</div>
@@ -50,7 +50,7 @@
<div {{bindAttr class=":span10 isDescriptionInvalid:error"}}>
{{view Ember.TextArea valueBinding="widgetDescription" class="description-text-area"}}
{{#if isDescriptionInvalid}}
- <div>{{t widget.create.wizard.step3.description.invalid.msg}}</div>
+ <div>{{descriptionErrorMessage}}</div>
{{/if}}
</div>
</div>
@@ -62,4 +62,4 @@
<button id="add-widget-step3-save" class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action "complete" target="controller"}}>{{t common.save}}</button>
<button id="add-widget-step3-cancel" class="btn pull-right" {{action "cancel" target="controller"}}>{{t common.cancel}}</button>
</div>
-</div>
\ No newline at end of file
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bef76ba/ambari-web/app/utils/validator.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/validator.js b/ambari-web/app/utils/validator.js
index 490fec5..896228b 100644
--- a/ambari-web/app/utils/validator.js
+++ b/ambari-web/app/utils/validator.js
@@ -292,5 +292,25 @@ module.exports = {
var remotePattern = /^(?:(?:https?|ftp):\/{2})(?:\S+(?::\S*)?@)?(?:(?:(?:[\w\-.]))*)(?::[0-9]+)?(?:\/\S*)?$/,
localPattern = /^file:\/{2,3}([a-zA-Z][:|]\/){0,1}[\w~!*'();@&=\/\\\-+$,?%#.\[\]]+$/;
return remotePattern.test(value) || localPattern.test(value);
+ },
+
+ /**
+ * Validate widget name
+ * @param {string} value
+ * @returns {boolean}
+ */
+ isValidWidgetName: function(value) {
+ var widgetNameRegex = /^[\s0-9a-z_\-%]+$/i;
+ return widgetNameRegex.test(value);
+ },
+
+ /**
+ * Validate widget description
+ * @param {string} value
+ * @returns {boolean}
+ */
+ isValidWidgetDescription: function(value) {
+ var widgetDescriptionRegex = /^[\s0-9a-z_\-%]+$/i;
+ return widgetDescriptionRegex.test(value);
}
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bef76ba/ambari-web/test/controllers/main/service/widgets/create/step3_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/widgets/create/step3_controller_test.js b/ambari-web/test/controllers/main/service/widgets/create/step3_controller_test.js
index 6f92142..d54d04a 100644
--- a/ambari-web/test/controllers/main/service/widgets/create/step3_controller_test.js
+++ b/ambari-web/test/controllers/main/service/widgets/create/step3_controller_test.js
@@ -30,12 +30,100 @@ describe('App.WidgetWizardStep3Controller', function () {
App.TestAliases.testAsComputedIfThenElse(controller, 'widgetScope', 'isSharedChecked', 'Cluster', 'User');
- App.TestAliases.testAsComputedGte(controller, 'isNameInvalid', 'widgetName.length', 129);
+ //App.TestAliases.testAsComputedGte(controller, 'isNameInvalid', 'widgetName.length', 129);
- App.TestAliases.testAsComputedGte(controller, 'isDescriptionInvalid', 'widgetDescription.length', 2049);
+ //App.TestAliases.testAsComputedGte(controller, 'isDescriptionInvalid', 'widgetDescription.length', 2049);
App.TestAliases.testAsComputedOr(controller, 'isSubmitDisabled', ['widgetNameEmpty', 'isNameInvalid', 'isDescriptionInvalid']);
+ describe("#validateName", function(){
+ var testCases = [
+ {
+ widgetName: 'abc 123 _ - %',
+ result: {
+ errorMessage: '',
+ isNameInvalid: false
+ }
+ },
+ {
+ widgetName: '$#@!',
+ result: {
+ errorMessage: Em.I18n.t('widget.create.wizard.step3.name.invalidCharacter.msg'),
+ isNameInvalid: true
+ }
+ },
+ {
+ widgetName: '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
+ result: {
+ errorMessage: Em.I18n.t('widget.create.wizard.step3.name.invalid.msg'),
+ isNameInvalid: true
+ },
+ },
+ {
+ widgetName: '',
+ result: {
+ errorMessage: '',
+ isNameInvalid: false
+ }
+ }
+ ];
+
+ testCases.forEach(function(test){
+ controller.setProperties({
+ widgetName: test.widgetName
+ });
+
+ //Since validateName() observes the property "widgetName", Ember framework will call it
+
+ expect(controller.get('widgetNameErrorMessage')).to.equal(test.result.errorMessage);
+ expect(controller.get('isNameInvalid')).to.equal(test.result.isNameInvalid);
+ });
+ });
+
+ describe("#validateDescription", function(){
+ var testCases = [
+ {
+ widgetDescription: 'abc 123 _ - %',
+ result: {
+ errorMessage: '',
+ isDescriptionInvalid: false
+ }
+ },
+ {
+ widgetDescription: '$#@!',
+ result: {
+ errorMessage: Em.I18n.t('widget.create.wizard.step3.description.invalidCharacter.msg'),
+ isDescriptionInvalid: true
+ }
+ },
+ {
+ widgetDescription: '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
78901234567890123456789012345678901234567890123456789012345678901234567890123456789',
+ result: {
+ errorMessage: Em.I18n.t('widget.create.wizard.step3.description.invalid.msg'),
+ isDescriptionInvalid: true
+ }
+ },
+ {
+ widgetDescription: '',
+ result: {
+ errorMessage: '',
+ isDescriptionInvalid: false
+ }
+ }
+ ];
+
+ testCases.forEach(function(test){
+ controller.setProperties({
+ widgetDescription: test.widgetDescription
+ });
+
+ //Since validateDescription() observes the property "widgetDescription", Ember framework will call it
+
+ expect(controller.get('descriptionErrorMessage')).to.equal(test.result.errorMessage);
+ expect(controller.get('isDescriptionInvalid')).to.equal(test.result.isDescriptionInvalid);
+ });
+ });
+
describe("#initPreviewData()", function () {
beforeEach(function () {
sinon.stub(controller, 'addObserver');