Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 ad772ddd6 -> f8d337659


AMBARI-20000.Workflow Manager optimising finding nodes(Belliraj via gauravn7)


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

Branch: refs/heads/branch-2.5
Commit: f8d33765933c7cd8f5954261c84d9141ada27462
Parents: ad772dd
Author: Gaurav Nagar <[email protected]>
Authored: Tue Feb 14 18:05:45 2017 +0530
Committer: Gaurav Nagar <[email protected]>
Committed: Tue Feb 14 18:06:22 2017 +0530

----------------------------------------------------------------------
 .../ui/app/components/decision-add-branch.js    |  5 --
 .../ui/app/components/decision-config.js        |  2 +
 .../ui/app/components/flow-designer.js          | 49 ++++++++++++++------
 .../ui/app/domain/cytoscape-flow-renderer.js    | 25 ++++++++--
 .../resources/ui/app/domain/cytoscape-style.js  | 24 +++++-----
 .../resources/ui/app/domain/mapping-utils.js    |  2 +-
 .../ui/app/domain/workflow-json-importer.js     |  2 +-
 .../main/resources/ui/app/domain/workflow.js    | 18 ++++---
 .../components/workflow-action-editor.hbs       |  2 +-
 .../wfmanager/src/main/resources/ui/bower.json  |  3 +-
 .../src/main/resources/ui/ember-cli-build.js    |  1 +
 11 files changed, 89 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
