ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From niti...@apache.org
Subject [3/4] ambari git commit: AMBARI-19031: UI Enhancements, import/export assets and smart version configuration (Padma Priya via nitirajrathore)
Date Fri, 16 Dec 2016 09:34:48 GMT
http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/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 ed743f4..02682a4 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
@@ -27,6 +27,8 @@ import {CytoscapeRenderer} from '../domain/cytoscape-flow-renderer';
 import {FindNodeMixin} from '../domain/findnode-mixin';
 import { validator, buildValidations } from 'ember-cp-validations';
 import WorkflowPathUtil from '../domain/workflow-path-util';
+import {ActionTypeResolver} from '../domain/action-type-resolver';
+import CommonUtils from "../utils/common-utils";
 
 const Validations = buildValidations({
   'dataNodes': { /* For Cytoscape */
@@ -71,6 +73,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   dataNodes: [], /* For cytoscape */
   hoveredAction: null,
   workflowImporter:WorkflowImporter.create({}),
+  actionTypeResolver: ActionTypeResolver.create({}),
   propertyExtractor : Ember.inject.service('property-extractor'),
   clipboardService : Ember.inject.service('workflow-clipboard'),
   workspaceManager : Ember.inject.service('workspace-manager'),
@@ -86,6 +89,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   killNode : {},
   isWorkflowImporting: false,
   isImportingSuccess: true,
+  isAssetPublishing: false,
+  isPublishingSuccess: true,
   shouldPersist : false,
   useCytoscape: Constants.useCytoscape,
   cyOverflow: {},
@@ -93,10 +98,15 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   isStackTraceVisible: false,
   isStackTraceAvailable: false,
   stackTrace:"",
+  showingStreamImport:false,
+  fileInfo:Ember.Object.create(),
+  isDraft: false,
+  saveJobService : Ember.inject.service('save-job'),
   initialize : function(){
     var id = 'cy-' + Math.ceil(Math.random() * 1000);
     this.set('cyId', id);
     this.sendAction('register', this.get('tabInfo'), this);
+    CommonUtils.setTestContext(this);
   }.on('init'),
   elementsInserted :function(){
     if (this.useCytoscape){
@@ -104,7 +114,6 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     }else{
       this.flowRenderer=JSPlumbRenderer.create({});
     }
-
     this.setConentWidth();
     this.set('workflow',Workflow.create({}));
     if(this.get("xmlAppPath")){
@@ -121,17 +130,18 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     if(Ember.isBlank(this.get('workflow.name'))){
       this.set('workflow.name', Ember.copy(this.get('tabInfo.name')));
     }
-
   }.on('didInsertElement'),
   restoreWorkflow(){
     if (!this.get("isNew")){
-      var draftWorkflow=this.getDraftWorkflow();
-      if (draftWorkflow){
-        this.resetDesigner();
-        this.set("workflow",draftWorkflow);
-        this.rerender();
-        this.doValidation();
-      }
+      this.getDraftWorkflow().promise.then(function(draftWorkflow){
+        if (draftWorkflow){
+          this.resetDesigner();
+          this.set("workflow",draftWorkflow);
+          this.rerender();
+          this.doValidation();
+        }
+      }.bind(this)).catch(function(data){
+      });
     }
   },
   observeXmlAppPath : Ember.observer('xmlAppPath', function(){
@@ -291,36 +301,30 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     this.set("isWorkflowImporting", true);
     this.set("workflowFilePath", filePath);
     this.resetDesigner();
-    this.set("isWorkflowImporting", true);
+    //this.set("isWorkflowImporting", true);
     var workflowXmlDefered=this.getWorkflowFromHdfs(filePath);
     workflowXmlDefered.promise.then(function(data){
       this.importWorkflowFromString(data);
       this.set("isWorkflowImporting", false);
     }.bind(this)).catch(function(data){
-    var stackTraceMsg = self.getStackTrace(data.responseText);
-    if(stackTraceMsg.length){
-      self.set("isStackTraceVisible", true);
-      self.set("stackTrace", stackTraceMsg);
-      self.set("isStackTraceAvailable", true);
-    } else {
-      self.set("isStackTraceVisible", false);
-      self.set("isStackTraceAvailable", false);
-    }
-      self.set("isWorkflowImporting", false);
-      self.set("isImportingSuccess", false);
+      console.error(data);
+      var stackTraceMsg = self.getStackTrace(data.responseText);
+      self.set("errorMsg", "There is some problem while importing.Please try again.");
+      self.showingErrorMsgInDesigner(data);
     });
   },
   importWorkflowFromString(data){
-    var workflow=this.get("workflowImporter").importWorkflow(data);
+    var wfObject=this.get("workflowImporter").importWorkflow(data);
     if(this.get('workflow')){
       this.resetDesigner();
-      this.set("workflow",workflow);
+      this.set("workflow",wfObject.workflow);
       this.initAndRenderWorkflow();
       this.rerender();
       this.doValidation();
+      this.set("errors", wfObject.errors);
     }else{
       this.workflow.initialize();
-      this.set("workflow",workflow);
+      this.set("workflow",wfObject.workflow);
       this.initAndRenderWorkflow();
       this.$('#wf_title').focus();
     }
@@ -343,8 +347,94 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     });
     return deferred;
   },
+  importActionSettingsFromString(actionSettings) {
+    var x2js = new X2JS();
+    var actionNode = this.flowRenderer.currentCyNode.data().node;
+    var actionJobHandler = this.actionTypeResolver.getActionJobHandler(actionNode.actionType);
+    actionJobHandler.handleImport(actionNode, x2js.xml_str2json(actionSettings)[actionNode.actionType]);
+    this.flowRenderer.hideOverlayNodeActions();
+  },
+  importActionNodeFromString(actionNodeXmlString) {
+    var x2js = new X2JS();
+    var actionNodeXml = x2js.xml_str2json(actionNodeXmlString);
+    var actionNodeType = Object.keys(actionNodeXml)[0];
+    var currentTransition = this.get("currentTransition");
+    this.createSnapshot();
+    var actionNode = this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode, currentTransition.sourceNodeId, currentTransition.targetNode.id),actionNodeType);
+    this.rerender();
+    this.doValidation();
+    this.scrollToNewPosition();
+    var actionJobHandler = this.actionTypeResolver.getActionJobHandler(actionNodeType);
+    actionJobHandler.handleImport(actionNode, actionNodeXml[actionNodeType]);
+  },
+  publishAsset(filePath, actionNodeXml, wfDynamicProps) {
+    var url = Ember.ENV.API_URL + "/publishAsset?uploadPath="+filePath;
+    wfDynamicProps.forEach(function(property){
+      url = url + "&config." + property.name + "=" + property.value;
+    });
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "POST",
+      dataType: "text",
+      contentType: "text/plain;charset=utf-8",
+      beforeSend: function (xhr) {
+        xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+        xhr.setRequestHeader("X-Requested-By", "Ambari");
+      },
+      data: actionNodeXml,
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  getRandomDataToDynamicProps(dynamicProperties) {
+    var wfDynamicProps = [];
+    var wfParams = this.get('workflow.parameters');
+    dynamicProperties.forEach(function(property) {
+      if (property!=="${nameNode}" && property!==Constants.rmDefaultValue) {
+        var propName = property.trim().substring(2, property.length-1);
+        var propValue;
+        if (wfParams && wfParams.configuration && wfParams.configuration.property) {
+          var param = wfParams.configuration.property.findBy('name', propName);
+          if (!(param && param.value)) {
+            propValue = param.value;
+          }
+        }
+        var prop = Ember.Object.create({
+          name: propName,
+          value: propValue ? propValue : Math.random().toString(36).slice(2)
+        });
+        wfDynamicProps.push(prop);
+      }
+    });
+    return wfDynamicProps;
+  },
+  exportActionNodeXml() {
+    var self = this;
+    self.set("isAssetPublishing", true);
+    var workflowGenerator = WorkflowGenerator.create({workflow:this.get("workflow"), workflowContext:this.get('workflowContext')});
+    var actionNodeXml = workflowGenerator.getActionNodeXml(this.flowRenderer.currentCyNode.data().name, this.flowRenderer.currentCyNode.data().node.actionType);
+    var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(actionNodeXml);
+
+    var exportActionNodeXmlDefered=this.publishAsset(this.get('exportActionNodeFilePath'), actionNodeXml, this.getRandomDataToDynamicProps(dynamicProperties));
+    exportActionNodeXmlDefered.promise.then(function(data){
+      self.set("isAssetPublishing", false);
+      self.set("isPublishingSuccess", true);
+      self.set("successMsg", "Asset is successfully published.");
+    }.bind(this)).catch(function(data){
+      self.set("errorMsg", "There is some problem while publishing asset. Please try again.");
+      self.showingErrorMsgInDesigner(data);
+      self.set("isImportingSuccess", true);
+    });
+
+    console.log("Action Node", actionNodeXml);
+  },
   resetDesigner(){
     this.set("isImportingSuccess", true);
+    this.set("isPublishingSuccess", true);
     this.set("xmlAppPath", null);
     this.set('errors',[]);
     this.set('validationErrors',[]);
@@ -374,8 +464,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       dataType: "text",
       cache:false,
       success: function(data) {
-        var workflow=this.get("workflowImporter").importWorkflow(data);
-        deferred.resolve(workflow);
+        var wfObject=this.get("workflowImporter").importWorkflow(data);
+        deferred.resolve(wfObject.workflow);
       }.bind(this),
       failure : function(data){
         deferred.reject(data);
@@ -383,19 +473,95 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     });
     return deferred;
   },
+  saveAsDraft(){
+    var self = this, url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("workflowFilePath") + "&overwrite=" + this.get("overwritePath");
+    Ember.$.ajax({
+      url: url,
+      method: "POST",
+      dataType: "text",
+      contentType: "text/plain;charset=utf-8",
+      beforeSend: function(request) {
+        request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+        request.setRequestHeader("X-Requested-By", "workflow-designer");
+      },
+      data: self.persistWorkflowAsDraft(),
+      success: function(response) {
+        //deferred.resolve(response);
+      }.bind(this),
+      error: function(response) {
+        //deferred.reject(response);
+      }.bind(this)
+    });
+  },
   persistWorkInProgress(){
-   var json=JSON.stringify(this.get("workflow"));
+   var json=this.getWorkflowAsJson();
    this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json);
   },
