AMBARI-20360. Need to show appropriate error message in cases of UI failures. 
(M Madhan Mohan Reddy via dipayanb)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7f3bee58
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7f3bee58
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7f3bee58

Branch: refs/heads/branch-feature-AMBARI-12556
Commit: 7f3bee58260080c786bd8882663c9daa67c81d81
Parents: 03a832e
Author: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Authored: Fri Mar 10 17:27:21 2017 +0530
Committer: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Committed: Fri Mar 10 17:27:56 2017 +0530

----------------------------------------------------------------------
 .../ui/app/components/bundle-config.js          | 15 ++++++++----
 .../resources/ui/app/components/coord-config.js | 25 ++++++++++++++------
 .../ui/app/components/designer-errors.js        |  3 +++
 .../ui/app/components/flow-designer.js          | 25 +++++++++++++++-----
 .../ui/app/domain/bundle/bundle-xml-importer.js |  4 ++++
 .../coordinator/coordinator-xml-importer.js     |  4 ++++
 .../ui/app/domain/workflow-importer.js          | 12 +++++++---
 .../templates/components/designer-errors.hbs    | 11 ++++++---
 8 files changed, 76 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
index e94d51a..7c63b47 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
@@ -144,9 +144,12 @@ export default Ember.Component.extend(Ember.Evented, 
Validations, {
     return deferred;
   },
   importBundle (filePath){
-    this.set("bundleFilePath", filePath);
+    if (!filePath) {
+      return;
+    }
     this.set("isImporting", true);
     filePath = this.appendFileName(filePath, 'bundle');
+    this.set("bundleFilePath", filePath);
     var deferred = this.getBundleFromHdfs(filePath);
     deferred.promise.then(function(response){
       if(response.type === 'xml'){
@@ -209,9 +212,11 @@ export default Ember.Component.extend(Ember.Evented, 
Validations, {
   getBundleFromXml(bundleXml){
     var bundleXmlImporter = BundleXmlImporter.create();
     var bundleObj = bundleXmlImporter.importBundle(bundleXml);
-    this.set("bundle", bundleObj.bundle);
     this.get("errors").clear();
     this.get("errors").pushObjects(bundleObj.errors);
+    if (bundleObj.bundle) {
+      this.set("bundle", bundleObj.bundle);
+    }
   },
   getJobProperties(coordinatorPath){
     var deferred = Ember.RSVP.defer();
@@ -386,8 +391,10 @@ export default Ember.Component.extend(Ember.Evented, 
Validations, {
       var deferred = this.importSampleBundle();
       deferred.promise.then(function(data){
         this.getBundleFromXml(data);
-      }.bind(this)).catch(function(e){
-        throw new Error(e);
+      }.bind(this)).catch(function(data){
+        console.error(data);
+        this.set("errorMsg", "There is some problem while importing.");
+        this.set("data", data);
       });
     },
     openTab(type, path){

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
index c87ea99..e8f8cc1 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
@@ -76,7 +76,7 @@ export default Ember.Component.extend(Validations, 
Ember.Evented, {
   }.on('willDestroyElement'),
   initialize : function(){
     var self = this;
-
+    this.set('errors', Ember.A([]));
     
this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id')).promise.then(function(draftCoordinator){
       self.loadCoordinator(draftCoordinator);
     }.bind(this)).catch(function(data){
@@ -262,9 +262,12 @@ export default Ember.Component.extend(Validations, 
Ember.Evented, {
     return deferred;
   },
   importCoordinator (filePath){
+    if (!filePath) {
+      return;
+    }
+    this.set("isImporting", true);
     filePath = this.appendFileName(filePath, 'coord');
     this.set("coordinatorFilePath", filePath);
-    this.set("isImporting", false);
     var deferred = this.readCoordinatorFromHdfs(filePath);
     deferred.promise.then(function(response){
       if(response.type === 'xml'){
@@ -344,10 +347,13 @@ export default Ember.Component.extend(Validations, 
Ember.Evented, {
   getCoordinatorFromXml(coordinatorXml){
     var coordinatorXmlImporter = CoordinatorXmlImporter.create({});
     var coordinatorObj = 
coordinatorXmlImporter.importCoordinator(coordinatorXml);
-    var coordinator = coordinatorObj.coordinator;
-    this.set("coordinator", coordinator);
     this.get("errors").clear();
     this.get("errors").pushObjects(coordinatorObj.errors);
+    var coordinator = coordinatorObj.coordinator;
+    if (coordinator === null) {
+      return;
+    }
+    this.set("coordinator", coordinator);
     this.$('input[name="dataInputType"][value="'+ 
coordinator.get('dataInputType')+'"]').prop('checked', true);
     if(coordinator.get('dataInputType') === 'logical'){
       this.set('conditionalDataInExists', true);
@@ -581,15 +587,20 @@ export default Ember.Component.extend(Validations, 
Ember.Evented, {
     importCoordinatorTest(){
       var deferred = this.importSampleCoordinator();
       deferred.promise.then(function(data){
-        this.set("coordinator", data.coordinator);
         this.get("errors").clear();
         this.get("errors").pushObjects(data.errors);
+        if (data.coordinator === null) {
+          return;
+        }
+        this.set("coordinator", data.coordinator);
         this.$('input[name="dataInputType"][value="'+ 
data.coordinator.get('dataInputType')+'"]').prop('checked', true);
         if(data.coordinator.get('dataInputType') === 'logical'){
           this.set('conditionalDataInExists', true);
         }
-      }.bind(this)).catch(function(e){
-        throw new Error(e);
+      }.bind(this)).catch(function(data){
+        console.error(data);
+        this.set("errorMsg", "There is some problem while importing.");
+        this.set("data", data);
       });
     },
     openTab(type, path){

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-errors.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-errors.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-errors.js
index fdb4f5e..a585679 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-errors.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-errors.js
@@ -65,6 +65,9 @@ export default Ember.Component.extend({
     },
     closeStackTrace(){
       this.set("showingStackTrace", false);
+    },
+    dismissError(idx){
+      this.get("errors").removeAt(idx);
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
index 37992be..f542c07 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
@@ -123,6 +123,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     this.set('workflow',Workflow.create({}));
     CommonUtils.setTestContext(this);
     this.set('dataNodes', Ember.A([]));
+    this.set('errors', Ember.A([]));
     this.set('validationErrors', Ember.A([]));
   }.on('init'),
   elementsInserted :function(){
@@ -334,7 +335,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
   importWorkflow(filePath){
     var self = this;
     this.set("isWorkflowImporting", true);
-    this.resetDesigner();
+
     var workflowXmlDefered=this.getWorkflowFromHdfs(filePath);
     workflowXmlDefered.promise.then(function(response){
       if(response.type === 'xml'){
@@ -353,13 +354,18 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
   },
   importWorkflowFromString(data){
     var wfObject=this.get("workflowImporter").importWorkflow(data);
+    this.set("errors", wfObject.errors);
+    if (wfObject.workflow === null) {
+      this.rerender();
+      return;
+    }
+    this.resetDesigner();
     if(this.get('workflow')){
       this.resetDesigner();
       this.set("workflow",wfObject.workflow);
       this.initAndRenderWorkflow();
       this.rerender();
       this.doValidation();
-      this.set("errors", wfObject.errors);
     }else{
       this.workflow.initialize();
       this.set("workflow",wfObject.workflow);
@@ -513,7 +519,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
       cache:false,
       success: function(data) {
         var wfObject=this.get("workflowImporter").importWorkflow(data);
-        deferred.resolve(wfObject.workflow);
+        deferred.resolve(wfObject);
       }.bind(this),
       failure : function(data){
         deferred.reject(data);
@@ -976,12 +982,19 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     importWorkflowTest(){
       var deferred = this.importSampleWorkflow();
       deferred.promise.then(function(data){
+        this.get("errors").clear();
+        this.get("errors").pushObjects(data.errors);
+        if (data.workflow === null) {
+          return;
+        }
         this.resetDesigner();
-        this.set("workflow",data);
+        this.set("workflow",data.workflow);
         this.rerender();
         this.doValidation();
-      }.bind(this)).catch(function(e){
-        console.error(e);
+      }.bind(this)).catch(function(data){
+        console.error(data);
+        this.set("errorMsg", "There is some problem while importing.");
+        this.set("data", data);
       });
     },
     closeFileBrowser(){

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
index b3eed4b..cd08a93 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
@@ -40,6 +40,10 @@ var BundleXmlImporter= Ember.Object.extend({
         bundleVersion : this.get("schemaVersions").getDefaultVersion('bundle')
       }
     });
+    if (!bundleJson || !bundleJson["bundle-app"]){
+      errors.push({message: "Could not import invalid 
bundle",dismissable:true});
+      return {bundle:null, errors: errors};
+    }
     var bundleApp=bundleJson["bundle-app"];
     bundle.name = bundleApp._name;
     var bundleVersion=CommonUtils.extractSchemaVersion(bundleApp._xmlns);

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
index 12d923c..b89ad05 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
@@ -71,6 +71,10 @@ var CoordinatorXmlImporter= Ember.Object.extend({
   },
   processCoordinatorXML(coordinatorJson){
     var errors=Ember.A([]);
+    if (!coordinatorJson || !coordinatorJson["coordinator-app"]){
+      errors.push({message: "Could not import invalid 
coordinator",dismissable:true});
+      return {coordinator:null, errors: errors};
+    }
     var coordinatorApp = coordinatorJson["coordinator-app"];
     var coordinator = this.createNewCoordinator();
     coordinator.name = coordinatorApp._name;

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
index a076e3e..5d8d0a0 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
@@ -20,6 +20,7 @@ import CommonUtils from "../utils/common-utils";
 import {Workflow} from '../domain/workflow';
 import {WorkflowXmlMapper} from '../domain/workflow_xml_mapper';
 import SchemaVersions from '../domain/schema-versions';
+import Constants from '../utils/constants';
 
 var WorkflowImporter= Ember.Object.extend({
   workflowMapper:null,
@@ -33,10 +34,15 @@ var WorkflowImporter= Ember.Object.extend({
     return this.processWorkflowXml(workflowXml,workflow, errors);
   },
   processWorkflowXml(workflowXml,workflow, errors){
-    var xmlDoc= xmlDoc = Ember.$.parseXML( workflowXml );
+    var xmlDoc=  Ember.$.parseXML( workflowXml );
+    if (xmlDoc && 
xmlDoc.getElementsByTagName('action').length>Constants.flowGraphMaxNodeCount){
+      errors.push({message: "Workflow is too large to be 
imported",dismissable:true});
+      return {workflow:null, errors: errors};
+    }
     var workflowJson= this.get("x2js").xml_str2json(workflowXml);
-    if (!workflowJson["workflow-app"]){
-      throw "Invalid workflow";
+    if (!workflowJson || !workflowJson["workflow-app"]){
+      errors.push({message: "Could not import invalid 
workflow",dismissable:true});
+      return {workflow:null, errors: errors};
     }
     var workflowAppJson=workflowJson["workflow-app"];
     var 
workflowVersion=CommonUtils.extractSchemaVersion(workflowAppJson._xmlns);

http://git-wip-us.apache.org/repos/asf/ambari/blob/7f3bee58/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-errors.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-errors.hbs
 
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-errors.hbs
index 3cab194..701a6eb6 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-errors.hbs
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-errors.hbs
@@ -19,11 +19,16 @@
   {{#if (or (gt errors.length 0) (gt validationErrors.length 0))}}
     <div id="alert"class="alert alert-danger alert-dismissible fade in 
workflow-error" role="alert">
       {{#if (gt errors.length 0)}}
-        {{#each errors as |error|}}
+        {{#each errors as |error index|}}
           {{#if error.node}}
-          <div>{{error.node.name}} : {{error.message}}</div>
+            <div>{{error.node.name}} : {{error.message}}</div>
           {{else}}
-          <div>{{error.message}}</div>
+            <div>
+              {{error.message}}
+              {{#if error.dismissable}}
+                <button type="button" class="dismissable-error-close" {{action 
"dismissError" index}}><span aria-hidden="true">&times;</span></button>
+              {{/if}}
+            </div>
           {{/if}}
         {{/each}}
       {{/if}}

Reply via email to