ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From niti...@apache.org
Subject ambari git commit: AMBARI-19292 : Asset Manager/Asset Upload/Asset import from DB (Madhan Mohan Reddy via nitirajrathore)
Date Tue, 03 Jan 2017 18:32:08 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 996abd6bb -> 15a04bfb4


AMBARI-19292 : Asset Manager/Asset Upload/Asset import from DB (Madhan Mohan Reddy via nitirajrathore)


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

Branch: refs/heads/branch-2.5
Commit: 15a04bfb404abc15bbf295b40bb3b2875a6a97ca
Parents: 996abd6
Author: Nitiraj Rathore <nitiraj.rathore@gmail.com>
Authored: Tue Jan 3 23:59:46 2017 +0530
Committer: Nitiraj Rathore <nitiraj.rathore@gmail.com>
Committed: Wed Jan 4 00:01:41 2017 +0530

----------------------------------------------------------------------
 .../resources/ui/app/components/asset-config.js |  46 ++++++
 .../resources/ui/app/components/asset-list.js   |  82 +++++++++++
 .../ui/app/components/asset-manager.js          |  70 +++++++++
 .../ui/app/components/designer-workspace.js     |  24 ++++
 .../ui/app/components/flow-designer.js          | 134 ++++++++++++-----
 .../ui/app/components/workflow-actions.js       |   4 +
 .../resources/ui/app/services/asset-manager.js  | 142 +++++++++++++++++++
 .../src/main/resources/ui/app/styles/app.less   |  36 ++++-
 .../app/templates/components/asset-config.hbs   |  55 +++++++
 .../ui/app/templates/components/asset-list.hbs  |  63 ++++++++
 .../app/templates/components/asset-manager.hbs  |  62 ++++++++
 .../templates/components/designer-workspace.hbs |   6 +
 .../app/templates/components/flow-designer.hbs  |  33 +++--
 .../templates/components/workflow-actions.hbs   |   5 +-
 .../wfmanager/src/main/resources/ui/bower.json  |   3 +-
 .../src/main/resources/ui/ember-cli-build.js    |   5 +-
 .../integration/components/asset-config-test.js |  40 ++++++
 .../integration/components/asset-list-test.js   |  40 ++++++
 .../components/asset-manager-test.js            |  40 ++++++
 .../tests/unit/services/asset-manager-test.js   |  28 ++++
 20 files changed, 865 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js