+  getWorkflowAsJson(){
+    try{
+     var json=JSON.stringify(this.get("workflow")), self = this;
+     //this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json);
+     return json;
+   }catch(err){
+    console.error(err);
+     this.isCyclic(this.get("workflow"));
+   }
+  },
+  isCyclic (obj) {
+    var seenObjects = [];
+    function detect (obj) {
+      if (typeof obj === 'object') {
+        if (seenObjects.indexOf(obj) !== -1) {
+          console.log("object already seen",obj);
+          return true;
+        }
+        seenObjects.push(obj);
+        for (var key in obj) {
+          if (obj.hasOwnProperty(key) && detect(obj[key])) {
+            console.log("object already seen",key);
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+    return detect(obj);
+  },
+  persistWorkflowAsDraft(){
+
+  },
+  getDraftWorkflowData(path){
+    var deferred = Ember.RSVP.defer();
+    //var path = encodeURIComponent("/user/ambari-qa/examples/demo/draft");
+    var self = this, url = Ember.ENV.API_URL + "/readWorkflowDraft?workflowXmlPath=" + path;
+    Ember.$.ajax({
+      url: url,
+      dataType: "text",
+      contentType: "text/plain;charset=utf-8",
+      beforeSend: function(request) {
+        request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+        request.setRequestHeader("X-Requested-By", "workflow-designer");
+      },
+      success: function(response) {
+        deferred.resolve(response);
+      }.bind(this),
+      error: function(response) {
+        deferred.reject(response);
+      }.bind(this)
+    });
+    return deferred;
+  },
   getDraftWorkflow(){
+    var deferred = Ember.RSVP.defer();
     var drafWorkflowJson = this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id'));
     var workflowImporter=WorkflowJsonImporter.create({});
     var workflow=workflowImporter.importWorkflow(drafWorkflowJson);
-    return workflow;
+    deferred.resolve(workflow);
+    return deferred;
   },
   createSnapshot() {
     this.set('undoAvailable', false);
-    this.set('workflowSnapshot', JSON.stringify(this.get("workflow")));
+    this.set('workflowSnapshot', this.getWorkflowAsJson());
   },
   showUndo (type){
     this.set('undoAvailable', true);
@@ -462,20 +628,26 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       scrollTop: scroll+200
     }, 1000);
   },
-  openSaveWorkflow (){
+  openSaveWorkflow (isWfPathSet){
     this.get('workflowContext').clearErrors();
     var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
     workflowContext:this.get('workflowContext')});
     var workflowXml=workflowGenerator.process();
     if(this.get('workflowContext').hasErrors()){
       this.set('errors',this.get('workflowContext').getErrors());
+      this.set("jobXmlJSONStr", this.persistWorkflowAsDraft());
+      this.set("isDraft", true);
     }else{
+      this.set("jobXmlJSONStr", "");
       var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(workflowXml);
       var configForSubmit={props:dynamicProperties,xml:workflowXml,params:this.get('workflow.parameters')};
       this.set("workflowSubmitConfigs",configForSubmit);
+      this.set("isDraft", false);
+    }
+    if(isWfPathSet) {
       this.set("showingSaveWorkflow",true);
     }
-  },  
+  },
   openJobConfig (){
     this.get('workflowContext').clearErrors();
     var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
@@ -490,7 +662,96 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       this.set("showingWorkflowConfigProps",true);
     }
   },
+  showingErrorMsgInDesigner(data){
+      var self = this, stackTraceMsg = self.getStackTrace(data.responseText);
+      if(stackTraceMsg.length){
+        self.set("isStackTraceVisible", true);
+        self.set("stackTrace", stackTraceMsg);
+        self.set("isStackTraceAvailable", true);
+      } else {
+        self.set("isStackTraceVisible", false);
+        self.set("isStackTraceAvailable", false);
+      }
+      self.set("isWorkflowImporting", false);
+      self.set("isImportingSuccess", false);
+      this.set("isAssetPublishing", false);
+      this.set("isPublishingSuccess", false);
+  },
+  isDraftExists(path){
+    var deferred = Ember.RSVP.defer(), url, self = this;
+    if(!path){
+      path = this.get("workflowFilePath");
+    }
+    url = Ember.ENV.API_URL + "/readWorkflowDetail?workflowXmlPath=" + path;
+    Ember.$.ajax({
+      url: url,
+      dataType: "text",
+      contentType: "text/plain;charset=utf-8",
+      beforeSend: function(request) {
+        request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+        request.setRequestHeader("X-Requested-By", "workflow-designer");
+      },
+      success: function(response) {
+        deferred.resolve(response);
+      }.bind(this),
+      error: function(response) {
+        deferred.reject(response);
+      }.bind(this)
+    });
+    return deferred;
+
+  },
+  importWorkflowFromFile(dataStr){
+    this.resetDesigner();
+    this.importWorkflowFromString(dataStr);
+    this.send("hideStreamImport");
+  },
   actions:{
+    importWorkflowStream(dataStr){
+      this.importWorkflowFromFile(dataStr);
+    },
+    saveFileinfo(path, overWritePath){
+      this.get("fileInfo").set("path", path);
+      this.get("fileInfo").set("overWritePath", overWritePath);
+    },
+    showStreamImport() {
+      this.set("showingStreamImport", true);
+    },
+    hideStreamImport() {
+      this.set("showingStreamImport", false);
+    },
+    fileLoaded(file){
+      var self = this;
+      function importWorkflowFromFile(dataStr){
+          self.importWorkflowFromFile(dataStr);
+      }
+      var reader = new FileReader();
+      reader.addEventListener("load", function (event) {
+          importWorkflowFromFile(event.target.result);
+      });
+      reader.readAsText(file);
+    },
+    importActionSettings(file){
+      var self = this;
+      var reader = new FileReader();
+      reader.addEventListener("load", function (event) {
+        var actionSettings = event.target.result;
+        var x2js = new X2JS();
+        var actionNode = self.flowRenderer.currentCyNode.data().node;
+        var actionJobHandler = self.actionTypeResolver.getActionJobHandler(actionNode.actionType);
+        actionJobHandler.handleImport(actionNode, x2js.xml_str2json(actionSettings)[actionNode.actionType]);
+        self.flowRenderer.hideOverlayNodeActions();
+      });
+      reader.readAsText(file);
+    },
+    importActionNodeLocalFS(file){
+      var self = this;
+      var reader = new FileReader();
+      reader.addEventListener("load", function (event) {
+        self.importActionNodeFromString(event.target.result);
+      });
+      reader.readAsText(file);
+    },
     showStackTrace(){
       this.set("isStackTraceVisible", true);
     },
@@ -515,7 +776,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     showVersionSettings(value){
       this.set('showVersionSettings', value);
     },
-    showingParameterSettings(value){ 
+    showingParameterSettings(value){
       if(this.get('workflow.parameters') !== null){
         this.set('parameters', Ember.copy(this.get('workflow.parameters')));
       }else{
@@ -616,7 +877,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
           if(trans.targetNode.id !== transition.okToNode.id){
             trans.targetNode = transition.okToNode;
             this.showUndo('transition');
-          }          
+          }
         }
       }, this);
     },