index 65d0974..41bb1e5 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
@@ -55,12 +55,7 @@ export default Ember.Component.extend(Validations, 
FindNodeMixin,{
         self.set("isInsertAction",false);
         this.set("newNodeType",null);
         this.get('flowRenderer').populateOkToandErrorTONodes(node);
-        var 
commonTarget=this.findCommonTargetNode(this.workflow.startNode,this.get('node'));
         var descendantNodes= this.get('node.validOkToNodes');
-        if (commonTarget){
-          descendantNodes.removeObject(commonTarget);
-          descendantNodes.unshiftObject(commonTarget);
-        }
         this.set('descendantNodes',descendantNodes);
         self.$("#selector-content").show();
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
index ad664d7..419be37 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
@@ -31,5 +31,7 @@ const Validations = buildValidations({
 export default Ember.Component.extend(Validations,{
   initialize : function(){
     this.sendAction('register','decision',this);
+    this.set('targetNodes', Ember.A([]));
+    this.get('targetNodes').pushObjects(this.get('killNodes'));
   }.on('init')
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/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 a5536af..29c9dd2 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
@@ -110,6 +110,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     this.sendAction('register', this.get('tabInfo'), this);
     this.set('flowRenderer',CytoscapeRenderer.create());
     this.set('workflow',Workflow.create({}));
+    this.set("isNew",true);
     CommonUtils.setTestContext(this);
   }.on('init'),
   elementsInserted :function(){
@@ -237,6 +238,10 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
       link.click();
   },
   nodeRendered: function(){
+    if (this.get("isNew")){
+      this.set("isNew",false);
+      return;
+    }
     this.doValidation();
     this.resize();
     this.persistWorkInProgress();
@@ -269,13 +274,17 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     this.flowRenderer.cleanup();
     this.renderWorkflow(this.get("workflow"));
   },
-  setCurrentTransition(transition){
-    this.set("currentTransition",transition);
+  setCurrentTransition(transitionInfo){
+    this.set("currentTransition", {
+      transition : transitionInfo.transition,
+      source : transitionInfo.source,
+      target : transitionInfo.target
+    });
   },
   actionInfo(node){
     this.send("showNotification", node);
   },
-  deleteTransition(transition){
+  deleteTransition(transition,sourceNode){
     this.createSnapshot();
     this.get("workflow").deleteTransition(transition);
     this.showUndo('transition');
@@ -442,7 +451,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     var x2js = new X2JS();
     var actionNodeXml = x2js.xml_str2json(actionNodeXmlString);
     var actionNodeType = Object.keys(actionNodeXml)[0];
-    var currentTransition = this.get("currentTransition");
+    var currentTransition = this.get("currentTransition.transition");
     this.createSnapshot();
     var actionNode = 
this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode,
 currentTransition.sourceNodeId, 
currentTransition.targetNode.id),actionNodeType);
     this.rerender();
@@ -558,18 +567,32 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
    this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), 
json);
   },
   getWorkflowAsJson(){
+    return this.getWorkflowAsJsonJsoGImpl();
+  },
+  getWorkflowAsNativeJsonImpl(){
     try{
      var json=JSON.stringify(this.get("workflow")), self = this;
      var actionVersions = 
JSON.stringify([...this.get("workflow").schemaVersions.actionVersions]);
      var workflow = JSON.parse(json);
      workflow.schemaVersions.actionVersions = actionVersions
-     //this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), 
json);
      return JSON.stringify(workflow);
    }catch(err){
     console.error(err);
      this.isCyclic(this.get("workflow"));
    }
   },
+  getWorkflowAsJsonJsoGImpl(){
+   try{
+    var json=JSOG.stringify(this.get("workflow")), self = this;
+    var actionVersions = 
JSOG.stringify([...this.get("workflow").schemaVersions.actionVersions]);
+    var workflow = JSOG.parse(json);
+    workflow.schemaVersions.actionVersions = actionVersions
+    return JSOG.stringify(workflow);
+  }catch(err){
+   console.error(err);
+    this.isCyclic(this.get("workflow"));
+  }
+},
   isCyclic (obj) {
     var seenObjects = [];
     function detect (obj) {
@@ -631,7 +654,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     this.set('undoAvailable', true);
     this.set('undoType', type);
   },
-  deleteWorkflowNode(node){
+  deleteWorkflowNode(node,transitionslist){
     this.createSnapshot();
     if(node.isKillNode()){
       var result=this.get("workflow").deleteKillNode(node);
@@ -639,7 +662,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
         this.get('validationErrors').pushObject({node : node ,message 
:result.message});
       }
     } else {
-      this.get("workflow").deleteNode(node);
+      this.get("workflow").deleteNode(node,transitionslist);
     }
     this.rerender();
     this.doValidation();
@@ -858,8 +881,10 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     },
     addAction(type){
       this.createSnapshot();
-      var currentTransition=this.get("currentTransition");
-      
this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode,
 currentTransition.sourceNodeId, currentTransition.targetNode.id),type);
+      var currentTransition=this.get("currentTransition.transition");
+      var transition = 
this.get("currentTransition").source.transitions.findBy('targetNode.id',currentTransition.targetNode.id);
+      transition.source=this.get("currentTransition").source;
+      this.get("workflow").addNode(transition, type);
       this.rerender();
       this.doValidation();
       this.scrollToNewPosition();
@@ -873,7 +898,7 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     },
     pasteNode(){
       var clipboardContent = this.get('clipboardService').getContent();
-      var currentTransition = this.get("currentTransition");
+      var currentTransition = this.get("currentTransition.transition");
       var node = this.get("workflow").addNode(currentTransition, 
clipboardContent.actionType);
       if(clipboardContent.operation === 'cut'){
         node.name = clipboardContent.name;
@@ -894,10 +919,6 @@ export default Ember.Component.extend(FindNodeMixin, 
Validations, {
     },
     showNotification(node){
       this.set("showNotificationPanel", true);
-      if(node.actionType){
-        //this.set("hoveredWidget", node.actionType+"-action-info");
-        //this.set("hoveredAction", node.getNodeDetail());
-      }
     },
     hideNotification(){
       this.set("showNotificationPanel", false);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/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 8202c6d..4194d5e 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
@@ -230,6 +230,8 @@ var CytoscapeRenderer= Ember.Object.extend({
       }else{
           this.get("context").$(".overlay-trash-transition-icon").hide();
       }
+      
this.get("context").$(".overlay-transition-content").data("sourceNode",event.cyTarget.source().data("node"));
+      
this.get("context").$(".overlay-transition-content").data("targetNode",event.cyTarget.target().data("node"));
       
this.get("context").$(".overlay-transition-content").data("transition",event.cyTarget.data().transition);
 
       if (event.cyTarget.data().transition && 
event.cyTarget.data().transition.condition) {
@@ -246,7 +248,11 @@ var CytoscapeRenderer= Ember.Object.extend({
     this.get("context").$('.overlay-plus-icon').on('click',function(){
       this.get("context").$(".overlay-transition-content").popover("show");
       this.get("context").set('popOverElement', 
this.get("context").$('.overlay-transition-content'));
-      
this.get("context").setCurrentTransition(this.get("context").$(".overlay-transition-content").data("transition"));
+      this.get("context").setCurrentTransition({
+        transition : 
this.get("context").$(".overlay-transition-content").data("transition"),
+        source : 
this.get("context").$(".overlay-transition-content").data("sourceNode"),
+        target : 
this.get("context").$(".overlay-transition-content").data("targetNode")
+      });
       Ember.run.later(this, function() {
         this.get("context").$('.overlay-transition-content').hide();
       }, 1000);
@@ -254,13 +260,26 @@ var CytoscapeRenderer= Ember.Object.extend({
 
     this.get("context").$('.overlay-trash-transition-icon').off('click');
     
this.get("context").$('.overlay-trash-transition-icon').on('click',function(){
-      
this.get("context").deleteTransition(this.get("context").$(".overlay-transition-content").data("transition"));
+      var 
tran=this.get("context").$(".overlay-transition-content").data("transition");
+      tran.sourceNode= 
this.get("context").$(".overlay-transition-content").data("sourceNode");
+      this.get("context").deleteTransition(tran);
       this.get("context").$('.overlay-transition-content').hide();
     }.bind(this));
 
     this.get("context").$('.overlay-trash-icon i').off('click');
     this.get("context").$('.overlay-trash-icon i').on('click',function(){
-      
this.get("context").deleteWorkflowNode(this.get("context").$(".overlay-trash-icon").data("node"));
+      var 
incomingNodes=this.get("currentCyNode").incomers("node").jsons().mapBy("data.node");
+      var transitionList=[];
+      var currentNodeId=this.get("currentCyNode").json().data.id;
+      for (var incomingNode of incomingNodes) {
+        for (var incomingTran of incomingNode.transitions ){
+          if (incomingTran.targetNode.id===currentNodeId){
+            incomingTran.sourceNode=incomingNode;
+            transitionList=transitionList.concat(incomingTran);
+           }
+        }
+      }
+      
this.get("context").deleteWorkflowNode(this.get("context").$(".overlay-trash-icon").data("node"),transitionList);
       this.get("context").$('.overlay-node-actions').hide();
     }.bind(this));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
index 92820f9..5a074df 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
@@ -18,6 +18,15 @@
 import Ember from 'ember';
 var defaultNodeColor = '#fff';
 var actionNodeColor = '#f5f5f5';
+var labelFunction=function(target) {
+  if (!target.data().node.name) {
+    return "";
+  } else if (target.data().node.name.length>12){
+    return target.data().node.name.slice(0, 12)+"...";
+  } else{
+    return target.data().node.name;
+  }
+};
 export default Ember.Object.create({
   style: [
     {
@@ -28,15 +37,7 @@ export default Ember.Object.create({
         'border-width': 1,
         'border-color': '#ABABAB',
         //'text-margin-x': 10,
-        label: function(target) {
-          if (!target.data().node.name) {
-            return "";
-          } else if (target.data().node.name.length>12){
-            return target.data().node.name.slice(0, 12)+"...";
-          } else{
-            return target.data().node.name;
-          }
-        },
+        label: labelFunction,
         'text-valign': 'center',
         'font-size': 14,
         height: 40,
@@ -50,13 +51,14 @@ export default Ember.Object.create({
         'background-position-x': 10,
         width: 150
       }
+
     },
     {
       selector: 'node[type = "join"]',
       style: {
         'background-image': 'assets/join.png',
-        label: '',
-        width: 80
+        'background-position-x': 10,
+        width: 150
       }
     },
     {

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/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 b918d70..153b538 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
@@ -71,7 +71,7 @@ var MappingMixin= Ember.Mixin.create({
     }
     actionNode.set("domain",domain);
     Object.keys(json).forEach((propKey)=>{
-       if(!mappings.findBy('xml', propKey) && propKey !=='_xmlns'){
+      if(!mappings.findBy('xml', propKey) && propKey !=='_xmlns'  && propKey 
!=='@id' && propKey !== '__jsogObjectId'){
          domain.unsupportedProperties[propKey] = json[propKey];
          domain[propKey] = json[propKey];
        }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
index 656df4b..fa7a8b8 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
@@ -24,7 +24,7 @@ var WorkflowJsonImporter= Ember.Object.extend({
         return null;
       }
       try{
-        var workflowJson=JSON.parse(workflowJsonStr);
+        var workflowJson=  JSOG.parse(workflowJsonStr);
         var workflow=Workflow.create({});
         workflow.initialize();
         workflow.set("name",workflowJson.name);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js 
b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
index 02842c5..1f02426 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
@@ -51,6 +51,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
     this.set("killNodes",Ember.A([]));
     this.set("globalSetting",null);
     this.set("name","");
+    this.set("draftFormat","jsog");
     this.appendDefaultKillNode();
     src.addTransitionTo(dest);
   },
@@ -102,8 +103,13 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
         sourceNode.addTransitionTo(target,settings.condition);
       }
     }else{
+      //not yet implemented
     }
   },
+  getDefaultKillNode(){
+    var defaultKillNode = 
this.get('killNodes').findBy('name',Constants.defaultKillNodeName);
+    return defaultKillNode ? defaultKillNode : 
this.get('killNodes').objectAt(0);
+  },
   generatedNode(target,type,settings){
     var generatedNode=null;
     if ("decision" === type){
@@ -116,7 +122,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
     }else{
       generatedNode = this.nodeFactory.createActionNode(type);
       generatedNode.addTransitionTo(target);
-      
generatedNode.addTransitionTo(this.get('killNodes').findBy('name',Constants.defaultKillNodeName),
 "error");
+      generatedNode.addTransitionTo(this.getDefaultKillNode(), "error");
     }
     return generatedNode;
   },
@@ -132,7 +138,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
       computedTarget=target.getTargets()[0];
     }
     var generatedNode=this.generatedNode(computedTarget,type,settings);
-    var sourceNode=this.findNodeById(this.startNode,transition.sourceNodeId);
+    var sourceNode=transition.source;
     if (sourceNode.isPlaceholder()){
       var 
orignalTransition=this.findTransitionTo(this.startNode,sourceNode.id);
       orignalTransition.targetNode=generatedNode;
@@ -165,7 +171,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
       status:true
     };
   },
-  deleteNode(node){
+  deleteNode(node,transitionslist){
     var self=this;
     var target=node.getDefaultTransitionTarget();
     if (!target.isEndNode() && (node.isForkNode()|| node.isDecisionNode())){
@@ -177,9 +183,8 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
         target=target.getDefaultTransitionTarget();
       }
     }
-    var transitionslist=this.findTransistionsToNode(node);
     transitionslist.forEach(function(tran){
-      var sourceNode=self.findNodeById(self.startNode,tran.sourceNodeId);
+      var sourceNode=tran.sourceNode;
       var joinNode;
       if (sourceNode.isDecisionNode()){
         joinNode=self.findJoinNode(sourceNode);
@@ -211,8 +216,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
     });
   },
   deleteTransition(transition){
-    var src=this.findNodeById(this.startNode,transition.sourceNodeId);
-    src.removeTransition(transition);
+    transition.sourceNode.removeTransition(transition);
   },
   deleteEmptyTransitions(transitionslist){
     var self=this;

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
 
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
index 0810f64..fae2d3d 100644
--- 
a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
+++ 
b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-action-editor.hbs
@@ -32,7 +32,7 @@
         <div>
             <form class="form-horizontal" id="action_properties">
               {{#if (eq nodeType 'decision')}}
-                {{#decision-config actionModel=actionModel 
register="registerChild"}}{{/decision-config}}
+                {{#decision-config actionModel=actionModel killNodes=killNodes 
register="registerChild"}}{{/decision-config}}
               {{/if}}
               {{#if (eq nodeType 'action')}}
                 {{#if containsUnsupportedProperties}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/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 b66a190..b44a83b 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/bower.json
+++ b/contrib/views/wfmanager/src/main/resources/ui/bower.json
@@ -27,6 +27,7 @@
     "cytoscape-dagre": "^1.3.0",
     "cytoscape-panzoom": "^2.4.0",
     "codemirror": "~5.15.0",
-    "fuse.js": "^2.5.0"
+    "fuse.js": "^2.5.0",
+    "jsog":"1.0.7"
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f8d33765/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 bf48e9c..0979c39 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
@@ -127,6 +127,7 @@ module.exports = function(defaults) {
 
        // Fuse js
        app.import('bower_components/fuse.js/src/fuse.min.js');
+  app.import('bower_components/jsog/lib/JSOG.js');
 
     return app.toTree();
 };

Reply via email to