new file mode 100644
index 0000000..dcfba34
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-config.js
@@ -0,0 +1,46 @@
+/*
+*    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 { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+  'assetModel.name': validator('presence', {
+    presence : true
+  })
+});
+
+export default Ember.Component.extend(Validations, {
+  initialize: function(){
+    this.$('#asset_config_dialog').modal('show');
+    this.$('#asset_config_dialog').modal().on('hidden.bs.modal', function() {
+      this.sendAction('showAssetConfig', false);
+    }.bind(this));
+  }.on('didInsertElement'),
+  actions: {
+    close() {
+      this.$('#asset_config_dialog').modal('hide');
+    },
+    save() {
+      if(this.get('validations.isInvalid')) {
+        this.set('showErrorMessage', true);
+        return;
+      }
+      this.$('#asset_config_dialog').modal('hide');
+      this.sendAction('saveAssetConfig');
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js
new file mode 100644
index 0000000..2ea82b0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-list.js
@@ -0,0 +1,82 @@
+/*
+*    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({
+  currentAssetId: null,
+  assetNotSelected: true,
+  assetSearchCriteria: "",
+  fuseSearchOptions: {
+    shouldSort: true,
+    threshold: 0.1,
+    location: 0,
+    distance: 100,
+    maxPatternLength: 32,
+    keys: [{
+      name: 'name',
+      weight: 0.3
+    }, {
+      name: 'type',
+      weight: 0.5
+    }, {
+      name: 'description',
+      weight: 0.1
+    }, {
+      name: 'owner',
+      weight: 0.1
+    }]
+  },
+  initialize: function() {
+    var self = this;
+    this.$('#asset_list_dialog').modal('show');
+    this.$('#asset_list_dialog').modal().on('hidden.bs.modal', function() {
+      this.sendAction('showAssetList', false);
+    }.bind(this));
+
+    this.$('#asset-list').on('click', 'tr', function(event) {
+      if(!$(this).hasClass('active-asset-row')) {
+        $(this).addClass('active-asset-row').siblings().removeClass('active-asset-row');
+      }
+      self.set('currentAssetId', $(this).data("assetId"));
+      self.set('assetNotSelected', false);
+    });
+    this.initializeFuseSearch();
+  }.on('didInsertElement'),
+  initializeFuseSearch() {
+     // var fuse = new Fuse(this.get("assetList"), this.get('fuseSearchOptions'));
+     // this.set('fuse', fuse);
+     // this.set('filteredAssetList', fuse.search(this.get("assetSearchCriteria")));
+     this.set('fuse', new Fuse(this.get("assetList"), this.get('fuseSearchOptions')));
+     this.set('filteredAssetList', this.get("assetList"));
+   },
+   assetSearchCriteriaObserver : Ember.observer('assetSearchCriteria', function(){
+     if (this.get("assetSearchCriteria") !== "") {
+       this.set('filteredAssetList', this.get('fuse').search(this.get("assetSearchCriteria")));
+     } else {
+       this.set('filteredAssetList', this.get("assetList"));
+     }
+   }),
+  actions: {
+    close() {
+      this.$('#asset_list_dialog').modal('hide');
+    },
+    importAsset() {
+      this.$('#asset_list_dialog').modal('hide');
+      this.sendAction('importAsset', this.get('assetList').filterBy('id', this.currentAssetId.toString())[0]);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js
new file mode 100644
index 0000000..4674533
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/asset-manager.js
@@ -0,0 +1,70 @@
+/*
+*    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({
+  assetSearchCriteria: "",
+  fuseSearchOptions: {
+    shouldSort: true,
+    threshold: 0.1,
+    location: 0,
+    distance: 100,
+    maxPatternLength: 32,
+    keys: [{
+      name: 'name',
+      weight: 0.3
+    }, {
+      name: 'type',
+      weight: 0.5
+    }, {
+      name: 'description',
+      weight: 0.1
+    }, {
+      name: 'owner',
+      weight: 0.1
+    }]
+  },
+  initialize: function() {
+    var self = this;
+    this.$('#asset_manager_dialog').modal('show');
+    this.$('#asset_manager_dialog').modal().on('hidden.bs.modal', function() {
+      this.sendAction('showAssetManager', false);
+    }.bind(this));
+
+    this.initializeFuseSearch();
+  }.on('didInsertElement'),
+  initializeFuseSearch() {
+     this.set('fuse', new Fuse(this.get("assetList"), this.get('fuseSearchOptions')));
+     this.set('filteredAssetList', this.get("assetList"));
+   },
+   assetSearchCriteriaObserver : Ember.observer('assetSearchCriteria', function(){
+     if (this.get("assetSearchCriteria") !== "") {
+       this.set('filteredAssetList', this.get('fuse').search(this.get("assetSearchCriteria")));
+     } else {
+       this.set('filteredAssetList', this.get("assetList"));
+     }
+   }),
+  actions: {
+    close() {
+      this.$('#asset_manager_dialog').modal('hide');
+    },
+    deleteAsset(asset) {
+      this.$('#asset_manager_dialog').modal('hide');
+      this.sendAction('deleteAsset', asset);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
index 6cbc3dd..c4f1b09 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
@@ -18,6 +18,7 @@ import Ember from 'ember';
 import CommonUtils from "../utils/common-utils";
 export default Ember.Component.extend({
   workspaceManager : Ember.inject.service('workspace-manager'),
+  assetManager : Ember.inject.service('asset-manager'),
   xmlAppPath : null,
   appPath : null,
   type : 'wf',
@@ -190,6 +191,29 @@ export default Ember.Component.extend({
       }else if(tab.type === 'dashboard'){
         this.sendAction('showDashboard');
       }
+    },
+    showAssetManager(value) {
+      var self=this;
+      if (value) {
+        var fetchAssetsDefered=self.get("assetManager").fetchMyAssets();
+        fetchAssetsDefered.promise.then(function(response){
+          self.set('assetList', JSON.parse(response).data);
+          self.set('showingAssetManager', value);
+        }.bind(this)).catch(function(data){
+          self.set("errorMsg", "There is some problem while fetching assets. Please try again.");
+        });
+      } else {
+        self.set('showingAssetManager', value);
+      }
+    },
+    deleteAsset(asset) {
+      var self=this;
+      var deleteAssetDefered=self.get("assetManager").deleteAsset(asset.id);
+      deleteAssetDefered.promise.then(function(response){
+        console.log("Asset deleted..");
+      }.bind(this)).catch(function(data){
+        self.set("errorMsg", "There is some problem while deleting asset. Please try again.");
+      });
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/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 50c7592..c6264ba 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
@@ -77,10 +77,12 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   propertyExtractor : Ember.inject.service('property-extractor'),
   clipboardService : Ember.inject.service('workflow-clipboard'),
   workspaceManager : Ember.inject.service('workspace-manager'),
+  assetManager : Ember.inject.service('asset-manager'),
   showGlobalConfig : false,
   showParameterSettings : false,
   showNotificationPanel : false,
   globalConfig : {},
+  assetConfig : {},
   parameters : {},
   clonedDomain : {},
   clonedErrorNode : {},
@@ -88,9 +90,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   showingFileBrowser : false,
   killNode : {},
   isWorkflowImporting: false,
-  isImportingSuccess: true,
   isAssetPublishing: false,
-  isPublishingSuccess: true,
+  errorMsg: "",
   shouldPersist : false,
   useCytoscape: Constants.useCytoscape,
   cyOverflow: {},
@@ -311,6 +312,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
       var stackTraceMsg = self.getStackTrace(data.responseText);
       self.set("errorMsg", "There is some problem while importing.Please try again.");
       self.showingErrorMsgInDesigner(data);
+      self.set("isWorkflowImporting", false);
     });
   },
   importWorkflowFromString(data){
@@ -349,10 +351,15 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
   },
   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();
+    var actionSettingsObj = x2js.xml_str2json(actionSettings);
+    var currentActionNode = this.flowRenderer.currentCyNode.data().node;
+    if (actionSettingsObj[currentActionNode.actionType]) {
+      var actionJobHandler = this.actionTypeResolver.getActionJobHandler(currentActionNode.actionType);
+      actionJobHandler.handleImport(currentActionNode, actionSettingsObj[currentActionNode.actionType]);
+      this.flowRenderer.hideOverlayNodeActions();
+    } else {
+      this.set("errorMsg", "Invalid asset settings");
+    }
   },
   importActionNodeFromString(actionNodeXmlString) {
     var x2js = new X2JS();
@@ -367,29 +374,6 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     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');
@@ -419,24 +403,21 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
     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));
+    var exportActionNodeXmlDefered=this.get("assetManager").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);
+      self.set("isAssetPublishing", false);
     });
 
     console.log("Action Node", actionNodeXml);
   },
   resetDesigner(){
-    this.set("isImportingSuccess", true);
-    this.set("isPublishingSuccess", true);
     this.set("xmlAppPath", null);
     this.set('errors',[]);
+    this.set('errorMsg',"");
     this.set('validationErrors',[]);
     this.set('workflowFilePath',"");
     this.get("workflow").resetWorfklow();
@@ -672,10 +653,6 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
         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;
@@ -1130,6 +1107,85 @@ export default Ember.Component.extend(FindNodeMixin, Validations, {
         return;
       }
       this.sendAction('openTab', 'coord', this.get('workflowFilePath'));
+    },
+    showAssetConfig(value) {
+      this.set('assetConfig', {});
+      this.set('showingAssetConfig', value);
+    },
+    saveAssetConfig() {
+      var self=this;
+      self.set("isAssetPublishing", true);
+      var workflowGenerator = WorkflowGenerator.create({workflow:self.get("workflow"), workflowContext:self.get('workflowContext')});
+      var actionNodeXml = workflowGenerator.getActionNodeXml(self.flowRenderer.currentCyNode.data().name, self.flowRenderer.currentCyNode.data().node.actionType);
+      var dynamicProperties = self.get('propertyExtractor').getDynamicProperties(actionNodeXml);
+      self.set('assetConfig.type', self.flowRenderer.currentCyNode.data().node.actionType);
+      self.set('assetConfig.definition', actionNodeXml);
+      var saveAssetConfigDefered=self.get("assetManager").saveAsset(self.get('assetConfig'), self.getRandomDataToDynamicProps(dynamicProperties));
+      saveAssetConfigDefered.promise.then(function(data){
+        self.set("isAssetPublishing", false);
+      }.bind(this)).catch(function(data){
+        self.set("isAssetPublishing", false);
+        self.set("errorMsg", "There is some problem while saving asset. Please try again.");
+        self.showingErrorMsgInDesigner(data);
+      });
+    },
+    showAssetList(value) {
+      var self=this;
+      if (value) {
+        var fetchAssetsDefered=self.get("assetManager").fetchAssets();
+        fetchAssetsDefered.promise.then(function(response){
+          self.set('assetList', JSON.parse(response).data);
+          self.set('showingAssetList', value);
+        }.bind(this)).catch(function(data){
+          self.set("errorMsg", "There is some problem while fetching assets. Please try again.");
+          self.showingErrorMsgInDesigner(data);
+        });
+      } else {
+        self.set('showingAssetList', value);
+      }
+    },
+    importAsset(asset) {
+      var self=this;
+      self.set("isAssetImporting", true);
+      var importAssetDefered=self.get("assetManager").importAssetDefinition(asset.id);
+      importAssetDefered.promise.then(function(response){
+        var importedAsset = JSON.parse(response).data;
+        self.importActionSettingsFromString(importedAsset.definition);
+        self.set("isAssetImporting", false);
+      }.bind(this)).catch(function(data){
+        self.set("isAssetImporting", false);
+        self.set("errorMsg", "There is some problem while importing asset. Please try again.");
+        self.showingErrorMsgInDesigner(data);
+      });
+    },
+    showAssetNodeList(value) {
+      var self=this;
+      if (value) {
+        var fetchAssetsDefered=self.get("assetManager").fetchAssets();
+        fetchAssetsDefered.promise.then(function(response){
+          self.set('assetList', JSON.parse(response).data);
+          self.set('showingAssetNodeList', value);
+        }.bind(this)).catch(function(data){
+          self.set("errorMsg", "There is some problem while fetching assets. Please try again.");
+          self.showingErrorMsgInDesigner(data);
+        });
+      } else {
+        self.set('showingAssetNodeList', value);
+      }
+    },
+    importAssetNode(asset) {
+      var self=this;
+      self.set("isAssetImporting", true);
+      var importAssetDefered=self.get("assetManager").importAssetDefinition(asset.id);
+      importAssetDefered.promise.then(function(response){
+        var importedAsset = JSON.parse(response).data;
+        self.importActionNodeFromString(importedAsset.definition);
+        self.set("isAssetImporting", false);
+      }.bind(this)).catch(function(data){
+        self.set("isAssetImporting", false);
+        self.set("errorMsg", "There is some problem while importing asset. Please try again.");
+        self.showingErrorMsgInDesigner(data);
+      });
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/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 55f86af..7c78eea 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
@@ -38,6 +38,10 @@ export default Ember.Component.extend({
     showImportActionNodeFileBrowser() {
       this.$(this.get('element')).popover('hide');
       this.sendAction("showImportActionNodeFileBrowser");
+    },
+    showAssetNodeList() {
+      this.$(this.get('element')).popover('hide');
+      this.sendAction("showAssetNodeList", true);
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js
new file mode 100644
index 0000000..3e87644
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/services/asset-manager.js
@@ -0,0 +1,142 @@
+/*
+*    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.Service.extend({
+  saveAsset(assetConfig, wfDynamicProps) {
+    var url = Ember.ENV.API_URL + "/assets";
+    wfDynamicProps.forEach(function(property, index){
+      url = url + ((index === 0) ? "?" : "&") + "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", "workflow-designer");
+      },
+      data: JSON.stringify(assetConfig),
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  fetchAssets() {
+    var url = Ember.ENV.API_URL + "/assets";
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "GET",
+      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", "workflow-designer");
+      }
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  fetchMyAssets() {
+    var url = Ember.ENV.API_URL + "/assets/mine";
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "GET",
+      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", "workflow-designer");
+      }
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  importAssetDefinition(assetDefinitionId) {
+    var url = Ember.ENV.API_URL + "/assets/" + assetDefinitionId;
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "GET",
+      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", "workflow-designer");
+      }
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  deleteAsset(assetId) {
+    var url = Ember.ENV.API_URL + "/assets/" + assetId;
+    var deferred = Ember.RSVP.defer();
+    Ember.$.ajax({
+      url: url,
+      method: "DELETE",
+      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", "workflow-designer");
+      }
+    }).done(function(data){
+      deferred.resolve(data);
+    }).fail(function(data){
+      deferred.reject(data);
+    });
+    return deferred;
+  },
+  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;
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
index 6296a64..4e8d82a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
@@ -54,6 +54,9 @@ a {
 .padding20{
     margin-top: 20px;
 }
+.marginBottom10{
+    margin-bottom: 10px;
+}
 .marginleft20{
   margin-left: 20px !important;
 }
@@ -577,7 +580,10 @@ input:invalid {
 #version-settings-dialog .modal-dialog,
 #control-dialog .modal-dialog,
 #ConfirmDialog .modal-dialog,
-#killnode-manager-dialog .modal-dialog {
+#killnode-manager-dialog .modal-dialog,
+#asset_manager_dialog .modal-dialog,
+#asset_config_dialog .modal-dialog,
+#asset_list_dialog .modal-dialog {
     width: 800px;
 }
 #configureJob .modal-dialog{
@@ -597,6 +603,9 @@ input:invalid {
 #configureWorkfowModal .panel-default > .panel-heading,
 #workflow_parameters_dialog .panel-default > .panel-heading,
 #killnode-manager-dialog .panel-default > .panel-heading,
+#asset_manager_dialog .panel-default > .panel-heading,
+#asset_config_dialog .panel-default > .panel-heading,
+#asset_list_dialog .panel-default > .panel-heading,
  .whiteLabel, .whiteLabel:hover, .whiteLabel:focus, .whiteLabel:visited, .whiteLabel:active {
     background-color: @bgGreenActive;
     color: #fff;
@@ -1543,3 +1552,28 @@ input:invalid {
 .inlineBlock{
   display:inline-block;
 }
+.asset-list .fa-trash-o {
+  color: @defaultRed;
+  cursor: pointer;
+}
+.active-asset-row {
+  background-color : @bgGreenActive !important;
+}
+.font10px {
+  font-size: 10px;
+}
+.asset-list-header-table {
+  width: 98%;
+}
+.asset-list-panel-header {
+  background-color: #f5f5f5;
+  border-bottom-left-radius: 0px;
+  border-bottom-right-radius: 0px;
+}
+.asset-list-panel-body {
+  max-height: 200px;
+  overflow-y: scroll;
+  border-top-left-radius: 0px;
+  border-top-right-radius: 0px;
+  border-top: 0px;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs
new file mode 100644
index 0000000..4ee6d05
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-config.hbs
@@ -0,0 +1,55 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="modal fade" id="asset_config_dialog">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close" {{action 'close'}}>
+          <span aria-hidden="true">&times;</span>
+        </button>
+        <h4 class="modal-title">Add Asset</h4>
+      </div>
+      <div class="modal-body">
+          <form class="form-horizontal">
+            <div class="panel panel-default">
+              <!-- <div class="panel-heading">General</div> -->
+              <div class="panel-body">
+                <div class="form-group">
+                  <label for="assetName" class="control-label col-xs-2">Name</label>
+                  <div class="col-xs-7">
+                    {{input type="text" class="form-control" name="assetName" value=assetModel.name placeholder="Asset Name"}}
+                    {{field-error model=this field='assetModel.name' showErrorMessage=showErrorMessage}}
+                  </div>
+                </div>
+                <div class="form-group">
+                  <label for="assetDescription" class="control-label col-xs-2">Description</label>
+                  <div class="col-xs-7">
+                    {{input type="text" class="form-control"  name="assetDescription" value=assetModel.description placeholder="Asset Description"}}
+                  </div>
+                </div>
+              </div>
+            </div>
+        </form>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-secondary" data-dismiss="modal" {{action 'close'}}>Cancel</button>
+        <button type="button" class="btn btn-primary" {{action 'save'}}>Save</button>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs
new file mode 100644
index 0000000..d377d2c
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-list.hbs
@@ -0,0 +1,63 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="modal fade" id="asset_list_dialog">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close" {{action 'close'}}>
+          <span aria-hidden="true">&times;</span>
+        </button>
+        <h4 class="modal-title">Select Asset</h4>
+      </div>
+      <div class="modal-body">
+        {{input type="text" class="form-control marginBottom10" name="assetSearchCriteria" value=assetSearchCriteria placeholder="Asset Search"}}
+        <div class="panel panel-default mb0 asset-list-panel-header">
+          <table class="table asset-list-header-table listing table-striped table-hover table-bordered" cellspacing="0" width="100%">
+            <thead>
+              <tr>
+                <th class="col-xs-3">Name</th>
+                <th class="col-xs-3">Type</th>
+                <th class="col-xs-3">Description</th>
+                <th class="col-xs-3">Owner</th>
+              </tr>
+            </thead>
+          </table>
+        </div>
+        <div class="panel panel-default asset-list-panel-body">
+          <table id="asset-list" class="table asset-list listing table-striped table-hover table-bordered" cellspacing="0" width="100%">
+            <tbody>
+              {{#each filteredAssetList as |asset idx|}}
+                <tr data-asset-id="{{asset.id}}">
+                  <td class="col-xs-3">{{asset.name}}</td>
+                  <td class="col-xs-3">{{asset.type}}</td>
+                  <td class="col-xs-3">{{asset.description}}</td>
+                  <td class="col-xs-3">{{asset.owner}}</td>
+                </tr>
+              {{/each}}
+            </tbody>
+          </table>
+
+        </div>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-secondary" data-dismiss="modal" {{action 'close'}}>Cancel</button>
+        <button type="button" class="btn btn-primary" disabled={{assetNotSelected}} {{action 'importAsset'}}>Import</button>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs
new file mode 100644
index 0000000..0fa86b0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/asset-manager.hbs
@@ -0,0 +1,62 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="modal fade" id="asset_manager_dialog">
+  <div class="modal-dialog" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close" {{action 'close'}}>
+          <span aria-hidden="true">&times;</span>
+        </button>
+        <h4 class="modal-title">Asset Manager</h4>
+      </div>
+      <div class="modal-body">
+        {{input type="text" class="form-control marginBottom10" name="assetSearchCriteria" value=assetSearchCriteria placeholder="Asset Search"}}
+        <div class="panel panel-default mb0 asset-list-panel-header">
+          <table class="table asset-list-header-table listing table-striped table-hover table-bordered" cellspacing="0" width="100%">
+            <thead>
+              <tr>
+                <th class="col-xs-3">Name</th>
+                <th class="col-xs-3">Type</th>
+                <th class="col-xs-3">Description</th>
+                <th class="col-xs-3"></th>
+              </tr>
+            </thead>
+          </table>
+        </div>
+        <div class="panel panel-default asset-list-panel-body">
+          <table id="asset-list" class="table asset-list listing table-striped table-hover table-bordered" cellspacing="0" width="100%">
+            <tbody>
+              {{#each filteredAssetList as |asset idx|}}
+                <tr data-asset-id="{{asset.id}}">
+                  <td class="col-xs-3">{{asset.name}}</td>
+                  <td class="col-xs-3">{{asset.type}}</td>
+                  <td class="col-xs-3">{{asset.description}}</td>
+                  <td class="col-xs-3"><span {{action 'deleteAsset' asset}}><i class="fa fa-trash-o"></i></span></td>
+                </tr>
+              {{/each}}
+            </tbody>
+          </table>
+
+        </div>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-secondary" data-dismiss="modal" {{action 'close'}}>Cancel</button>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
index 20e5b35..88e2c70 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
@@ -65,6 +65,9 @@
               <button {{action 'showDashboard'}} class="backto-dashboard btn btn-default" title="Workflow Dashboard">
                 <i class="fa fa-th marginright5"></i>Dashboard
               </button>
+              <button {{action "showAssetManager" true}} class="btn btn-default" title="Manage Assets">
+                  Manage Assets
+              </button>
               {{help-icon}}
             </div>
           </div>
@@ -111,6 +114,9 @@
       {{/each}}
     </div>
   </div>
+  {{#if showingAssetManager}}
+    {{#asset-manager showAssetManager="showAssetManager" deleteAsset="deleteAsset" assetList=assetList}}{{/asset-manager}}
+  {{/if}}
   <!--
   {{#if (eq type 'wf')}}
   {{flow-designer xmlAppPath=appPath isNew=isNew}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
index 101f861..7449f27 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
@@ -194,7 +194,7 @@
           </div>
       </div>
       {{/if}}
-      {{#unless isImportingSuccess}}
+      {{#if (not (eq errorMsg ""))}}
         <div id="loader">
             <div id="alert"class="alert alert-danger alert-dismissible" role="alert">
                 {{errorMsg}}
@@ -209,7 +209,7 @@
                 {{/if}}
             </div>
         </div>
-      {{/unless}}
+      {{/if}}
       {{#if isAssetPublishing}}
         <div id="loader">
             <div id="alert"class="alert alert-info alert-dismissible" role="alert">
@@ -217,13 +217,13 @@
             </div>
         </div>
       {{/if}}
-      {{#unless isPublishingSuccess}}
+      {{#if isAssetImporting}}
         <div id="loader">
-            <div id="alert"class="alert alert-danger alert-dismissible" role="alert">
-                {{errorMsg}}
+            <div id="alert"class="alert alert-info alert-dismissible" role="alert">
+              Importing asset. Please wait...
             </div>
         </div>
-      {{/unless}}
+      {{/if}}
       <div id="flow-designer">
         {{#each flattenedNodes as |node|}}
         <div class="node-wrapper">
@@ -284,12 +284,18 @@
                 {{/file-picker}}
               </div>
             </span>
-            <span class="overlay-hdfs-import-icon" title="Import action" {{action "showActionSettingsFileBrowser"}}>
+            <span class="hide" title="Import action" {{action "showActionSettingsFileBrowser"}}>
                 <i class="fa fa-download"></i>
             </span>
-            <span class="overlay-hdfs-export-icon" title="Export action" {{action "showExportActionNodeFileBrowser"}}>
+            <span class="overlay-hdfs-import-icon" title="Import Asset" {{action "showAssetList" true}}>
+                <i class="fa fa-download"></i>
+            </span>
+            <span class="hide" title="Export action" {{action "showExportActionNodeFileBrowser"}}>
                 <i class="fa fa-upload"></i>
             </span>
+            <span class="overlay-hdfs-export-icon" title="Publish Asset" {{action "showAssetConfig" true}}>
+                <i class="fa fa-share-square-o"></i>
+            </span>
           </div>
           {{decision-add-branch node=node registerAddBranchAction="registerAddBranchAction" addDecisionBranch="addDecisionBranch" workflow=workflow}}
         </div>
@@ -299,7 +305,7 @@
         {{/if}}
       </div>
       <div id="workflow-actions" class="hidden">
-        {{workflow-actions element=popOverElement addNode="addNode" pasteNode="pasteNode" showImportActionNodeFileBrowser="showImportActionNodeFileBrowser" importActionNodeLocalFS="importActionNodeLocalFS" clipboard=clipboard}}
+        {{workflow-actions element=popOverElement addNode="addNode" pasteNode="pasteNode" showImportActionNodeFileBrowser="showImportActionNodeFileBrowser" importActionNodeLocalFS="importActionNodeLocalFS" showAssetNodeList="showAssetNodeList" clipboard=clipboard}}
       </div>
     </div>
   </div>
@@ -332,6 +338,15 @@
 {{#if showingExportActionNodeFileBrowser}}
   {{hdfs-browser closeFileBrowser="closeExportActionNodeFileBrowser" selectFileCallback=selectFileCallback filePath=exportActionNodeFilePath}}
 {{/if}}
+{{#if showingAssetConfig}}
+  {{#asset-config showAssetConfig="showAssetConfig" saveAssetConfig="saveAssetConfig" assetModel=assetConfig}}{{/asset-config}}
+{{/if}}
+{{#if showingAssetList}}
+  {{#asset-list showAssetList="showAssetList" importAsset="importAsset" assetList=assetList}}{{/asset-list}}
+{{/if}}
+{{#if showingAssetNodeList}}
+  {{#asset-list showAssetList="showAssetNodeList" importAsset="importAssetNode" deleteAsset="deleteAsset" assetList=assetList}}{{/asset-list}}
+{{/if}}
 {{#if showingPreview}}
   {{#preview-dialog title="Workflow XML Preview" previewXml=previewXml closePreview="closePreview"}}{{/preview-dialog}}
 {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
index 50a87d8..be8afd4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
@@ -33,9 +33,10 @@
              <i class="fa fa-paste"></i>
              <span class="paste-action">Paste from clipboard</span>
            </span>
-        </div>     
+        </div>
       {{/if}}
-      <div {{action 'showImportActionNodeFileBrowser'}} class="btn btn-default"> <i class="fa fa-download"></i> <span class="paste-action">Import action</span></div>
+      <div {{action 'showImportActionNodeFileBrowser'}} class="btn btn-default hide"> <i class="fa fa-download"></i> <span class="font10px">Import action</span></div>
+      <div {{action 'showAssetNodeList'}} class="btn btn-default"> <i class="fa fa-download"></i> <span class="font10px">Import asset</span></div>
       <div class="clearfix"></div>
       <ul class="actions_list_left actionNodes">
           <li {{action 'addAction' 'hive'}} class="dr_action enabled" data-name="Hive" data-type="hive"> <i class="fa fa-server"></i> Hive </li>

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/bower.json b/contrib/views/wfmanager/src/main/resources/ui/bower.json
index 7fc1736..b66a190 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/bower.json
+++ b/contrib/views/wfmanager/src/main/resources/ui/bower.json
@@ -26,6 +26,7 @@
     "cytoscape": "^2.7.7",
     "cytoscape-dagre": "^1.3.0",
     "cytoscape-panzoom": "^2.4.0",
-    "codemirror": "~5.15.0"
+    "codemirror": "~5.15.0",
+    "fuse.js": "^2.5.0"
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js b/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
index 5dfb87c..20f5971 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
@@ -123,7 +123,10 @@ module.exports = function(defaults) {
 
 	//cytoscape-panzoom
 	app.import('bower_components/cytoscape-panzoom/cytoscape-panzoom.js');
-	app.import('bower_components/cytoscape-panzoom/cytoscape.js-panzoom.css');	
+	app.import('bower_components/cytoscape-panzoom/cytoscape.js-panzoom.css');
+
+	// Fuse js
+	app.import('bower_components/fuse.js/src/fuse.min.js');
 
     return app.toTree();
 };

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-config-test.js
new file mode 100644
index 0000000..597124f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-config-test.js
@@ -0,0 +1,40 @@
+/*
+ *    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 { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('asset-config', 'Integration | Component | asset config', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });"
+
+  this.render(hbs`{{asset-config}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:"
+  this.render(hbs`
+    {{#asset-config}}
+      template block text
+    {{/asset-config}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-list-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-list-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-list-test.js
new file mode 100644
index 0000000..20d6e6e
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-list-test.js
@@ -0,0 +1,40 @@
+/*
+ *    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 { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('asset-list', 'Integration | Component | asset list', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });"
+
+  this.render(hbs`{{asset-list}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:"
+  this.render(hbs`
+    {{#asset-list}}
+      template block text
+    {{/asset-list}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-manager-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-manager-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-manager-test.js
new file mode 100644
index 0000000..507a275
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/asset-manager-test.js
@@ -0,0 +1,40 @@
+/*
+ *    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 { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('asset-manager', 'Integration | Component | asset manager', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });"
+
+  this.render(hbs`{{asset-manager}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:"
+  this.render(hbs`
+    {{#asset-manager}}
+      template block text
+    {{/asset-manager}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/15a04bfb/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/asset-manager-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/asset-manager-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/asset-manager-test.js
new file mode 100644
index 0000000..8c1f5ea
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/asset-manager-test.js
@@ -0,0 +1,28 @@
+/*
+ *    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 { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:asset-manager', 'Unit | Service | asset manager', {
+  // Specify the other units that are required for this test.
+  // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  let service = this.subject();
+  assert.ok(service);
+});


Mime
View raw message