@@ -624,9 +885,29 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       this.set('dryrun', false);
       this.openJobConfig();
     },
-    saveWorkflow(){
+    saveWorkflow(action){
+      if(this.get("fileInfo").get("path") && action === "save"){
+        this.openSaveWorkflow();
+        var url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath");
+        var self = this, workflowData;
+
+        if(this.get('isDraft')){
+           url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath");;
+           workflowData = this.get("jobXmlJSONStr");
+        } else {
+           url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath");;
+           workflowData = this.get("workflowSubmitConfigs").xml;
+        }
+
+        this.get("saveJobService").saveWorkflow(url, workflowData).promise.then(function(data){
+        }.bind(this)).catch(function(data){
+          self.set("errorMsg", "There is some problem while saving workflow.Please try again.");
+          self.showingErrorMsgInDesigner(data);
+        });
+      } else {
+        this.openSaveWorkflow(true);
+      }
       this.set('dryrun', false);
-      this.openSaveWorkflow();
     },
     previewWorkflow(){
       this.set("showingPreview",false);
@@ -671,14 +952,85 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       });
     },
     closeFileBrowser(){
+      var self = this, path = this.get('workflowFilePath');
       this.set("showingFileBrowser",false);
-      if(this.get('workflowFilePath')){
-        this.importWorkflow(this.get('workflowFilePath'));
+      if(path){
+        this.isDraftExists().promise.then(function(data){
+          var draftData = JSON.parse(data);
+          if(draftData.draftExists && draftData.isDraftCurrent){
+            self.getDraftWorkflowData(path).promise.then(function(data){
+              var drafWorkflowJson = self.get('workspaceManager').restoreWorkInProgress(data);
+              var workflowImporter=WorkflowJsonImporter.create({});
+              var workflow=workflowImporter.importWorkflow(drafWorkflowJson);
+
+              self.resetDesigner();
+              self.set("workflow",workflow);
+              self.rerender();
+              self.doValidation();
+
+            }.bind(this)).catch(function(data){
+
+            });
+
+            //deferred.resolve(workflow);
+          } else {
+            self.importWorkflow(path);
+          }
+        }.bind(this)).catch(function(data){
+          //self.importWorkflow(path);
+          console.error(data);
+        });
       }
     },
     showFileBrowser(){
       this.set('showingFileBrowser', true);
     },
+    closeActionSettingsFileBrowser() {
+      var self = this;
+      this.set("showingActionSettingsFileBrowser", false);
+      if(this.get('actionSettingsFilePath')){
+        var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionSettingsFilePath'));
+        actionSettingsXmlDefered.promise.then(function(data){
+          this.importActionSettingsFromString(data);
+        }.bind(this)).catch(function(data){
+          console.error(data);
+          var stackTraceMsg = self.getStackTrace(data.responseText);
+          self.set("errorMsg", "There is some problem while importing.Please try again.");
+          self.showingErrorMsgInDesigner(data);
+        });
+      }
+    },
+    showActionSettingsFileBrowser() {
+      this.set('showingActionSettingsFileBrowser', true);
+    },
+    closeImportActionNodeFileBrowser() {
+      var self = this;
+      this.set("showingImportActionNodeFileBrowser", false);
+      if(this.get('actionNodeFilePath')){
+        var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionNodeFilePath'));
+        actionSettingsXmlDefered.promise.then(function(data){
+          this.importActionNodeFromString(data);
+        }.bind(this)).catch(function(data){
+          console.error(data);
+          var stackTraceMsg = self.getStackTrace(data.responseText);
+          self.set("errorMsg", "There is some problem while importing.Please try again.");
+          self.showingErrorMsgInDesigner(data);
+        });
+      }
+    },
+    showImportActionNodeFileBrowser() {
+      this.set('showingImportActionNodeFileBrowser', true);
+    },
+    closeExportActionNodeFileBrowser() {
+      var self = this;
+      this.set("showingExportActionNodeFileBrowser", false);
+      if(this.get('exportActionNodeFilePath')){
+        self.exportActionNodeXml();
+      }
+    },
+    showExportActionNodeFileBrowser() {
+      this.set('showingExportActionNodeFileBrowser', true);
+    },
     createNewWorkflow(){
       this.resetDesigner();
       this.rerender();
@@ -768,6 +1120,13 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     dryRunWorkflow(){
       this.set('dryrun', true);
       this.openJobConfig();
+    },
+    scheduleWorkflow(){
+      if(!this.get('workflowFilePath')){
+        console.error("Workflow doesnot exists");
+        return;
+      }
+      this.sendAction('openTab', 'coord', this.get('workflowFilePath'));
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
index 232df16..c9be41a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
@@ -59,7 +59,8 @@ export default Ember.Component.extend({
       var self=this;
       var $elem=this.$('input[name="selectedPath"]');
       //$elem.val($elem.val()+"/");
-
+      var folderHint="<enter folder here>";
+      this.set("selectedPath",this.get("selectedPath")+"/"+folderHint);
       setTimeout(function(){
         $elem[0].selectionStart = $elem[0].selectionEnd = self.get("selectedPath").length-folderHint.length;
       },10);

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js
new file mode 100644
index 0000000..c9aa3c4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js
@@ -0,0 +1,67 @@
+/*
+*    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.
+*/
+
+import Ember from 'ember';
+import Constants from '../utils/constants';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+  'workflowStream': validator('presence', {
+    presence : true
+  }),
+  'configMap': {
+    validators: [
+      validator('job-params-validator', {
+        dependentKeys: ['configMap.@each.value', 'showErrorMessage']
+      })
+    ]
+  }
+});
+
+
+export default Ember.Component.extend(Validations, {
+  workflowStream : "",
+  displayName : Ember.computed('type', function(){
+    if(this.get('type') === 'wf'){
+      return "Workflow";
+    }else if(this.get('type') === 'coord'){
+      return "Coordinator";
+    }else{
+      return "Bundle";
+    }
+  }),
+  initialize :function(){
+
+  }.on('init'),
+  rendered : function(){
+    this.$("#configureJob").modal("show");    
+  }.on('didInsertElement'),
+
+  getParsedErrorResponse (response){
+
+  },
+  actions: {
+    save(){
+      this.$("#configureJob").modal("hide");		
+      this.sendAction("importWorkflowStream", this.$('.CodeMirror')[0].CodeMirror.getValue());
+    },
+    close(){
+      this.$("#configureJob").modal("hide");	
+      this.sendAction("hideStreamImport");
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
index 4fa2666..8b685f0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
@@ -142,7 +142,7 @@ export default Ember.Component.extend(Validations, {
     }
     this.set("alertDetails", data.details);
     this.set("alertMessage", data.message);
-    if(data.stackTrace.length){
+    if(data.stackTrace && data.stackTrace.length){
       this.set("stackTrace", data.stackTrace);
       this.set("isStackTraceAvailable", true);
     } else {

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
index 0e5fd36..32f5ef4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
@@ -49,16 +49,21 @@ export default Ember.Component.extend({
     }
   }),
   displayType : Ember.computed('model.jobType', function() {
-    if(this.get('jobType') === 'wf'){
+    if(this.get('model.jobType') === 'wf'){
       return "Workflow";
-    }else if(this.get('jobType') === 'coords'){
+    }else if(this.get('model.jobType') === 'coords'){
       return "Coordinator";
     }
-    else if(this.get('jobType') === 'bundles'){
+    else if(this.get('model.jobType') === 'bundles'){
       return "Bundle";
     }
     return "Workflow";
   }),
+  configurationProperties : Ember.computed('model', function(){
+    var x2js = new X2JS();
+    var configurationObj  = x2js.xml_str2json(this.get('model.conf'));
+    return configurationObj.configuration.property;
+  }),
   initialize : function(){
     if(this.get('currentTab')){
       this.$('.nav-tabs a[href="'+this.get('currentTab').attr("href")+'"]').click();
@@ -66,11 +71,6 @@ export default Ember.Component.extend({
         this.set('model.actionDetails', this.get('model.actions')[0]);
       }
     }
-
-    var x2js = new X2JS();
-    var configurationObj  = x2js.xml_str2json(this.get('model.conf'));
-    this.set('model.configurationProperties', configurationObj.configuration.property);
-
     this.$('.nav-tabs').on('shown.bs.tab', function(event){
       this.sendAction('onTabChange', this.$(event.target));
     }.bind(this));
@@ -229,7 +229,8 @@ export default Ember.Component.extend({
       this.set('model.actionInfo', actionInfo);
     },
     renderDag(xmlString){
-      var workflow = this.get("workflowImporter").importWorkflow(xmlString);
+      var wfObject = this.get("workflowImporter").importWorkflow(xmlString);
+      var workflow = wfObject.workflow;
       console.log("Workflow Object..", workflow);
       var dataNodes=this.getCyDataNodes(workflow);
       var cy = cytoscape({
@@ -321,8 +322,8 @@ export default Ember.Component.extend({
       });
     },
     actions : {
-      back (){
-        this.sendAction('back');
+      back (jobType, jobId){
+        this.sendAction('back', jobType, jobId);
       },
       close : function(){
         this.sendAction('close');
@@ -332,7 +333,7 @@ export default Ember.Component.extend({
       },
       getJobDefinition : function () {
         Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=definition&timezone=GMT',function(response){
-          this.set('model.jobDefinition', (new XMLSerializer()).serializeToString(response).trim());
+          this.set('jobDefinition', (new XMLSerializer()).serializeToString(response).trim());
         }.bind(this)).fail(function(error){
           this.set('error',error);
         }.bind(this));
@@ -400,6 +401,9 @@ export default Ember.Component.extend({
       },
       showCoord : function(coordId){
         this.sendAction('showCoord', coordId);
+      },
+      editWorkflow(path){
+        this.sendAction('editWorkflow', path);
       }
     }
   });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js
index 297244a..2a5fc22 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js
@@ -19,6 +19,10 @@ import Ember from 'ember';
 
 export default Ember.Component.extend({
   tagName: 'tr',
+  targetParentId: Ember.computed('job', function() {
+    var parentID = this.get('job').parentId;
+    return parentID.split("@")[0];
+  }),
   onRender : function(){
     this.$('#actions').hide();
   }.on('didInsertElement'),

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
index ae453a0..bac2124 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
@@ -33,7 +33,6 @@ export default Ember.Component.extend({
     }
   }.on('willDestroyElement'),
   addProperty (){
-    alert(this.get("validations"));
     this.get('configuration.property').pushObject({name:this.get('propertyName'),value:this.get('propertyValue')});
     //if(this.get("doNotInitialize")){
       this.set('propertyName', "");

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
index 31f9df8..7e956a6 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
@@ -1,3 +1,4 @@
+
 /*
 *    Licensed to the Apache Software Foundation (ASF) under one or more
 *    contributor license agreements.  See the NOTICE file distributed with
@@ -17,4 +18,10 @@
 import Ember from 'ember';
 
 export default Ember.Component.extend({
+  elementsInserted :function(){
+  	var self = this;
+	  this.$('#previewModal').on('shown.bs.modal', function (e) {
+	    self.$('.CodeMirror')[0].CodeMirror.refresh();
+	  }); 
+  }.on('didInsertElement'),
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
index b41f743..8514cb0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
@@ -38,6 +38,7 @@ export default Ember.Component.extend(Validations, {
   alertDetails : "",
   filePath : "",
   showErrorMessage: false,
+  saveJobService : Ember.inject.service('save-job'),
   displayName : Ember.computed('type', function(){
     if(this.get('type') === 'wf'){
       return "Workflow";
@@ -69,7 +70,7 @@ export default Ember.Component.extend(Validations, {
     }
     this.set("alertDetails", data.details);
     this.set("alertMessage", data.message);
-    if(data.stackTrace.length){
+    if(data.stackTrace && data.stackTrace.length){
       this.set("stackTrace", data.stackTrace);
       this.set("isStackTraceAvailable", true);
     } else {
@@ -77,36 +78,34 @@ export default Ember.Component.extend(Validations, {
     }
   },
   saveJob(){
-    var url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath");
-    Ember.$.ajax({
-      url: url,
-      method: "POST",
-      dataType: "text",
-      contentType: "text/plain;charset=utf-8",
-      beforeSend: function(request) {
-        request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
-        request.setRequestHeader("X-Requested-By", "workflow-designer");
-      },
-      data: this.get("jobXml"),
-      success: function(response) {
-        //var result=JSON.parse(response);
-        this.showNotification({
+    var url, workflowData;
+    if(this.get('isDraft')){
+       url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath");
+       workflowData = this.get("jobXmlJSONStr");
+    } else {
+       url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath");
+       workflowData = this.get("jobXml");
+    }
+
+    var self = this;
+    this.get("saveJobService").saveWorkflow(url, workflowData).promise.then(function(response){
+        self.showNotification({
           "type": "success",
           "message": "Workflow have been saved"
         });
-        this.set("savingInProgress",false);
-      }.bind(this),
-      error: function(response) {
+        self.set("savingInProgress",false);
+        self.sendAction("saveFileinfo", this.get("filePath"), this.get("overwritePath"));
+    }.bind(this)).catch(function(response){
         console.log(response);
-        this.set("savingInProgress",false);
-        this.set("isStackTraceVisible",true);
-        this.showNotification({
+        self.set("savingInProgress",false);
+        self.set("isStackTraceVisible",true);
+        self.showNotification({
           "type": "error",
-          "message": "Error occurred while saving "+ this.get('displayName').toLowerCase(),
-          "details": this.getParsedErrorResponse(response),
-          "stackTrace": this.getStackTrace(response.responseText)
+          "message": "Error occurred while saving "+ self.get('displayName').toLowerCase(),
+          "details": self.getParsedErrorResponse(response),
+          "stackTrace": self.getStackTrace(response.responseText)
         });
-      }.bind(this)
+        self.sendAction("saveFileinfo", self.get("filePath"), self.get("overwritePath"));
     });
   },
   getStackTrace(data){

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js
index 420d3b0..f9226f4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js
@@ -98,6 +98,7 @@ export default Ember.Component.extend(Ember.Evented,{
           }
           strs.push('Name:'+ searchTerm);
           strs.push('User:'+ searchTerm);
+          strs.push('Job id:'+ searchTerm);
           var newLength = strs.length;
           var matches, substrRegex;
           matches = [];
@@ -115,19 +116,20 @@ export default Ember.Component.extend(Ember.Evented,{
           typeaheadjs: {
             name: 'source',
             source: substringMatcher(source),
-            highlight : true,
-            limit : 10
+            highlight : true
           }
       });
       this.get('tags').forEach(function(value){
         this.$('#search-field').tagsinput('add', value);
       }.bind(this));
       this.$('#search-field').tagsinput('refresh');
+
       this.$('#search-field').on('itemAdded itemRemoved',function(){
         var searchTerms = this.$('#search-field').tagsinput('items');
         var filter = searchTerms.map(function(value){
+
           var eachTag = value.split(":");
-          return eachTag[0].toLowerCase()+"="+eachTag[1];
+          return self.mapSearchItems(eachTag[0])+"="+eachTag[1];
         });
         if(filter.length > 0){
           this.filter.tags = filter.join(";");
@@ -144,7 +146,14 @@ export default Ember.Component.extend(Ember.Evented,{
         }
       }.bind(this));
     }.on('didInsertElement'),
-
+    mapSearchItems(key){
+      key = key.replace(" ", "_").toLowerCase();
+      var keys = {"job_id":"id"};
+      if(keys[key]){
+        return keys[key];
+      }
+      return key;
+    },
     filterByDate(date, dateType){
       var queryParam;
       if(dateType === 'start'){

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
index 7fc1c94..55f86af 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
@@ -30,6 +30,14 @@ export default Ember.Component.extend({
     pasteNode(){
       this.$(this.get('element')).popover('hide');
       this.sendAction("pasteNode");
+    },
+    importActionNodeLocalFS(file) {
+      this.$(this.get('element')).popover('hide');
+      this.sendAction("importActionNodeLocalFS", file);
+    },
+    showImportActionNodeFileBrowser() {
+      this.$(this.get('element')).popover('hide');
+      this.sendAction("showImportActionNodeFileBrowser");
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js
new file mode 100644
index 0000000..31dd392
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js
@@ -0,0 +1,21 @@
+/*
+*    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.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  tagName: 'span'
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js
new file mode 100644
index 0000000..9760ddb
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js
@@ -0,0 +1,81 @@
+/*
+*    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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    launchDesign: function () {
+      this.transitionToRoute('design');
+    },
+    doRefresh : function(){
+      this.get('target.router').refresh();
+    },
+    onJobAction: function (params, deferred) {
+      if (Ember.ENV.API_FAILED) {
+        return { error: "Remote API Failed." };
+      }
+      var url = [Ember.ENV.API_URL,
+        "/v2/job/", params.id, "?action=", params.action,'&user.name=oozie'
+      ].join("");
+      var jobActionParams = {
+        url: url,
+        method: 'PUT',
+        beforeSend: function (xhr) {
+          xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+          xhr.setRequestHeader("X-Requested-By", "Ambari");
+          if(params.action.indexOf('rerun') > -1){
+            xhr.setRequestHeader("Content-Type","application/xml");
+          }
+        }
+      };
+      if(params.action.indexOf('rerun') > -1){
+        jobActionParams.data = params.conf;
+      }
+      Ember.$.ajax(jobActionParams).done(function(){
+        deferred.resolve();
+      }).fail(function(){
+        deferred.reject();
+      });
+    },
+    onBulkAction : function(params, deferred){
+      if (Ember.ENV.API_FAILED) {
+        return { error: "Remote API Failed." };
+      }
+      var url = [Ember.ENV.API_URL,
+        "/v2/jobs?jobtype=", params.jobType,
+        "&offset=", params.start,
+        "&len=", params.len,
+        "&filter=", params.filter,
+        "&action=", params.action,
+        "&user.name=oozie"
+      ].join("");
+      Ember.$.ajax({
+        url: url,
+        method: 'PUT',
+        beforeSend: function (xhr) {
+          xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+          xhr.setRequestHeader("X-Requested-By", "Ambari");
+        }
+      }).done(function(response){
+        deferred.resolve(response);
+      }).fail(function(response){
+        deferred.reject(response);
+      });
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js
new file mode 100644
index 0000000..18559cc
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js
@@ -0,0 +1,59 @@
+/*
+*    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.
+*/
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  dashboardContext: Ember.inject.service(),
+  fromBundleId: null,
+  fromCoordId: null,
+  actions : {
+    close : function(){
+      this.sendAction('onCloseJobDetails');
+    },
+    showWorkflow : function(workflowId){
+      this.get('dashboardContext').setCurrentCoordName(this.get('model.coordJobName'));
+      this.transitionToRoute('design.jobtab', {
+        queryParams: {
+          jobType: 'wf',
+          id: workflowId,
+          fromBundleId: this.get('fromBundleId'),
+          fromCoordId: this.get('model.coordJobId')
+        }
+      });
+    },
+    showCoord : function(coordJobId){
+      this.get('dashboardContext').setCurrentBundleName(this.get('model.bundleJobName'));
+      this.transitionToRoute('design.jobtab', {
+        queryParams: {
+          jobType: 'coords',
+          id: coordJobId,
+          fromBundleId: this.get('model.bundleJobId')
+        }
+      });
+    },
+    back : function (jobType, jobId){
+      this.transitionToRoute('design.jobtab', {
+        queryParams: {
+          jobType: jobType,
+          id: jobId,
+          fromBundleId : (jobType === 'coords') ? this.get('fromBundleId') : null,
+          fromCoordId : null
+        }
+      });
+    },
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js
index 2c90be4..5a95b84 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js
@@ -17,8 +17,9 @@
 import Ember from 'ember';
 
 export default Ember.Controller.extend({
-  from : null,
-  fromType : null,
+  dashboardContext: Ember.inject.service(),
+  fromBundleId: null,
+  fromCoordId: null,
   actions : {
     close : function(){
       this.sendAction('onCloseJobDetails');
@@ -27,32 +28,33 @@ export default Ember.Controller.extend({
       this.get('target.router').refresh();
     },
     showWorkflow : function(workflowId){
-      this.transitionToRoute('job', {
+      this.get('dashboardContext').setCurrentCoordName(this.get('model.coordJobName'));
+      this.transitionToRoute('design.jobtab', {
         queryParams: {
           jobType: 'wf',
           id: workflowId,
-          from : this.get('model.coordJobId'),
-          fromType : this.get('model.jobType')
+          fromBundleId: this.get('fromBundleId'),
+          fromCoordId: this.get('model.coordJobId')
         }
       });
     },
     showCoord : function(coordJobId){
-      this.transitionToRoute('job', {
+      this.get('dashboardContext').setCurrentBundleName(this.get('model.bundleJobName'));
+      this.transitionToRoute('design.jobtab', {
         queryParams: {
           jobType: 'coords',
           id: coordJobId,
-          from : this.get('model.bundleJobId'),
-          fromType : this.get('model.jobType')
+          fromBundleId: this.get('model.bundleJobId')
         }
       });
     },
-    back : function (){
-      this.transitionToRoute('job', {
+    back : function (jobType, jobId){
+      this.transitionToRoute('design.jobtab', {
         queryParams: {
-          jobType: this.get('fromType'),
-          id: this.get('from'),
-          from : null,
-          fromType : null
+          jobType: jobType,
+          id: jobId,
+          fromBundleId : (jobType === 'coords') ? this.get('fromBundleId') : null,
+          fromCoordId : null
         }
       });
     },

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
index 957d1c0..7dc05a9 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
@@ -22,7 +22,7 @@ var BundleGenerator= Ember.Object.extend({
     var xmlJson={"bundle-app":{}};
     console.log(this.bundle);
     var bundleApp=xmlJson["bundle-app"];
-    bundleApp._xmlns = "uri:oozie:bundle:0.1";
+    bundleApp._xmlns = "uri:oozie:bundle:"+this.bundle.schemaVersions.bundleVersion;
     bundleApp._name = this.bundle.name;
     if(!Ember.isEmpty(this.bundle.kickOffTime.value)){
       bundleApp["control"] = {};

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/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 aa96221..2714ca1 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
@@ -16,14 +16,18 @@
 */
 import Ember from 'ember';
 import { Bundle } from '../bundle/bundle';
+import SchemaVersions from '../schema-versions';
+import CommonUtils from "../../utils/common-utils";
 
 var BundleXmlImporter= Ember.Object.extend({
   x2js : new X2JS(),
-  importBundle (xml){
+  schemaVersions : null,
+  importBundle (xml, errors){
     var bundleJson = this.get("x2js").xml_str2json(xml);
-    return this.processBundleXML(bundleJson);
+    return this.processBundleXML(bundleJson, errors);
   },
   processBundleXML(bundleJson){
+    var errors=Ember.A([]);
     var bundle = Bundle.create({
       name : '',
       kickOffTime : {
@@ -31,17 +35,25 @@ var BundleXmlImporter= Ember.Object.extend({
         displayValue : '',
         type : 'date'
       },
-      coordinators : Ember.A([])
+      coordinators : Ember.A([]),
+      schemaVersions : this.get("schemaVersions")
     });
     var bundleApp=bundleJson["bundle-app"];
     bundle.name = bundleApp._name;
+    var bundleVersion=CommonUtils.extractSchemaVersion(bundleApp._xmlns);
+    var maxBundleVersion = Math.max.apply(Math, bundle.schemaVersions.getBundleVersions());
+    if (bundleVersion < maxBundleVersion) {
+      bundle.schemaVersions.setCurrentBundleVersion(bundleVersion);
+    } else {
+      errors.push({message: "Unsupported bundle version - " + bundleVersion});
+    }
     if(bundleApp.control && bundleApp.control["kick-off-time"]) {
       bundle.kickOffTime = this.extractDateField(bundleApp["control"]["kick-off-time"]);
     }else{
 
     }
     this.processCoordinatorsJson(bundleApp, bundle);
-    return bundle;
+    return {bundle: bundle, errors: errors};
   },
   processCoordinatorsJson(bundleApp, bundle){
     if (bundleApp.coordinator){

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
index a657706..cbefa99 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
@@ -33,7 +33,7 @@ var CoordinatorGenerator= Ember.Object.extend({
     coordinatorApp._start = this.coordinator.start.value;
     coordinatorApp._end = this.coordinator.end.value;
     coordinatorApp._timezone = this.coordinator.timezone;
-    coordinatorApp._xmlns = "uri:oozie:coordinator:0.4";
+    coordinatorApp._xmlns = "uri:oozie:coordinator:"+this.coordinator.schemaVersions.coordinatorVersion;
     this.generateDataSets(coordinatorApp);
     if(this.coordinator.dataInputType === 'simple'){
       this.generateInputEvents(coordinatorApp);

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/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 fca90b3..76da535 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
@@ -16,12 +16,15 @@
 */
 import Ember from 'ember';
 import { Coordinator } from '../coordinator/coordinator';
+import SchemaVersions from '../schema-versions';
+import CommonUtils from "../../utils/common-utils";
 
 var CoordinatorXmlImporter= Ember.Object.extend({
   x2js : new X2JS(),
-  importCoordinator (xml){
+  schemaVersions: null,
+  importCoordinator (xml, errors){
     var coordinatorJson = this.get("x2js").xml_str2json(xml);
-    return this.processCoordinatorXML(coordinatorJson);
+    return this.processCoordinatorXML(coordinatorJson, errors);
   },
   createNewCoordinator(){
     return Coordinator.create({
@@ -55,13 +58,22 @@ var CoordinatorXmlImporter= Ember.Object.extend({
           property : Ember.A([])
         }
       },
-      controls : Ember.A([])
+      controls : Ember.A([]),
+      schemaVersions : this.get("schemaVersions")
     });
   },
   processCoordinatorXML(coordinatorJson){
+    var errors=Ember.A([]);
     var coordinatorApp = coordinatorJson["coordinator-app"];
     var coordinator = this.createNewCoordinator();
     coordinator.name = coordinatorApp._name;
+    var coordinatorVersion=CommonUtils.extractSchemaVersion(coordinatorApp._xmlns);
+    var maxCoordinatorVersion = Math.max.apply(Math, coordinator.schemaVersions.getCoordinatorVersions());
+    if (coordinatorVersion < maxCoordinatorVersion) {
+      coordinator.schemaVersions.setCurrentCoordinatorVersion(coordinatorVersion);
+    } else {
+      errors.push({message: "Unsupported coordinator version - " + coordinatorVersion});
+    }
     var frequency = coordinatorApp._frequency;
     if(frequency.startsWith('${coord:')){
       coordinator.frequency.type = frequency.substring(frequency.indexOf(':')+1, frequency.indexOf('('));
@@ -77,7 +89,7 @@ var CoordinatorXmlImporter= Ember.Object.extend({
     if(coordinatorApp['input-events'] && coordinatorApp['input-events']['data-in']){
       coordinator.dataInputType = 'simple';
       this.extractInputEvents(coordinatorApp, coordinator);
-    }else{
+    }else if(coordinatorApp['input-events']){
       coordinator.dataInputType = 'logical';
       coordinator.supportsConditionalDataInput = true;
       this.extractLogicalInputEvents(coordinatorApp, coordinator);
@@ -86,7 +98,7 @@ var CoordinatorXmlImporter= Ember.Object.extend({
     this.extractAction(coordinatorApp, coordinator);
     this.extractParameters(coordinatorApp, coordinator);
     this.extractControls(coordinatorApp, coordinator);
-    return coordinator;
+    return {coordinator: coordinator, errors: errors};
   },
   extractDateField(value){
     var dateField = {};

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
index 086916f..d1150c3 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
@@ -79,7 +79,7 @@ var CytoscapeRenderer= Ember.Object.extend({
         return 'roundrectangle';
       case 'fork' :
       case 'join' :
-        return 'rectangle';
+        return 'roundrectangle';
       case 'decision' :
         return 'diamond';
       default :
@@ -199,6 +199,8 @@ var CytoscapeRenderer= Ember.Object.extend({
       if (node.data().type === 'action') {
         this.get("context").$(".overlay-copy-icon").show();
         this.get("context").$(".overlay-cut-icon").show();
+        this.get("context").$(".overlay-hdfs-import-icon").show();
+        this.get("context").$(".overlay-hdfs-export-icon").show();
         if(this.get('context').get('clipboard')){
           this.get("context").$(".overlay-paste-icon").show();
         }
@@ -317,6 +319,15 @@ var CytoscapeRenderer= Ember.Object.extend({
     this._initCY(settings);
     callback();
   },
+
+  fitWorkflow() {
+    this.cy.fit();
+  },
+
+  hideOverlayNodeActions() {
+    this.get("context").$('.overlay-node-actions').hide();
+  },
+
   reset(){
 
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
index 2962e71..d4d8f50 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
@@ -65,7 +65,7 @@ var MappingMixin= Ember.Mixin.create({
     var domain={};
     if (json._xmlns){
       var version=CommonUtils.extractSchemaVersion(json._xmlns);
-      this.schemaVersions.setActionVersion(actionNode.actionType,version);
+      //this.schemaVersions.setActionVersion(actionNode.actionType,version);
     }
     actionNode.set("domain",domain);
     mappings.forEach(function(mapping){

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js
index 9562ae8..0a5083f 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js
@@ -18,35 +18,133 @@ import Ember from 'ember';
 export default Ember.Object.extend({
   actionVersions: Ember.Map.create(),
   currentActionVersion:Ember.Map.create(),
+  workflowVersions: [],
+  workflowVersion: null,
+  bundleVersions: [],
+  bundleVersion: null,
+  coordinatorVersions: [],
+  coordinatorVersion: null,
   clone : {},
+  actionSchemaMap:{
+    "hive":["0.6","0.5","0.4","0.3","0.2","0.1"],
+    "hive2":["0.2","0.1"],
+    "sqoop":["0.3","0.2","0.1"],
+    "shell":["0.3","0.2","0.1"],
+    "spark":["0.2","0.1"],
+    "distcp":["0.2","0.1"],
+    "email":["0.2","0.1"]
+  },
   createCopy(){
     this.clone.workflowVersion = this.workflowVersion;
     this.clone.currentActionVersion = this.currentActionVersion.copy();
+    this.clone.coordinatorVersion = this.coordinatorVersion;
+    this.clone.bundleVersion = this.bundleVersion;
   },
   rollBack(){
     this.workflowVersion = this.clone.workflowVersion;
     this.currentActionVersion = this.clone.currentActionVersion.copy();
   },
+  importAdminConfigs(){
+    var url = Ember.ENV.API_URL + "/v1/admin/configuration";
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "GET",
+      dataType: "text",
+      contentType: "text/plain;charset=utf-8",
+      beforeSend: function(request) {
+        request.setRequestHeader("X-Requested-By", "workflow-designer");
+      },
+      success: function(response) {
+        deferred.resolve(response);
+      }.bind(this),
+      error: function(response) {
+        deferred.reject(response);
+      }.bind(this)
+    });
+    return deferred;
+  },
+  setWfSchemaVersions(configSettings) {
+    this.workflowVersions = [];
+    var wfSchemaVersions = configSettings["oozie.service.SchemaService.wf.schemas"].trim().split(",");
+    wfSchemaVersions = wfSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort();
+    wfSchemaVersions.forEach(function(wfSchemaVersion) {
+      var wfSchema = wfSchemaVersion.split("-");
+      var wfSchemaName = wfSchema[0];
+      var wfSchemaType = wfSchema[1];
+      var wfSchemaVersionNumber = wfSchema[2].replace(".xsd", "");
+      if (wfSchemaType === "action") {
+        if (this.actionVersions.get(wfSchemaName)) {
+          this.actionVersions.get(wfSchemaName).push(wfSchemaVersionNumber);
+          this.currentActionVersion.set(wfSchemaName, wfSchemaVersionNumber);
+        } else {
+          this.actionVersions.set(wfSchemaName, [wfSchemaVersionNumber]);
+          this.currentActionVersion.set(wfSchemaName, wfSchemaVersionNumber);
+        }
+      } else if (wfSchemaType === "workflow") {
+        this.workflowVersions.push(wfSchemaVersionNumber);
+        this.workflowVersion = wfSchemaVersionNumber;
+      }
+    }.bind(this));
+  },
+  setCoordSchemaVersions(configSettings) {
+    this.coordinatorVersions = [];
+    var coordSchemaVersions = configSettings["oozie.service.SchemaService.coord.schemas"].trim().split(",");
+    coordSchemaVersions = coordSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort();
+    coordSchemaVersions.forEach(function(coordSchemaVersion) {
+      var coordSchema = coordSchemaVersion.split("-");
+      var coordSchemaType = coordSchema[1];
+      var coordSchemaVersionNumber = coordSchema[2].replace(".xsd", "");
+      if (coordSchemaType === "coordinator") {
+        this.coordinatorVersions.push(coordSchemaVersionNumber);
+        this.coordinatorVersion = coordSchemaVersionNumber;
+      }
+    }.bind(this));
+  },
+  setBundleSchemaVersions(configSettings) {
+    this.bundleVersions = [];
+    var bundleSchemaVersions = configSettings["oozie.service.SchemaService.bundle.schemas"].trim().split(",");
+    bundleSchemaVersions = bundleSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort();
+    bundleSchemaVersions.forEach(function(bundleSchemaVersion) {
+      var bundleSchema = bundleSchemaVersion.split("-");
+      var bundleSchemaType = bundleSchema[1];
+      var bundleSchemaVersionNumber = bundleSchema[2].replace(".xsd", "");
+      if (bundleSchemaType === "bundle") {
+        this.bundleVersions.push(bundleSchemaVersionNumber);
+        this.bundleVersion = bundleSchemaVersionNumber;
+      }
+    }.bind(this));
+  },
   init(){
-    this.workflowVersion = "0.5";
-    this.workflowVersions = ["0.5","0.4.5","0.4","0.3","0.2.5","0.2","0.1"];
-    this.actionVersions.set("hive",["0.6","0.5","0.4","0.3","0.2","0.1"]);
-    this.actionVersions.set("hive2",["0.2","0.1"]);
-    this.actionVersions.set("pig",["0.3","0.2","0.1"]);
-    this.actionVersions.set("sqoop",["0.3","0.2","0.1"]);
-    this.actionVersions.set("shell",["0.3","0.2","0.1"]);
-    this.actionVersions.set("spark",["0.2","0.1"]);
-    this.actionVersions.set("distcp",["0.2","0.1"]);
-    this.actionVersions.set("email",["0.2","0.1"]);
-
-    this.currentActionVersion.set("hive","0.6");
-    this.currentActionVersion.set("hive2","0.2");
-    this.currentActionVersion.set("pig","0.3");
-    this.currentActionVersion.set("sqoop","0.3");
-    this.currentActionVersion.set("shell","0.3");
-    this.currentActionVersion.set("spark","0.2");
-    this.currentActionVersion.set("distcp","0.2");
-    this.currentActionVersion.set("email","0.2");
+    var importAdminConfigsDefered=this.importAdminConfigs();
+    importAdminConfigsDefered.promise.then(function(data){
+      var configSettings = JSON.parse(data);
+      if (!(configSettings instanceof Object)) {
+        configSettings = JSON.parse(configSettings);
+      }
+      this.setWfSchemaVersions(configSettings);
+      this.setCoordSchemaVersions(configSettings);
+      this.setBundleSchemaVersions(configSettings);
+      this.setDefaultActionVersions();
+    }.bind(this)).catch(function(){
+      this.setWorkflowVersions(["0.5","0.4.5","0.4","0.3","0.2.5","0.2","0.1"]);
+      this.setCurrentWorkflowVersion("0.5");
+      this.setCoordinatorVersions(["0.4","0.3", "0.2","0.1"]);
+      this.setCurrentCoordinatorVersion("0.4");
+      this.setBundleVersions(["0.2","0.1"]);
+      this.setCurrentBundleVersion("0.2");
+      this.setDefaultActionVersions();
+      console.error("There is some problem while importing schema versions. defaulting to known versions.");
+    }.bind(this));
+  },
+  setDefaultActionVersions(){
+    var self=this;
+    Object.keys(this.actionSchemaMap).forEach(function(key) {
+      if (!self.actionVersions.get(key)){
+        self.actionVersions.set(key,self.actionSchemaMap[key]);
+        self.currentActionVersion.set(key,self.actionSchemaMap[key][0]);
+      }
+    });
   },
   getActionVersions(type){
     return this.actionVersions.get(type);
@@ -60,11 +158,38 @@ export default Ember.Object.extend({
   getWorkflowVersions(){
     return this.workflowVersions;
   },
+  getCurrentCoordinatorVersion(){
+    return this.coordinatorVersion;
+  },
+  getCoordinatorVersions(){
+    return this.coordinatorVersions;
+  },
+  getCurrentBundleVersion(){
+    return this.bundleVersion;
+  },
+  getBundleVersions(){
+    return this.bundleVersions;
+  },
   setActionVersion(type, version){
     this.currentActionVersion.set(type, version);
   },
   setCurrentWorkflowVersion(version){
-    return this.workflowVersion = version;
+    this.workflowVersion = version;
+  },
+  setCurrentCoordinatorVersion(version){
+    this.coordinatorVersion = version;
+  },
+  setCurrentBundleVersion(version){
+    this.bundleVersion = version;
+  },
+  setWorkflowVersions(versions){
+    this.workflowVersions = versions;
+  },
+  setCoordinatorVersions(versions){
+    this.coordinatorVersions = versions;
+  },
+  setBundleVersions(versions){
+    this.bundleVersions = versions;
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/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 7415544..d001f38 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
@@ -24,11 +24,12 @@ var WorkflowImporter= Ember.Object.extend({
   x2js : new X2JS(),
   importWorkflow(workflowXml){
     var workflow=Workflow.create({});
+    var errors=[];
     workflow.initialize();
     this.workflowMapper=WorkflowXmlMapper.create({schemaVersions:workflow.schemaVersions});
-    return this.processWorkflowXml(workflowXml,workflow);
+    return this.processWorkflowXml(workflowXml,workflow, errors);
   },
-  processWorkflowXml(workflowXml,workflow){
+  processWorkflowXml(workflowXml,workflow, errors){
     var workflowJson= this.get("x2js").xml_str2json(workflowXml);
     if (!workflowJson["workflow-app"]){
       throw "Invalid workflow";
@@ -36,6 +37,8 @@ var WorkflowImporter= Ember.Object.extend({
     var workflowAppJson=workflowJson["workflow-app"];
     var workflowVersion=CommonUtils.extractSchemaVersion(workflowAppJson._xmlns);
     workflow.schemaVersions.setCurrentWorkflowVersion(workflowVersion);
+    this.processWorkflowActionVersions(workflowAppJson, workflow, errors);
+
     if (workflowAppJson.info && workflowAppJson.info.__prefix==="sla") {
       workflow.slaEnabled=true;
       this.workflowMapper.handleSLAImport(workflow,workflowAppJson.info);
@@ -46,7 +49,33 @@ var WorkflowImporter= Ember.Object.extend({
     this.setupTransitions(workflowAppJson,nodeMap);
     workflow.set("startNode",nodeMap.get("start").node);
     this.populateKillNodes(workflow,nodeMap);
-    return workflow;
+    return {workflow: workflow, errors: errors};
+  },
+  processWorkflowActionVersions(workflowAppJson, workflow, errors) {
+    var importedWfActionVersions = Ember.Map.create();
+    var actions=workflowAppJson.action.length?workflowAppJson.action:[workflowAppJson.action];
+    actions.forEach(function(wfAction) {
+      var wfActionType = Object.keys(wfAction)[0];
+      var wfActionXmlns = wfAction[wfActionType]._xmlns;
+      if (!wfActionXmlns) {
+        return;
+      }
+      var wfActionVersion = CommonUtils.extractSchemaVersion(wfActionXmlns);
+      if (importedWfActionVersions.get(wfActionType)) {
+        importedWfActionVersions.get(wfActionType).push(wfActionVersion);
+      } else {
+        importedWfActionVersions.set(wfActionType, [wfActionVersion]);
+      }
+    });
+
+    importedWfActionVersions._keys.forEach(function(wfActionType){
+      var maxImportedActionVersion = Math.max.apply(Math, importedWfActionVersions.get(wfActionType))
+      if (workflow.schemaVersions.getActionVersion(wfActionType) < maxImportedActionVersion) {
+        errors.push({message: "Unsupported " + wfActionType + " version - " + maxImportedActionVersion});
+      } else {
+        workflow.schemaVersions.setActionVersion(wfActionType, maxImportedActionVersion.toString());
+      }
+    });
   },
   processActionNode(nodeMap,action){
     var actionMapper=this.get("workflowMapper").getNodeHandler("action");

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
index 7049fde..012e7ac 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
@@ -58,6 +58,21 @@ var WorkflowGenerator= Ember.Object.extend({
     var xmlAsStr = this.get("x2js").json2xml_str(reordered);
     return xmlAsStr;
   },
+
+  getActionNodeXml(actionNodeName, actionNodeType) {
+    var workflowObj={"workflow-app":{}};
+    this.visitNode(workflowObj, this.workflow.startNode);
+    var workflowActions = workflowObj["workflow-app"].action;
+    var actionNodes = workflowActions.filter(function (workflowActionNode) {
+        return workflowActionNode._name === actionNodeName;
+      });
+    if (actionNodes.length>0) {
+      var actionNode = {};
+      actionNode[actionNodeType] = actionNodes[0][actionNodeType];
+      return this.get("x2js").json2xml_str(actionNode);
+    }
+    return "";
+  },
   slaInfoExists(workflowApp){
     if (workflowApp.info){
       return true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/router.js b/contrib/views/wfmanager/src/main/resources/ui/app/router.js
index 1fcd633..f494f6f 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/router.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/router.js
@@ -24,7 +24,10 @@ const Router = Ember.Router.extend({
 
 Router.map(function () {
   this.route('dashboard');
-  this.route('design');
+  this.route('design', function() {
+    this.route('dashboardtab');
+    this.route('jobtab');
+  });
   this.route('designtest');
   this.route('job');
   this.route('connection-error');

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
index 949d39a..84cbd28 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
@@ -31,8 +31,8 @@ export default Ember.Route.extend({
         queryParams : {
           id : params.id,
           jobType : params.type,
-          from: null,
-          fromType: null
+          fromBundleId: null,
+          fromCoordId: null
         }
       });
     },

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
index 5ed2619..10f745a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
@@ -17,11 +17,24 @@
 
 import Ember from 'ember';
 
-export default Ember.Route.extend({
+export default Ember.Route.extend(Ember.Evented, {
 
   beforeModel: function(transition){
     this.set("xmlAppPath", transition.queryParams.appPath);
     this.controllerFor('design').set("xmlAppPath", transition.queryParams.appPath);
+  },
+  actions : {
+    editWorkflow(path){
+      this.trigger('openNewTab', path);
+    },
+    showDashboard(){
+      this.controller.set('dashboardShown', true);
+      this.transitionTo('design.dashboardtab');
+    },
+    hideDashboard(){
+      this.controller.set('dashboardShown', false);
+      this.transitionTo('design');
+    }
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js
new file mode 100644
index 0000000..ddb19af
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js
@@ -0,0 +1,154 @@
+/*
+*    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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  history: Ember.inject.service(),
+  errorMessage : "Error",
+  queryParams: {
+    jobType: { refreshModel: true },
+    start: { refreshModel: true },
+    filter: { refreshModel: true }
+  },
+  actions: {
+    onShowJobDetails : function(params){
+      this.transitionTo('design.jobtab',{
+        queryParams : {
+          id : params.id,
+          jobType : params.type,
+          fromBundleId: null,
+          fromCoordId: null
+        }
+      });
+    },
+    loading: function ( /*transition, originRoute*/ ) {
+      Ember.$("#loading").css("display", "block");
+      var app = this.controllerFor('application');
+      if (app.get('currentRouteName') !== "dashboard") {
+        return true;
+      }
+      return false;
+    },
+    error: function() {
+
+    },
+    doSearch (params){
+      this.get('history').setSearchParams(params);
+      Ember.$("#loading").css("display", "block");
+      this.search(params);
+    }
+  },
+  fetchJobs (url){
+    var deferred = Ember.RSVP.defer();
+    Ember.$.get(url).done(function(res){
+      deferred.resolve(res);
+    }).fail(function(){
+      deferred.reject();
+    });
+    return deferred.promise;
+  },
+  setPageResultLen(){
+    /*
+      setting the no of jobs to be displayed to multiple of 5
+    */
+    var relHeight = parseInt(Ember.$(window).width()/100);
+    return relHeight - relHeight%5;
+  },
+  search(params){
+    params = params || {};
+    var type = params.type || "wf",
+    start = Number(params.start || 1),
+    //len = Number(params.len || Ember.ENV.PAGE_SIZE),
+    len = this.setPageResultLen(),
+    index = 0,
+    filter = params.filter || "",
+    API_URL = Ember.ENV.API_URL,
+    url = [API_URL,
+      "/v2/jobs?jobtype=", type,
+      "&offset=", start,
+      "&len=", len,
+      "&filter=", filter
+    ].join(""),
+    page = (start - 1) / len + 1;
+    return this.fetchJobs(url).catch(function(){
+      this.controllerFor('dashboard').set('model',{error : "Remote API Failed"});
+      Ember.$("#loading").css("display", "none");
+    }.bind(this)).then(function (res) {
+      if(!res){
+        return;
+      }
+      if (typeof res === "string") {
+        res = JSON.parse(res);
+      }
+      res.jobs = [];
+
+      if (res.workflows) {
+        res.areWfs = true;
+        res.type = "wf";
+        res.workflows.forEach(function (job) {
+          job.type = "wf";
+          res.jobs.push(job);
+        });
+      }
+      if (res.coordinatorjobs) {
+        res.areCoords = true;
+        res.type = "coords";
+        res.coordinatorjobs.forEach(function (job) {
+          job.type = "coordinatorjobs";
+          job.id = job.coordJobId;
+          job.appName = job.coordJobName;
+          res.jobs.push(job);
+        });
+      }
+      if (res.bundlejobs) {
+        res.areBundles = true;
+        res.type = "bundles";
+        res.bundlejobs.forEach(function (job) {
+          job.type = "bundlejobs";
+          job.id = job.bundleJobId;
+          job.appName = job.bundleJobName;
+          res.jobs.push(job);
+        });
+      }
+      res.pageSize = len;
+      res.pages = [];
+
+      while (index++ < (res.total / len)) {
+        res.pages.push({ index: index, active: page === index });
+      }
+
+      res.jobTypeValue = type;
+      res.filterValue = filter;
+      res.pageSize = len;
+      res.totalValue = res.total;
+      res.page = page;
+      res.start = start;
+      res.end = (start + res.jobs.length - 1);
+      res.time = new Date().getTime();
+      this.controllerFor('design.dashboardtab').set('model', res);
+      Ember.$("#loading").css("display", "none");
+      return res;
+    }.bind(this));
+  },
+  afterModel: function (model) {
+    Ember.$("#loading").css("display", "none");
+  },
+  model: function (params) {
+
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js
new file mode 100644
index 0000000..7d0fa92
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js
@@ -0,0 +1,94 @@
+/*
+ *    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.
+ */
+
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  history: Ember.inject.service(),
+  queryParams: {
+      jobType: { refreshModel: true },
+      id: { refreshModel: true },
+      fromBundleId: {refreshModel: true},
+      fromCoordId: {refreshModel: true}
+  },
+  fromBundleId: null,
+  fromCoordId: null,
+  getJobInfo (url){
+    var deferred = Ember.RSVP.defer();
+    Ember.$.get(url).done(function(res){
+      deferred.resolve(res);
+    }).fail(function(){
+      deferred.reject();
+    });
+    return deferred.promise;
+  },
+  model : function(params){
+    return this.getJobInfo(Ember.ENV.API_URL+'/v2/job/'+params.id+'?show=info&timezone=GMT&offset=1&len='+Ember.ENV.PAGE_SIZE).catch(function(){
+        return {error : "Remote API Failed"};
+      }).then(function(response){
+      if (typeof response === "string") {
+          response = JSON.parse(response);
+      }
+      response.jobType = params.jobType;
+      return response;
+    });
+  },
+  afterModel : function (model, transition){
+    if(transition.queryParams.fromBundleId){
+      this.set('fromBundleId', transition.queryParams.fromBundleId);
+    }else{
+      this.set('fromBundleId', null);
+    }
+    if(transition.queryParams.fromCoordId){
+      this.set('fromCoordId', transition.queryParams.fromCoordId);
+    }else{
+      this.set('fromCoordId', null);
+    }
+  },
+  actions : {
+    didTransition (){
+      if (this.get('fromBundleId')) {
+        this.controller.set('fromBundleId', this.get('fromBundleId'));
+      }
+      if (this.get('fromCoordId')) {
+        this.controller.set('fromCoordId',this.get('fromCoordId'));
+      }
+    },
+    onTabChange : function(tab){
+      this.set('currentTab', tab);
+      this.controller.set('currentTab',tab);
+    },
+    backToSearch : function(){
+      var params = this.get('history').getSearchParams();
+      if(null != params){
+        this.transitionTo('design.dashboardtab', {
+            queryParams: {
+                jobType: params.type,
+                start: params.start,
+                end: params.end,
+                filter: params.filter
+            }
+        });
+      }else{
+        this.transitionTo('design.dashboardtab');
+      }
+    },
+    doRefresh : function(){
+      this.refresh();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fb567758/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js
index 0fbbaa2..23609e9 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js
@@ -19,6 +19,6 @@ import Ember from 'ember';
 
 export default Ember.Route.extend({
     beforeModel() {
-        this.transitionTo('dashboard');
+        this.transitionTo('design');
     }
 });


Mime
View raw message