diff --git a/web/package.json b/web/package.json
index 1e566a540..0849a2955 100644
--- a/web/package.json
+++ b/web/package.json
@@ -66,7 +66,12 @@
     "webpack": "^5.21.2",
     "webpack-bundle-analyzer": "^4.4.0",
     "webpack-cli": "^4.5.0",
-    "yarn-audit-html": "^2.0.0"
+    "yarn-audit-html": "^2.0.0",
+    "@babel/preset-typescript": "^7.8.3",
+    "@babel/plugin-proposal-object-rest-spread": "^7.10.1",
+    "typescript": "^3.2.2",
+    "svgo": "^1.1.1",
+    "svgo-loader": "^2.2.0"
   },
   "dependencies": {
     "@babel/plugin-proposal-class-properties": "^7.10.4",
@@ -144,7 +149,21 @@
     "xterm": "^4.11.0",
     "xterm-addon-fit": "^0.5.0",
     "xterm-addon-search": "^0.8.0",
-    "xterm-addon-web-links": "^0.4.0"
+    "xterm-addon-web-links": "^0.4.0",
+    "pgadmin4-tree": "git+https://github.com/EnterpriseDB/pgadmin4-treeview/#383edc329e2b322a5a646b5db75dd2910c1af2a4",
+    "react-aspen": "^1.1.0",
+    "@types/classnames": "^2.2.6",
+    "@types/react": "^16.7.18",
+    "@types/react-dom": "^16.0.11",
+    "aspen-decorations": "^1.0.2",
+    "browserfs": "^1.4.3",
+    "classnames": "^2.2.6",
+    "context-menu": "^2.0.0",
+    "insert-if": "^1.1.0",
+    "notificar": "^1.0.1",
+    "path-fx": "^2.0.0",
+    "valid-filename": "^2.0.1",
+    "url-loader": "^1.1.2"
   },
   "scripts": {
     "linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js  --ext .jsx .",
diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py
index 7fe8fed80..084fb178a 100644
--- a/web/pgadmin/browser/__init__.py
+++ b/web/pgadmin/browser/__init__.py
@@ -487,7 +487,7 @@ class BrowserPluginModule(PgAdminModule):
         browser tree.
         """
         obj = {
-            "id": "%s/%s" % (node_type, node_id),
+            "id": "%s_%s" % (node_type, node_id),
             "label": label,
             "icon": icon,
             "inode": inode,
diff --git a/web/pgadmin/browser/collection.py b/web/pgadmin/browser/collection.py
index 4155061a3..5b29b9b54 100644
--- a/web/pgadmin/browser/collection.py
+++ b/web/pgadmin/browser/collection.py
@@ -90,7 +90,7 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
             self, node_id, parent_id, label, icon, **kwargs
     ):
         obj = {
-            "id": "%s/%s" % (self.node_type, node_id),
+            "id": "%s_%s" % (self.node_type, node_id),
             "label": label,
             "icon": self.node_icon if not icon else icon,
             "inode": self.node_inode
@@ -107,7 +107,7 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
 
     def generate_browser_collection_node(self, parent_id, **kwargs):
         obj = {
-            "id": "coll-%s/%d" % (self.node_type, parent_id),
+            "id": "coll-%s_%d" % (self.node_type, parent_id),
             "label": self.collection_label,
             "icon": self.collection_icon,
             "inode": True,
diff --git a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js
index 30b2705a9..9820711c9 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js
@@ -134,7 +134,7 @@ define('pgadmin.node.publication', [
 
         canCreate: function(itemData, item) {
 
-          var treeData = this.getTreeNodeHierarchy(item),
+          var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
             server = treeData['server'];
 
           // If server is less than 10 then do not allow 'create' menu
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js
index ad9d9a46f..b83401c4c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js
@@ -80,7 +80,7 @@ define('pgadmin.node.procedure', [
         ]);
       },
       canCreateProc: function(itemData, item) {
-        var node_hierarchy = this.getTreeNodeHierarchy.apply(this, [item]);
+        var node_hierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
         // Do not provide Create option in catalog
         if ('catalog' in node_hierarchy)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
index e70b17956..95a3c5e63 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js
@@ -43,7 +43,7 @@ define('pgadmin.node.trigger_function', [
       label: gettext('Trigger function'),
       collection_type: 'coll-trigger_function',
       canEdit: function(itemData, item) {
-        let node = pgBrowser.treeMenu.findNodeByDomElement(item);
+        let node = pgBrowser.tree.findNodeByDomElement(item);
 
         if (!node || node.parentNode.getData()._type === 'trigger')
           return false;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js
index 94c34b29a..811a76745 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js
@@ -78,7 +78,7 @@ define('pgadmin.node.package', [
         if (data && data.check == false)
           return true;
 
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         if (server && server.server_type === 'pg')
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
index 46e01185d..dbc1e86d7 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js
@@ -409,7 +409,7 @@ define('pgadmin.node.schema', [
     });
 
     pgBrowser.tableChildTreeNodeHierarchy = function(i) {
-      return this.getTreeNodeHierarchy(i);
+      return pgBrowser.tree.getTreeNodeHierarchy(i);
     };
   }
 
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema_child_tree_node.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema_child_tree_node.js
index d62c7f297..f4e107234 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema_child_tree_node.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema_child_tree_node.js
@@ -7,7 +7,9 @@
 //
 /////////////////////////////////////////////////////////////
 
-import * as pgBrowser from 'pgbrowser/browser';
+import pgAdmin from 'sources/pgadmin';
+
+let pgBrowser = pgAdmin.Browser;
 
 export function childCreateMenuEnabled(itemData, item, data) {
   // If check is false then , we will allow create menu
@@ -15,7 +17,7 @@ export function childCreateMenuEnabled(itemData, item, data) {
     return true;
   }
 
-  let node = pgBrowser.treeMenu.findNodeByDomElement(item);
+  let node = pgBrowser.tree.findNodeByDomElement(item);
 
   if (node)
     return node.anyFamilyMember(
@@ -26,7 +28,7 @@ export function childCreateMenuEnabled(itemData, item, data) {
 }
 
 export function isTreeItemOfChildOfSchema(itemData, item) {
-  let node = pgBrowser.treeMenu.findNodeByDomElement(item);
+  let node = pgBrowser.tree.findNodeByDomElement(item);
 
   if (node)
     return isTreeNodeOfSchemaChild(node);
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js
index 36749506f..5fd3b3283 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js
@@ -152,7 +152,7 @@ define('pgadmin.node.synonym', [
         if (data && data.check == false)
           return true;
 
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         if (server && server.server_type === 'pg')
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
index e526302ff..ef27c57fd 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js
@@ -41,7 +41,7 @@ define('pgadmin.node.column', [
       sqlCreateHelp: 'sql-altertable.html',
       dialogHelp: url_for('help.static', {'filename': 'column_dialog.html'}),
       canDrop: function(itemData, item){
-        let node = pgBrowser.treeMenu.findNodeByDomElement(item);
+        let node = pgBrowser.tree.findNodeByDomElement(item);
 
         if (!node)
           return false;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
index 783af99d0..cac03d252 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js
@@ -108,7 +108,7 @@ define('pgadmin.node.compound_trigger', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -146,7 +146,7 @@ define('pgadmin.node.compound_trigger', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -206,7 +206,7 @@ define('pgadmin.node.compound_trigger', [
         if (data && data.check == false)
           return true;
 
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         if (server && (server.server_type === 'pg' || server.version < 120000))
@@ -221,7 +221,7 @@ define('pgadmin.node.compound_trigger', [
       },
       // Check to whether trigger is disable ?
       canCreate_with_compound_trigger_enable: function(itemData, item, data) {
-        var treeData = this.getTreeNodeHierarchy(item);
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item);
         if ('view' in treeData) {
           return false;
         }
@@ -231,7 +231,7 @@ define('pgadmin.node.compound_trigger', [
       },
       // Check to whether trigger is enable ?
       canCreate_with_compound_trigger_disable: function(itemData, item, data) {
-        var treeData = this.getTreeNodeHierarchy(item);
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item);
         if ('view' in treeData) {
           return false;
         }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/static/js/check_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/static/js/check_constraint.js
index 1e1454c7d..d10eace47 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/static/js/check_constraint.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/static/js/check_constraint.js
@@ -64,7 +64,7 @@ define('pgadmin.node.check_constraint', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             var data = d;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
index 75007f685..2d8bb6076 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/static/js/foreign_key.js
@@ -61,7 +61,7 @@ define('pgadmin.node.foreign_key', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             var data = d;
@@ -99,7 +99,7 @@ define('pgadmin.node.foreign_key', [
         var t = pgBrowser.tree, i = item, d = itemData, parents = [],
           immediate_parent_table_found = false,
           is_immediate_parent_table_partitioned = false,
-          s_version = this.getTreeNodeHierarchy(i).server.version;
+          s_version = t.getTreeNodeHierarchy(i).server.version;
 
         // To iterate over tree to check parent node
         while (i) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
index 0a44e7958..f95ab632b 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
@@ -58,7 +58,7 @@ define('pgadmin.node.primary_key', [
         var t = pgBrowser.tree, i = item, d = itemData, parents = [],
           immediate_parent_table_found = false,
           is_immediate_parent_table_partitioned = false,
-          s_version = this.getTreeNodeHierarchy(i).server.version;
+          s_version = t.getTreeNodeHierarchy(i).server.version;
 
         // To iterate over tree to check parent node
         while (i) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js
index d018959ed..7b2a8fe87 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/unique_constraint.js
@@ -57,7 +57,7 @@ define('pgadmin.node.unique_constraint', [
         var t = pgBrowser.tree, i = item, d = itemData, parents = [],
           immediate_parent_table_found = false,
           is_immediate_parent_table_partitioned = false,
-          s_version = this.getTreeNodeHierarchy(i).server.version;
+          s_version = pgBrowser.tree.getTreeNodeHierarchy(i).server.version;
 
         // To iterate over tree to check parent node
         while (i) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js
index e2c43c627..2d1348305 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js
@@ -124,7 +124,7 @@ define('pgadmin.node.index', [
         var t = pgBrowser.tree, i = item, d = itemData, parents = [],
           immediate_parent_table_found = false,
           is_immediate_parent_table_partitioned = false,
-          s_version = this.getTreeNodeHierarchy(i).server.version;
+          s_version = t.getTreeNodeHierarchy(i).server.version;
         // To iterate over tree to check parent node
         while (i) {
           // Do not allow creating index on partitioned tables.
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
index e2816761c..f3696d7be 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js
@@ -116,7 +116,7 @@ function(
         }
 
         info = (_.isUndefined(item) || _.isNull(item)) ?
-          info || {} : this.getTreeNodeHierarchy(item);
+          info || {} : pgBrowser.tree.getTreeNodeHierarchy(item);
 
         return pgadminUtils.sprintf('table/%s/%s/%s/%s/%s/%s',
           encodeURIComponent(type), encodeURIComponent(info['server_group']._id),
@@ -146,7 +146,7 @@ function(
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -188,7 +188,7 @@ function(
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -232,7 +232,7 @@ function(
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -276,7 +276,7 @@ function(
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -294,15 +294,14 @@ function(
                     if (res.success == 1) {
                       Alertify.success(res.info);
                       var n = t.next(i);
-                      if (!n || !n.length) {
+                      if (!n) {
                         n = t.prev(i);
-                        if (!n || !n.length) {
+                        if (!n) {
                           n = t.parent(i);
-                          t.setInode(n, true);
                         }
                       }
                       t.remove(i);
-                      if (n.length) {
+                      if (n) {
                         t.select(n);
                       }
                     }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js
index b9e3ba0b6..f67396aff 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js
@@ -147,7 +147,7 @@ define('pgadmin.node.row_security_policy', [
       }),
       canCreate: function(itemData, item) {
 
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         // If node is under catalog then do not allow 'create' menu
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
index 2c1103f4a..42c306174 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/table.js
@@ -140,7 +140,7 @@ define('pgadmin.node.table', [
         /* Enable trigger(s) on table */
         enable_triggers_on_table: function(args) {
           tableFunctions.enableTriggers(
-            pgBrowser.treeMenu,
+            pgBrowser.tree,
             Alertify,
             this.generate_url.bind(this),
             args
@@ -149,7 +149,7 @@ define('pgadmin.node.table', [
         /* Disable trigger(s) on table */
         disable_triggers_on_table: function(args) {
           tableFunctions.disableTriggers(
-            pgBrowser.treeMenu,
+            pgBrowser.tree,
             Alertify,
             this.generate_url.bind(this),
             args
@@ -174,7 +174,7 @@ define('pgadmin.node.table', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -219,7 +219,7 @@ define('pgadmin.node.table', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -263,7 +263,7 @@ define('pgadmin.node.table', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
           if (!d)
             return false;
 
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
index 2b9904e0d..2067ce267 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js
@@ -102,7 +102,7 @@ define('pgadmin.node.trigger', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -140,7 +140,7 @@ define('pgadmin.node.trigger', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -653,7 +653,7 @@ define('pgadmin.node.trigger', [
       canCreate: SchemaChildTreeNode.isTreeItemOfChildOfSchema,
       // Check to whether trigger is disable ?
       canCreate_with_trigger_enable: function(itemData, item, data) {
-        var treeData = this.getTreeNodeHierarchy(item);
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item);
         if ('view' in treeData) {
           return false;
         }
@@ -663,7 +663,7 @@ define('pgadmin.node.trigger', [
       },
       // Check to whether trigger is enable ?
       canCreate_with_trigger_disable: function(itemData, item, data) {
-        var treeData = this.getTreeNodeHierarchy(item);
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item);
         if ('view' in treeData) {
           return false;
         }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
index abff525b4..a5e31967d 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js
@@ -238,7 +238,7 @@ define('pgadmin.node.mview', [
           obj = this,
           t = pgBrowser.tree,
           i = input.item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined,
+          d = i  ? t.itemData(i) : undefined,
           server_data = null;
 
         if (!d)
@@ -253,7 +253,7 @@ define('pgadmin.node.mview', [
           }
 
           if (pgBrowser.tree.hasParent(j)) {
-            j = $(pgBrowser.tree.parent(j));
+            j = pgBrowser.tree.parent(j);
           } else {
             Alertify.alert(gettext('Please select server or child node from tree.'));
             break;
@@ -316,9 +316,7 @@ define('pgadmin.node.mview', [
       is_version_supported: function(data, item) {
         var t = pgAdmin.Browser.tree,
           i = item || t.selected(),
-          d = data || (i && i.length == 1 ? t.itemData(i): undefined),
-          node = this || (d && pgAdmin.Browser.Nodes[d._type]),
-          info = node && node.getTreeNodeHierarchy.apply(node, [i]),
+          info = t && t.getTreeNodeHierarchy(i),
           version = _.isUndefined(info) ? 0 : info.server.version;
 
         // disable refresh concurrently if server version is 9.3
diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
index 5485b0183..522cc9035 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
@@ -106,13 +106,13 @@ define('pgadmin.node.database', [
         );
       },
       can_create_database: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         return server.connected && server.user.can_create_db;
       },
       canCreate: function(itemData, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         // If server is less than 10 then do not allow 'create' menu
@@ -201,7 +201,7 @@ define('pgadmin.node.database', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d && d.label != 'template0') {
             connect_to_database(obj, d, t, i, true);
@@ -214,7 +214,7 @@ define('pgadmin.node.database', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             Alertify.confirm(
@@ -238,7 +238,6 @@ define('pgadmin.node.database', [
                       data.icon = 'icon-database-not-connected';
                       t.addIcon(i, {icon: data.icon});
                       t.unload(i);
-                      t.setInode(i);
                       setTimeout(function() {
                         t.select(prv_i);
                       }, 10);
@@ -272,7 +271,7 @@ define('pgadmin.node.database', [
           var input = args || {},
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i ? t.itemData(i) : undefined;
           pgBrowser.erd.showErdTool(d, i, true);
         },
 
diff --git a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js
index 0b684ee42..e05002944 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js
@@ -158,7 +158,7 @@ define('pgadmin.node.subscription', [
           return pgBrowser.DataModel.prototype.sessChanged.apply(this);
         },
         canCreate: function(itemData, item) {
-          var treeData = this.getTreeNodeHierarchy(item),
+          var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
             server = treeData['server'];
 
           // If server is less than 10 then do not allow 'create' menu
diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job.js b/web/pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job.js
index 8d0641855..083a18074 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job.js
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/static/js/pga_job.js
@@ -114,7 +114,7 @@ define('pgadmin.node.pga_job', [
           obj = this,
           t = pgBrowser.tree,
           i = input.item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i  ? t.itemData(i) : undefined;
 
         if (d) {
           $.ajax({
diff --git a/web/pgadmin/browser/server_groups/servers/resource_groups/static/js/resource_group.js b/web/pgadmin/browser/server_groups/servers/resource_groups/static/js/resource_group.js
index bfb32bfec..95a53b03a 100644
--- a/web/pgadmin/browser/server_groups/servers/resource_groups/static/js/resource_group.js
+++ b/web/pgadmin/browser/server_groups/servers/resource_groups/static/js/resource_group.js
@@ -56,7 +56,7 @@ define('pgadmin.node.resource_group', [
            * Resource Group only supported in PPAS 9.4 and above.
            */
           enable: function(node, item) {
-            var treeData = this.getTreeNodeHierarchy(item),
+            var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
               server = treeData['server'];
             return server.connected && node.server_type === 'ppas' &&
               node.version >= 90400;
diff --git a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
index 279371ecc..c18e7c2c1 100644
--- a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
+++ b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js
@@ -46,7 +46,7 @@ define('pgadmin.node.role', [
       hasSQL: true,
       width: '550px',
       canDrop: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
           /*
         To Drop a role:
@@ -114,13 +114,13 @@ define('pgadmin.node.role', [
         }]);
       },
       can_create_role: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         return server.connected && server.user.can_create_role;
       },
       can_reassign_role: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         return server.connected && node.can_login;
@@ -444,7 +444,7 @@ define('pgadmin.node.role', [
                 if (!_d)
                   return;
                 // Create treeInfo
-                var treeInfo = node.getTreeNodeHierarchy.apply(node, [_i]);
+                var treeInfo = pgBrowser.tree.getTreeNodeHierarchy(_i);
                 // Instance of backbone model
                 var newModel = new RoleReassignObjectModel({}, {node_info: treeInfo}),
                   fields = Backform.generateViewSchema(
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js
index 0111eb286..bd0f5191b 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/server.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js
@@ -227,7 +227,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             connect_to_server(obj, d, t, i, false);
@@ -240,7 +240,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = 'item' in input ? input.item : t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i ? t.itemData(i) : undefined;
 
           if (d) {
             notify = notify || _.isUndefined(notify) || _.isNull(notify);
@@ -263,6 +263,7 @@ define('pgadmin.node.server', [
                     }
                     t.addIcon(i, {icon: d.icon});
                     obj.callbacks.refresh.apply(obj, [null, i]);
+                    t.close(i);
                     if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
                       delete pgBrowser.serverInfo[d._id];
                     }
@@ -332,7 +333,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i ? t.itemData(i) : undefined;
 
           if (d) {
             Alertify.confirm(
@@ -368,7 +369,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -409,7 +410,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
+            d = i  ? t.itemData(i) : undefined,
             url = obj.generate_url(i, 'change_password', d, true),
             is_pgpass_file_used = false,
             check_pgpass_url = obj.generate_url(i, 'check_pgpass', d, true);
@@ -591,7 +592,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -626,7 +627,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (!d)
             return false;
@@ -661,7 +662,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             Alertify.confirm(
@@ -698,7 +699,7 @@ define('pgadmin.node.server', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
 
           if (d) {
             Alertify.confirm(
@@ -733,7 +734,7 @@ define('pgadmin.node.server', [
           var input = args || {},
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i  ? t.itemData(i) : undefined;
           pgBrowser.psql.psql_tool(d, i, true);
         }
       },
@@ -848,7 +849,7 @@ define('pgadmin.node.server', [
           // It should be attempt to reconnect.
           // Let's not change the status of the tree node now.
           if (!_wasConnected) {
-            tree.setInode(_item);
+            tree.close(_item);
             if (_data.shared && pgAdmin.server_mode == 'True'){
               tree.addIcon(_item, {icon: 'icon-shared-server-not-connected'});
             }else{
@@ -922,7 +923,6 @@ define('pgadmin.node.server', [
             // We're not reconnecting
             if (!_wasConnected) {
               _tree.setInode(_item);
-              _tree.deselect(_item);
 
               setTimeout(function() {
                 _tree.select(_item);
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js b/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
index e5c0a8a76..80ff07685 100644
--- a/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
@@ -84,13 +84,13 @@ define('pgadmin.node.tablespace', [
         ]);
       },
       can_create_tablespace: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
 
         return server.connected && server.user.is_superuser;
       },
       can_move_objects: function(node, item) {
-        var treeData = this.getTreeNodeHierarchy(item),
+        var treeData = pgBrowser.tree.getTreeNodeHierarchy(item),
           server = treeData['server'];
         // Only supported PG9.4 and above version
         return server.connected &&
@@ -104,7 +104,7 @@ define('pgadmin.node.tablespace', [
             obj = this,
             t = pgBrowser.tree,
             i = input.item || t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
+            d = i  ? t.itemData(i) : undefined,
             url = obj.generate_url(i, 'move_objects', d, true),
             msql_url = obj.generate_url(i, 'move_objects_sql', d, true);
 
@@ -243,7 +243,7 @@ define('pgadmin.node.tablespace', [
                   if (!_d)
                     return;
                   // Create treeInfo
-                  var treeInfo = node.getTreeNodeHierarchy.apply(node, [_i]);
+                  var treeInfo = pgAdmin.tree.getTreeNodeHierarchy.apply(node, [_i]);
                   // Instance of backbone model
                   var newModel = new objModel({}, {node_info: treeInfo, selected_ts: _d.label}),
                     fields = Backform.generateViewSchema(
diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js
index bdab52993..c62704f00 100644
--- a/web/pgadmin/browser/static/js/browser.js
+++ b/web/pgadmin/browser/static/js/browser.js
@@ -8,11 +8,11 @@
 //////////////////////////////////////////////////////////////
 
 define('pgadmin.browser', [
-  'sources/tree/tree',
   'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore',
   'bootstrap', 'sources/pgadmin', 'pgadmin.alertifyjs', 'bundled_codemirror',
   'sources/check_node_visibility', './toolbar', 'pgadmin.help',
   'sources/csrf', 'sources/utils', 'sources/window', 'pgadmin.authenticate.kerberos',
+  'sources/tree/tree_init',
   'pgadmin.browser.utils', 'wcdocker', 'jquery.contextmenu', 'jquery.aciplugin',
   'jquery.acitree',
   'pgadmin.browser.preferences', 'pgadmin.browser.messages',
@@ -23,11 +23,10 @@ define('pgadmin.browser', [
   'pgadmin.browser.keyboard', 'sources/tree/pgadmin_tree_save_state','jquery.acisortable',
   'jquery.acifragment',
 ], function(
-  tree,
   gettext, url_for, require, $, _,
   Bootstrap, pgAdmin, Alertify, codemirror,
   checkNodeVisibility, toolBar, help, csrfToken, pgadminUtils, pgWindow,
-  Kerberos
+  Kerberos, InitTree,
 ) {
   window.jQuery = window.$ = $;
   // Some scripts do export their object in the window only.
@@ -48,7 +47,7 @@ define('pgadmin.browser', [
     if (this.isVisible()) {
       var obj = pgAdmin.Browser,
         i   = obj.tree ? obj.tree.selected() : undefined,
-        d   = i && i.length == 1 ? obj.tree.itemData(i) : undefined;
+        d   = i ? obj.tree.itemData(i) : undefined;
 
       if (d && obj.Nodes[d._type].callbacks['selected'] &&
         _.isFunction(obj.Nodes[d._type].callbacks['selected'])) {
@@ -58,98 +57,52 @@ define('pgadmin.browser', [
     }
   };
 
-  var processTreeData = function(payload) {
-    var data = JSON.parse(payload).data;
-    if (data.length && data[0]._type !== 'column' &&
-      data[0]._type !== 'catalog_object_column') {
-      data.sort(function(a, b) {
-        return pgAdmin.natural_sort(a.label, b.label);
-      });
-    }
-    _.each(data, function(d){
-      d._label = d.label;
-      d.label = _.escape(d.label);
-    });
-    return data;
-  };
-
   var initializeBrowserTree = pgAdmin.Browser.initializeBrowserTree =
     function(b) {
-      $('#tree').aciTree({
-        ajax: {
-          url: url_for('browser.nodes'),
-          converters: {
-            'text json': processTreeData,
+      InitTree.initBrowserTree(b).then(() => {
+        b.tree.registerDraggableType({
+          'collation domain domain_constraints fts_configuration fts_dictionary fts_parser fts_template synonym table partition type sequence package view mview foreign_table edbvar' : (data, item)=>{
+            return pgadminUtils.fully_qualify(b, data, item);
           },
-        },
-        ajaxHook: function(item, settings) {
-          if (item != null) {
-            var d = this.itemData(item);
-            var n = b.Nodes[d._type];
-            if (n)
-              settings.url = n.generate_url(item, 'children', d, true);
-          }
-        },
-        loaderDelay: 100,
-        show: {
-          duration: 75,
-        },
-        hide: {
-          duration: 75,
-        },
-        view: {
-          duration: 75,
-        },
-        animateRoot: true,
-        unanimated: false,
-        fullRow: true,
-      });
-
-      b.tree = $('#tree').aciTree('api');
-      b.treeMenu.register($('#tree'));
+          'schema column database cast event_trigger extension language foreign_data_wrapper foreign_server user_mapping compound_trigger index index_constraint primary_key unique_constraint check_constraint exclusion_constraint foreign_key rule' : (data)=>{
+            return pgadminUtils.quote_ident(data._label);
+          },
+          'trigger trigger_function' : (data)=>{
+            return data._label;
+          },
+          'edbfunc function edbproc procedure' : (data, item)=>{
+            let newData = {...data},
+              parsedFunc = null,
+              dropVal = '',
+              curPos = {from: 0, to: 0};
+
+            parsedFunc = pgadminUtils.parseFuncParams(newData._label);
+            newData._label = parsedFunc.func_name;
+            dropVal = pgadminUtils.fully_qualify(b, newData, item);
+
+            if(parsedFunc.params.length > 0) {
+              dropVal = dropVal + '(';
+              curPos.from =  dropVal.length;
+              dropVal = dropVal + parsedFunc.params[0][0];
+              curPos.to = dropVal.length;
+
+              for(let i=1; i<parsedFunc.params.length; i++) {
+                dropVal = dropVal + ', ' + parsedFunc.params[i][0];
+              }
 
-      b.treeMenu.registerDraggableType({
-        'collation domain domain_constraints fts_configuration fts_dictionary fts_parser fts_template synonym table partition type sequence package view mview foreign_table edbvar' : (data, item)=>{
-          return pgadminUtils.fully_qualify(b, data, item);
-        },
-        'schema column database cast event_trigger extension language foreign_data_wrapper foreign_server user_mapping compound_trigger index index_constraint primary_key unique_constraint check_constraint exclusion_constraint foreign_key rule' : (data)=>{
-          return pgadminUtils.quote_ident(data._label);
-        },
-        'trigger trigger_function' : (data)=>{
-          return data._label;
-        },
-        'edbfunc function edbproc procedure' : (data, item)=>{
-          let newData = {...data},
-            parsedFunc = null,
-            dropVal = '',
-            curPos = {from: 0, to: 0};
-
-          parsedFunc = pgadminUtils.parseFuncParams(newData._label);
-          newData._label = parsedFunc.func_name;
-          dropVal = pgadminUtils.fully_qualify(b, newData, item);
-
-          if(parsedFunc.params.length > 0) {
-            dropVal = dropVal + '(';
-            curPos.from =  dropVal.length;
-            dropVal = dropVal + parsedFunc.params[0][0];
-            curPos.to = dropVal.length;
-
-            for(let i=1; i<parsedFunc.params.length; i++) {
-              dropVal = dropVal + ', ' + parsedFunc.params[i][0];
+              dropVal = dropVal + ')';
+            } else {
+              dropVal = dropVal + '()';
+              curPos.from = curPos.to = dropVal.length + 1;
             }
 
-            dropVal = dropVal + ')';
-          } else {
-            dropVal = dropVal + '()';
-            curPos.from = curPos.to = dropVal.length + 1;
-          }
-
-          return {
-            text: dropVal,
-            cur: curPos,
-          };
-        },
-      });
+            return {
+              text: dropVal,
+              cur: curPos,
+            };
+          },
+        });
+      }, () => {console.warn('Tree Load Error');});
     };
 
   // Extend the browser class attributes
@@ -164,7 +117,6 @@ define('pgadmin.browser', [
     editor:null,
     // Left hand browser tree
     tree:null,
-    treeMenu: new tree.Tree(),
     // list of script to be loaded, when a certain type of node is loaded
     // It will be used to register extensions, tools, child node scripts,
     // etc.
@@ -232,8 +184,9 @@ define('pgadmin.browser', [
         icon: '',
         limit: 1,
         content: '<div id="tree" class="aciTree"></div>',
-        onCreate: function(panel) {
+        onCreate: function(panel, $container) {
           toolBar.initializeToolbar(panel, wcDocker);
+          $container.addClass('pg-no-overflow');
         },
       }),
       // Properties of the object node
@@ -387,7 +340,7 @@ define('pgadmin.browser', [
         // Drop down menu for objects
         $obj_mnu = navbar.find('li#mnu_obj .dropdown-menu').first(),
         // data for current selected object
-        d = obj.tree.itemData(item),
+        d = item ? obj.tree.itemData(item) : undefined,
         update_menuitem = function(m) {
           if (m instanceof pgAdmin.Browser.MenuItem) {
             m.update(d, item);
@@ -473,6 +426,8 @@ define('pgadmin.browser', [
         });
       }
 
+      initializeBrowserTree(obj);
+
       // Syntax highlight the SQL Pane
       obj.editor = CodeMirror.fromTextArea(
         document.getElementById('sql-textarea'), {
@@ -503,12 +458,9 @@ define('pgadmin.browser', [
         obj.editor.refresh();
       }, 10);
 
-      // Initialise the treeview
-      initializeBrowserTree(obj);
-
       // Build the treeview context menu
       $('#tree').contextMenu({
-        selector: '.aciTreeLine',
+        selector: '.file-entry',
         autoHide: false,
         build: function(element) {
           var item = obj.tree.itemFrom(element),
@@ -534,47 +486,6 @@ define('pgadmin.browser', [
         },
       });
 
-      // Treeview event handler
-      $('#tree').on('acitree', function(event, api, item, eventName, options) {
-        var d = item ? obj.tree.itemData(item) : null;
-        var node;
-
-        if (d && obj.Nodes[d._type]) {
-          node = obj.Nodes[d._type];
-
-          /* If the node specific callback returns false, we will also return
-           * false for further processing.
-           */
-          if (_.isObject(node.callbacks) &&
-            eventName in node.callbacks &&
-              typeof node.callbacks[eventName] == 'function' &&
-              !node.callbacks[eventName].apply(
-                node, [item, d, obj, options, eventName])) {
-            return false;
-          }
-          /* Raise tree events for the nodes */
-          try {
-            node.trigger(
-              'browser-node.' + eventName, node, item, d
-            );
-          } catch (e) {
-            console.warn(e.stack || e);
-          }
-        }
-
-        try {
-          obj.Events.trigger(
-            'pgadmin-browser:tree', eventName, item, d
-          );
-          obj.Events.trigger(
-            'pgadmin-browser:tree:' + eventName, item, d, node
-          );
-        } catch (e) {
-          console.warn(e.stack || e);
-        }
-        return true;
-      });
-
       // Register scripts and add menus
       pgBrowser.utils.registerScripts(this);
       pgBrowser.utils.addMenus(obj);
@@ -597,7 +508,7 @@ define('pgadmin.browser', [
       obj.check_corrupted_db_file();
       obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode, obj);
       obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode, obj);
-      obj.Events.on('pgadmin:browser:tree:refresh', obj.onRefreshTreeNode, obj);
+      obj.Events.on('pgadmin:browser:tree:refresh', obj.onRefreshTreeNodeReact, obj);
       obj.Events.on('pgadmin-browser:tree:loadfail', obj.onLoadFailNode, obj);
 
       obj.bind_beforeunload();
@@ -937,7 +848,7 @@ define('pgadmin.browser', [
     showHelp: function(type, url, node, item) {
       if (type == 'object_help') {
         // Construct the URL
-        var server = node.getTreeNodeHierarchy(item).server;
+        var server = pgBrowser.tree.getTreeNodeHierarchy(item).server;
         var baseUrl = pgBrowser.utils.pg_help_path;
         if (server.server_type == 'ppas') {
           baseUrl = pgBrowser.utils.edbas_help_path;
@@ -962,7 +873,7 @@ define('pgadmin.browser', [
           var items = _o.t.children(_i),
             i, d, n, idx = 0, size = items.length;
           for (; idx < size; idx++) {
-            i = items.eq(idx);
+            i = items[idx];
             d = _o.t.itemData(i);
             if (d._type === _d._type) {
               if (!_o.hasId || d._id == _d._id) {
@@ -998,19 +909,17 @@ define('pgadmin.browser', [
         };
 
       if (!loaded && _o.load) {
-        _o.t.open(_i, {
-          success: onLoad,
-          unanimated: true,
-          fail: function() {
+        _o.t.open(_i).then(
+          () => {
+            onLoad();
+          },
+          () => {
             var fail = _o && _o.o && _o.o.fail;
-
-            if (
-              fail && typeof(fail) == 'function'
-            ) {
+            if (fail && typeof(fail) == 'function') {
               fail.apply(_o.t, []);
             }
-          },
-        });
+          }
+        );
       } else if (loaded) {
         onLoad();
       } else {
@@ -1089,7 +998,7 @@ define('pgadmin.browser', [
                 s = 0, e = items.length - 1, i,
                 linearSearch = function() {
                   while (e >= s) {
-                    i = items.eq(s);
+                    i = items[s];
                     var d = __ctx.t.itemData(i);
                     if (d._type === 'column') {
                       if (pgAdmin.numeric_comparator(d._id, _data._id) == 1)
@@ -1102,7 +1011,7 @@ define('pgadmin.browser', [
                   }
                   //when the current element is greater than the end element
                   if (e != items.length - 1) {
-                    i = items.eq(e+1);
+                    i = items[e+1];
                     return true;
                   }
                   i = null;
@@ -1116,7 +1025,7 @@ define('pgadmin.browser', [
                   //
                   // We will try until it's half.
                   while (e - s > 22) {
-                    i = items.eq(s);
+                    i = items[s];
                     d = __ctx.t.itemData(i);
                     if (d._type === 'column') {
                       if (pgAdmin.numeric_comparator(d._id, _data._id) != -1)
@@ -1125,7 +1034,7 @@ define('pgadmin.browser', [
                       if (pgAdmin.natural_sort(d._label, _data._label) != -1)
                         return true;
                     }
-                    i = items.eq(e);
+                    i = items[e];
                     d = __ctx.t.itemData(i);
                     let result;
                     if (d._type === 'column') {
@@ -1135,14 +1044,14 @@ define('pgadmin.browser', [
                     }
                     if (result !=1) {
                       if (e != items.length - 1) {
-                        i = items.eq(e+1);
+                        i = items[e+1];
                         return true;
                       }
                       i = null;
                       return false;
                     }
                     m = s + Math.round((e - s) / 2);
-                    i = items.eq(m);
+                    i = items[m];
                     d = __ctx.t.itemData(i);
                     if(d._type === 'column'){
                       result = pgAdmin.numeric_comparator(d._id, _data._id);
@@ -1190,10 +1099,8 @@ define('pgadmin.browser', [
                     is_parent_loaded_before = ___ctx.t.wasLoad(___ctx.i),
                     _parent_data = ___ctx.t.itemData(___ctx.i);
 
-                  ___ctx.t.append(___ctx.i, {
-                    itemData: _data,
-                    success: function(item, options) {
-                      var _i = $(options.items[0]);
+                  ___ctx.t.append(___ctx.i, _data).then(
+                    (_i) => {
                       // Open the item path only if its parent is loaded
                       // or parent type is same as nodes
                       if(
@@ -1202,18 +1109,17 @@ define('pgadmin.browser', [
                           _data._type
                         ) > -1
                       ) {
-                        ___ctx.t.openPath(_i);
+                        ___ctx.t.open(___ctx.i);
                         ___ctx.t.select(_i);
                       } else {
                         if (_parent_data) {
                           // Unload the parent node so that we'll get
                           // latest data when we try to expand it
-                          ___ctx.t.unload(___ctx.i, {
-                            success: function (_item) {
-                              // Lets try to load it now
-                              ___ctx.t.open(_item);
-                            },
-                          });
+                          ___ctx.t.unload(___ctx.i).then(
+                            () => {
+                              ___ctx.t.open(___ctx.i);
+                            }
+                          );
                         }
                       }
                       if (
@@ -1223,7 +1129,7 @@ define('pgadmin.browser', [
                         ___ctx.o.success.apply(___ctx.t, [_i, _data]);
                       }
                     },
-                    fail: function() {
+                    () => {
                       console.warn('Failed to append...', arguments);
                       if (
                         ___ctx.o && ___ctx.o.fail &&
@@ -1231,12 +1137,16 @@ define('pgadmin.browser', [
                       ) {
                         ___ctx.o.fail.apply(___ctx.t, [___ctx.i, _data]);
                       }
-                    },
-                  });
+                    }
+                  );
                 }.bind(__ctx);
 
                 if (__ctx.i && !__ctx.t.isInode(__ctx.i)) {
-                  __ctx.t.setInode(__ctx.i, {success: _append});
+                  __ctx.t.setInode(__ctx.i).then(
+                    () => {
+                      _append();
+                    }
+                  );
                 } else {
                   // Handle case for node without parent i.e. server-group
                   // or if parent node's inode is true.
@@ -1247,28 +1157,26 @@ define('pgadmin.browser', [
 
           // Parent node do not have any children, let me unload it.
           if (!first && _ctx.t.wasLoad(_ctx.i)) {
-            _ctx.t.unload(_ctx.i, {
-              success: function() {
-                findChildNode(
-                  selectNode,
-                  function() {
-                    var o = this && this.o;
-                    if (
-                      o && o.fail && typeof(o.fail) == 'function'
-                    ) {
-                      o.fail.apply(this.t, [this.i, _data]);
-                    }
-                  }.bind(this)
-                );
-              }.bind(this),
-              fail: function() {
-                var o = this && this.o;
-                if (
-                  o && o.fail && typeof(o.fail) == 'function'
-                ) {
-                  o.fail.apply(this.t, [this.i, _data]);
-                }
-              }.bind(this),
+            _ctx.t.unload(_ctx.i).then(() => {
+              findChildNode(
+                selectNode,
+                function() {
+                  var o = this && this.o;
+                  if (
+                    o && o.fail && typeof(o.fail) == 'function'
+                  ) {
+                    o.fail.apply(this.t, [this.i, _data]);
+                  }
+                }.bind(this)
+              );
+            },
+            () => {
+              var o = this && this.o;
+              if (
+                o && o.fail && typeof(o.fail) == 'function'
+              ) {
+                o.fail.apply(this.t, [this.i, _data]);
+              }
             });
             return;
           }
@@ -1342,7 +1250,8 @@ define('pgadmin.browser', [
               && this.t.parent(this.i)) || null,
             _item_grand_parent = _item_parent ?
               (this.t.hasParent(_item_parent)
-              && this.t.parent(_item_parent))
+              && this.t.parent(_item_parent) &&
+              _item_parent.root != this.t.parent(_item_parent))
               : null;
 
           // Remove the current node first.
@@ -1358,13 +1267,13 @@ define('pgadmin.browser', [
             } else {
               var postRemove = function() {
                 // If item has parent but no grand parent
-                if (_item_parent && !_item_grand_parent) {
+                if (_item_parent.path !== '/browser' && !_item_grand_parent) {
                   var parent = null;
                   // We need to search in all parent siblings (eg: server groups)
                   var parents = this.t.siblings(this.i) || [];
-                  parents.push(this.i[0]);
+                  parents.push(this.i);
                   _.each(parents, function (p) {
-                    var d = self.t.itemData($(p));
+                    var d = self.t.itemData(p);
                     // If new server group found then assign it parent
                     if(d._id == self.new._pid) {
                       parent = p;
@@ -1383,7 +1292,6 @@ define('pgadmin.browser', [
                     this.notFound = errorOut;
 
                     // var _d = {_id: this.new._pid, _type: self.d._type};
-                    parent = $(parent);
                     var loaded = this.t.wasLoad(parent),
                       onLoad = function() {
                         self.i = parent;
@@ -1393,19 +1301,19 @@ define('pgadmin.browser', [
                       };
 
                     if (!loaded && self.load) {
-                      self.t.open(parent, {
-                        success: onLoad,
-                        unanimated: true,
-                        fail: function() {
+                      self.t.open(parent).then(
+                        () => {
+                          onLoad();
+                        },
+                        () => {
                           var fail = self && self.o && self.o.fail;
-
                           if (
                             fail && typeof(fail) == 'function'
                           ) {
                             fail.apply(self.t, []);
                           }
-                        },
-                      });
+                        }
+                      );
                     } else {
                       onLoad();
                     }
@@ -1438,30 +1346,17 @@ define('pgadmin.browser', [
                 }
               }.bind(this);
 
-              // If there is a parent then we can remove the node
-              this.t.remove(this.i, {
-                success: function() {
-                  // Find the parent
-                  findParent();
-                  // If server group have no children then close it and set inode
-                  // and unload it so it can fetch new data on next expand
-                  if (_item_parent && !_item_grand_parent && _parent
+              this.t.remove(this.i).then(() => {
+                findParent();
+                if (_item_parent && !_item_grand_parent && _parent
                     && self.t.children(_parent).length == 0) {
-                    self.t.setInode(_parent, {
-                      success: function() {
-                        self.t.unload(_parent, {success: function() {
-                          setTimeout(postRemove);
-                        }}
-                        );
-                      },
-                    });
-                  } else {
-                    setTimeout(postRemove);
-                  }
-                  return true;
-                },
-              }
-              );
+                  self.t.unload(_parent).then( () => { setTimeout(postRemove); });
+                }
+                else {
+                  setTimeout(postRemove);
+                }
+                return true;
+              });
             }
 
           }
@@ -1605,7 +1500,7 @@ define('pgadmin.browser', [
                 s = 0, e = items.length - 1, i,
                 linearSearch = function() {
                   while (e >= s) {
-                    i = items.eq(s);
+                    i = items[s];
                     var d = __ctx.t.itemData(i);
                     if (d._type === 'column') {
                       if (pgAdmin.numeric_comparator(d._id, _new._id) == 1)
@@ -1617,7 +1512,7 @@ define('pgadmin.browser', [
                     s++;
                   }
                   if (e != items.length - 1) {
-                    i = items.eq(e+1);
+                    i = items[e+1];
                     return true;
                   }
                   i = null;
@@ -1625,7 +1520,7 @@ define('pgadmin.browser', [
                 },
                 binarySearch = function() {
                   while (e - s > 22) {
-                    i = items.eq(s);
+                    i = items[s];
                     var d = __ctx.t.itemData(i);
                     if (d._type === 'column') {
                       if (pgAdmin.numeric_comparator(d._id, _new._id) != -1)
@@ -1634,7 +1529,7 @@ define('pgadmin.browser', [
                       if (pgAdmin.natural_sort(d._label, _new._label) != -1)
                         return true;
                     }
-                    i = items.eq(e);
+                    i = items[e];
                     d = __ctx.t.itemData(i);
                     let result;
                     if (d._type === 'column') {
@@ -1644,14 +1539,14 @@ define('pgadmin.browser', [
                     }
                     if (result !=1) {
                       if (e != items.length - 1) {
-                        i = items.eq(e+1);
+                        i = items[e+1];
                         return true;
                       }
                       i = null;
                       return false;
                     }
                     var m = s + Math.round((e - s) / 2);
-                    i = items.eq(m);
+                    i = items[m];
                     d = __ctx.t.itemData(i);
                     if(d._type === 'column'){
                       result = pgAdmin.numeric_comparator(d._id, _new._id);
@@ -1698,9 +1593,8 @@ define('pgadmin.browser', [
                 });
               } else {
                 var _appendNode = function() {
-                  __ctx.t.append(__ctx.i, {
-                    itemData: _new,
-                    success: function() {
+                  __ctx.t.append(__ctx.i, _new).then(
+                    () => {
                       var new_item = $(arguments[1].items[0]);
                       __ctx.t.openPath(new_item);
                       __ctx.t.select(new_item);
@@ -1710,7 +1604,7 @@ define('pgadmin.browser', [
                         __ctx.o.success.apply(__ctx.t, [__ctx.i, _old, _new]);
                       }
                     },
-                    fail: function() {
+                    () => {
                       console.warn('Failed to append...', arguments);
                       if (
                         __ctx.o && __ctx.o.fail && typeof(__ctx.o.fail) == 'function'
@@ -1718,7 +1612,7 @@ define('pgadmin.browser', [
                         __ctx.o.fail.apply(__ctx.t, [__ctx.i, _old, _new]);
                       }
                     },
-                  });
+                  );
                 };
 
                 // If the current node's inode is false
@@ -1735,29 +1629,28 @@ define('pgadmin.browser', [
 
           // Parent node do not have any children, let me unload it.
           if (!first && _ctx.t.wasLoad(_ctx.i)) {
-            _ctx.t.unload(_ctx.i, {
-              success: function() {
-                findChildNode(
-                  selectNode,
-                  function() {
-                    var o = this && this.o;
-                    if (
-                      o && o.fail && typeof(o.fail) == 'function'
-                    ) {
-                      o.fail.apply(this.t, [this.i, _old, _new]);
-                    }
-                  }.bind(this)
-                );
-              }.bind(this),
-              fail: function() {
-                var o = this && this.o;
-                if (
-                  o && o.fail && typeof(o.fail) == 'function'
-                ) {
-                  o.fail.apply(this.t, [this.i, _old, _new]);
+            _ctx.t.unload(_ctx.i).then( () => {
+              findChildNode(
+                selectNode,
+                function() {
+                  var o = this && this.o;
+                  if (
+                    o && o.fail && typeof(o.fail) == 'function'
+                  ) {
+                    o.fail.apply(this.t, [this.i, _old, _new]);
+                  }
                 }
-              }.bind(this),
-            });
+              );
+            },
+            () => {
+              var o = this && this.o;
+              if (
+                o && o.fail && typeof(o.fail) == 'function'
+              ) {
+                o.fail.apply(this.t, [this.i, _old, _new]);
+              }
+            }
+            );
             return;
           }
 
@@ -1799,6 +1692,10 @@ define('pgadmin.browser', [
       }
     },
 
+    onRefreshTreeNodeReact: function(_i) {
+      this.tree.refresh(_i);
+    },
+
     onRefreshTreeNode: function(_i, _opts) {
       var _d = _i && this.tree.itemData(_i),
         n = _d && _d._type && this.Nodes[_d._type],
@@ -2034,10 +1931,10 @@ define('pgadmin.browser', [
 
       if (_selectNext) {
         nodeToSelect = tree_local.next(_node);
-        if (!nodeToSelect || !nodeToSelect.length) {
+        if (!nodeToSelect) {
           nodeToSelect = tree_local.prev(_node);
 
-          if (!nodeToSelect || !nodeToSelect.length) {
+          if (!nodeToSelect) {
             if (!_parentNode) {
               nodeToSelect = tree_local.parent(_node);
             } else {
@@ -2048,6 +1945,7 @@ define('pgadmin.browser', [
         if (nodeToSelect)
           tree_local.select(nodeToSelect);
       }
+
       tree_local.remove(_node);
       return true;
     },
diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js
index 289a54758..cb45e68a2 100644
--- a/web/pgadmin/browser/static/js/collection.js
+++ b/web/pgadmin/browser/static/js/collection.js
@@ -99,7 +99,7 @@ define([
           $msgContainer = '',
           // This will be the URL, used for object manipulation.
           urlBase = this.generate_url(item, 'properties', data),
-          info = this.getTreeNodeHierarchy.apply(this, [item]),
+          info = pgBrowser.tree.getTreeNodeHierarchy(item),
           gridSchema = Backform.generateGridColumnsFromModel(
             info, node.model, 'properties', that.columns
           ),
@@ -496,7 +496,7 @@ define([
         var collectionPickFunction = function (treeInfoValue, treeInfoKey) {
           return (treeInfoKey != self.type);
         };
-        var treeInfo = this.getTreeNodeHierarchy(item);
+        var treeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
         var actionType = type in opURL ? opURL[type] : type;
         return generateUrl.generate_url(
           pgAdmin.Browser.URL, treeInfo, actionType, self.node,
@@ -517,7 +517,7 @@ define([
         var input = args || {},
           t = pgBrowser.tree,
           i = input.item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i ? t.itemData(i) : undefined;
         pgBrowser.psql.psql_tool(d, i, true);
       },
     });
diff --git a/web/pgadmin/browser/static/js/keyboard.js b/web/pgadmin/browser/static/js/keyboard.js
index a69c7009f..7040b5e25 100644
--- a/web/pgadmin/browser/static/js/keyboard.js
+++ b/web/pgadmin/browser/static/js/keyboard.js
@@ -244,7 +244,7 @@ _.extend(pgBrowser.keyboardNavigation, {
     const tree = this.getTreeDetails();
 
     $('#tree').trigger('focus');
-    tree.t.focus(tree.i);
+    // tree.t.focus(tree.i);
     tree.t.select(tree.i);
   },
   bindSubMenuQueryTool: function() {
@@ -370,8 +370,8 @@ _.extend(pgBrowser.keyboardNavigation, {
   },
   getTreeDetails: function() {
     const aciTree = pgAdmin.Browser.tree;
-    const selectedTreeNode = aciTree.selected().length > 0 ? aciTree.selected() : aciTree.first();
-    const selectedTreeNodeData = selectedTreeNode && selectedTreeNode.length === 1 ? aciTree.itemData(selectedTreeNode) : undefined;
+    const selectedTreeNode = aciTree.selected() ? aciTree.selected() : aciTree.first();
+    const selectedTreeNodeData = selectedTreeNode ? aciTree.itemData(selectedTreeNode) : undefined;
 
     return {
       t: aciTree,
diff --git a/web/pgadmin/browser/static/js/layout.js b/web/pgadmin/browser/static/js/layout.js
index 54046bf2b..5f3138675 100644
--- a/web/pgadmin/browser/static/js/layout.js
+++ b/web/pgadmin/browser/static/js/layout.js
@@ -89,7 +89,7 @@ _.extend(pgBrowser, {
           browser.reflectLocklayoutChange(docker);
         });
       }
-    }, 500);
+    }, 5000);
   },
 
   reflectLocklayoutChange: function(docker) {
diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js
index 7d91ea729..fef519b22 100644
--- a/web/pgadmin/browser/static/js/node.js
+++ b/web/pgadmin/browser/static/js/node.js
@@ -10,13 +10,13 @@
 import {getNodeView, removeNodeView} from './node_view';
 
 define('pgadmin.browser.node', [
-  'sources/tree/pgadmin_tree_node', 'sources/url_for',
+  'sources/url_for',
   'sources/gettext', 'jquery', 'underscore', 'sources/pgadmin',
   'pgadmin.browser.menu', 'backbone', 'pgadmin.alertifyjs', 'pgadmin.browser.datamodel',
   'backform', 'sources/browser/generate_url', 'pgadmin.help', 'sources/utils',
   'pgadmin.browser.utils', 'pgadmin.backform',
 ], function(
-  pgadminTreeNode, url_for,
+  url_for,
   gettext, $, _, pgAdmin,
   Menu, Backbone, Alertify, pgBrowser,
   Backform, generateUrl, help,
@@ -269,8 +269,7 @@ define('pgadmin.browser.node', [
       if (itemData._type == 'database' && !itemData.allowConn)
         return false;
 
-      var node = pgBrowser.Nodes[itemData._type],
-        parentData = node.getTreeNodeHierarchy(item);
+      var parentData = pgBrowser.tree.getTreeNodeHierarchy(item);
       if (_.indexOf(['create', 'insert', 'update', 'delete'], data.script) != -1) {
         if (itemData.type == 'role' &&
           parentData.server.user.can_create_role) {
@@ -325,7 +324,7 @@ define('pgadmin.browser.node', [
         }
 
         // We know - which data model to be used for this object.
-        var info = this.getTreeNodeHierarchy.apply(this, [item]),
+        var info = pgBrowser.tree.getTreeNodeHierarchy(item),
           newModel = new(this.model.extend({
             urlRoot: urlBase,
           }))(
@@ -450,7 +449,7 @@ define('pgadmin.browser.node', [
                 },
                 error: function(model, xhr, options) {
                   var _label = that && item ?
-                    that.getTreeNodeHierarchy(
+                    pgBrowser.tree.getTreeNodeHierarchy(
                       item
                     )[that.type].label : '';
                   pgBrowser.Events.trigger(
@@ -594,7 +593,7 @@ define('pgadmin.browser.node', [
       show_obj_properties: function(args, item) {
         var t = pgBrowser.tree,
           i = (args && args.item) || item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined,
+          d = i ? t.itemData(i) : undefined,
           o = this,
           l = o.title.apply(this, [d]);
 
@@ -786,7 +785,7 @@ define('pgadmin.browser.node', [
           obj = this,
           t = pgBrowser.tree,
           i = input.item || item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i ? t.itemData(i) : undefined;
 
         if (!d)
           return;
@@ -882,7 +881,7 @@ define('pgadmin.browser.node', [
           obj,
           t = pgBrowser.tree,
           i = item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i ? t.itemData(i) : undefined;
 
         if (!d)
           return;
@@ -920,7 +919,7 @@ define('pgadmin.browser.node', [
         var preference = pgBrowser.get_preference('sqleditor', 'copy_sql_to_query_tool');
         var t = pgBrowser.tree,
           i = item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i ? t.itemData(i) : undefined;
 
         if (!d)
           return;
@@ -944,7 +943,7 @@ define('pgadmin.browser.node', [
         var input = args || {},
           t = pgBrowser.tree,
           i = input.item || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i  ? t.itemData(i) : undefined;
         pgBrowser.psql.psql_tool(d, i, true);
       },
 
@@ -988,32 +987,7 @@ define('pgadmin.browser.node', [
           }
         }
       },
-      added: function(item, data, browser) {
-        var b = browser || pgBrowser,
-          t = b.tree,
-          pItem = t.parent(item),
-          pData = pItem && t.itemData(pItem),
-          pNode = pData && pgBrowser.Nodes[pData._type];
-
-        // Check node is a collection or not.
-        if (pNode && pNode.is_collection) {
-          /* If 'collection_count' is not present in data
-           * it means tree node expanded first time, so we will
-           * kept collection count and label in data itself.
-           */
-          if (!('collection_count' in pData)) {
-            pData.collection_count = 0;
-          }
-          pData.collection_count++;
-          t.setLabel(
-            pItem, {
-              label: (
-                _.escape(pData._label) + ' <span>(' + pData.collection_count + ')</span>'
-              ),
-            }
-          );
-        }
-
+      added: function(item, data) {
         pgBrowser.Events.trigger('pgadmin:browser:tree:expand-from-previous-tree-state',
           item);
         pgBrowser.Node.callbacks.change_server_background(item, data);
@@ -1050,43 +1024,11 @@ define('pgadmin.browser.node', [
         return true;
       },
       removed: function(item) {
-        var self = this,
-          t = pgBrowser.tree,
-          pItem = t.parent(item),
-          pData = pItem && t.itemData(pItem),
-          pNode = pData && pgBrowser.Nodes[pData._type];
-
-        // Check node is a collection or not.
-        if (
-          pNode && pNode.is_collection && 'collection_count' in pData
-        ) {
-          pData.collection_count--;
-          t.setLabel(
-            pItem, {
-              label: (
-                _.escape(pData._label) + ' <span>(' + pData.collection_count + ')</span>'
-              ),
-            }
-          );
-        }
-
+        var self = this;
         setTimeout(function() {
           self.clear_cache.apply(self, item);
         }, 0);
       },
-      unloaded: function(item) {
-        var self = this,
-          t = pgBrowser.tree,
-          data = item && t.itemData(item);
-
-        // In case of unload remove the collection counter
-        if (self.is_collection &&  data === Object(data) &&'collection_count' in data) {
-          delete data.collection_count;
-          t.setLabel(item, {
-            label: _.escape(data._label),
-          });
-        }
-      },
       refresh: function(cmd, _item) {
         var self = this,
           t = pgBrowser.tree,
@@ -1232,8 +1174,7 @@ define('pgadmin.browser.node', [
           // Avoid unnecessary reloads
           var i = tree.selected(),
             d = i && tree.itemData(i),
-            n = i && d && pgBrowser.Nodes[d._type],
-            treeHierarchy = n.getTreeNodeHierarchy(i);
+            treeHierarchy = tree.getTreeNodeHierarchy(i);
 
           if (_.isEqual($(this).data('node-prop'), treeHierarchy)) {
             return;
@@ -1246,7 +1187,7 @@ define('pgadmin.browser.node', [
           removeNodeView(j[0]);
           /* getSchema is a schema for React. Get the react node view */
           if(that.getSchema) {
-            let treeNodeInfo = that.getTreeNodeHierarchy.apply(this, [item]);
+            let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
             getNodeView(
               that.type, treeNodeInfo, 'properties', data, 'tab', j[0], this, onEdit
             );
@@ -1323,7 +1264,7 @@ define('pgadmin.browser.node', [
         }.bind(panel),
         onSqlHelp = function() {
           // Construct the URL
-          var server = that.getTreeNodeHierarchy(item).server;
+          var server = pgBrowser.tree.getTreeNodeHierarchy(item).server;
 
           var url = pgBrowser.utils.pg_help_path;
           if (server.server_type == 'ppas') {
@@ -1507,7 +1448,7 @@ define('pgadmin.browser.node', [
           removeNodeView(j[0]);
           /* getSchema is a schema for React. Get the react node view */
           if(that.getSchema) {
-            let treeNodeInfo = that.getTreeNodeHierarchy.apply(this, [item]);
+            let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
             getNodeView(
               that.type, treeNodeInfo, action, data, 'dialog', j[0], this, onEdit,
               (nodeData)=>{
@@ -1884,7 +1825,7 @@ define('pgadmin.browser.node', [
         self = this,
         priority = -Infinity;
       var treeInfo = (_.isUndefined(item) || _.isNull(item)) ?
-        info || {} : this.getTreeNodeHierarchy(item);
+        info || {} : pgBrowser.tree.getTreeNodeHierarchy(item);
       var actionType = type in opURL ? opURL[type] : type;
       var itemID = with_id && d._type == self.type ? encodeURIComponent(d._id) : '';
 
@@ -1921,7 +1862,6 @@ define('pgadmin.browser.node', [
     Collection: pgBrowser.DataCollection,
     // Base class for Node Data Model
     Model: pgBrowser.DataModel,
-    getTreeNodeHierarchy: pgadminTreeNode.getTreeNodeHierarchyFromIdentifier.bind(pgBrowser),
     cache: function(url, node_info, level, data) {
       var cached = this.cached = this.cached || {},
         hash = url,
@@ -1938,7 +1878,7 @@ define('pgadmin.browser.node', [
         )), function(o) {
           return o.priority;
         }), function(o) {
-          hash = commonUtils.sprintf('%s/%s', hash, encodeURI(o._id));
+          hash = commonUtils.sprintf('%s_%s', hash, encodeURI(o._id));
         });
       }
 
diff --git a/web/pgadmin/browser/static/js/preferences.js b/web/pgadmin/browser/static/js/preferences.js
index c5eafacd2..98b006fc5 100644
--- a/web/pgadmin/browser/static/js/preferences.js
+++ b/web/pgadmin/browser/static/js/preferences.js
@@ -14,7 +14,7 @@ import * as Alertify from 'pgadmin.alertifyjs';
 import * as SqlEditorUtils from 'sources/sqleditor_utils';
 import pgWindow from 'sources/window';
 
-var modifyAnimation = require('sources/modify_animation');
+//var modifyAnimation = require('sources/modify_animation');
 
 const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
 
@@ -91,10 +91,10 @@ _.extend(pgBrowser, {
           self.preference_version(self.generate_preference_version());
 
           pgBrowser.keyboardNavigation.init();
-          if(pgBrowser.tree) {
-            modifyAnimation.modifyAcitreeAnimation(self);
-            modifyAnimation.modifyAlertifyAnimation(self);
-          }
+          //          if(pgBrowser.tree) {
+          //            modifyAnimation.modifyAcitreeAnimation(self);
+          //            modifyAnimation.modifyAlertifyAnimation(self);
+          //          }
 
           // Initialize Tree saving/reloading
           pgBrowser.browserTreeState.init();
diff --git a/web/pgadmin/browser/static/js/toolbar.js b/web/pgadmin/browser/static/js/toolbar.js
index bc9c13a3d..9920cd629 100644
--- a/web/pgadmin/browser/static/js/toolbar.js
+++ b/web/pgadmin/browser/static/js/toolbar.js
@@ -123,7 +123,7 @@ export function initializeToolbar(panel, wcDocker) {
       var input = {},
         t = pgAdmin.Browser.tree,
         i = input.item || t.selected(),
-        d = i && i.length == 1 ? t.itemData(i) : undefined;
+        d = i  ? t.itemData(i) : undefined;
       pgAdmin.Browser.psql.psql_tool(d, i, true);
     }
   });
diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js
index 529ba3b5f..6e6228304 100644
--- a/web/pgadmin/dashboard/static/js/dashboard.js
+++ b/web/pgadmin/dashboard/static/js/dashboard.js
@@ -272,16 +272,16 @@ define('pgadmin.dashboard', [
       // The server connected may not be the same one, which was selected, and
       // we do care out the current selected one only.
       if (item.length != 0) {
-        this.object_selected(item, itemData, pgBrowser.Nodes[itemData._type]);
+        this.object_selected(item, itemData);
       }
     },
 
     // Handle treeview clicks
-    object_selected: function(item, itemData, node) {
+    object_selected: function(item, itemData) {
       let self = this;
 
       if (itemData && itemData._type) {
-        var treeHierarchy = node.getTreeNodeHierarchy(item),
+        var treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item),
           url = NodesDashboard.url(itemData, item, treeHierarchy);
 
         if (url === null) {
@@ -1142,11 +1142,10 @@ define('pgadmin.dashboard', [
       } else {
         var t = pgBrowser.tree,
           i = t.selected(),
-          d = i && t.itemData(i),
-          n = i && d && pgBrowser.Nodes[d._type];
+          d = i && t.itemData(i);
 
         this.chartsDomObj && this.chartsDomObj.setPageVisible(dashboardVisible);
-        this.object_selected(i, d, n);
+        this.object_selected(i, d);
       }
     },
     can_take_action: function(m) {
diff --git a/web/pgadmin/misc/dependencies/static/js/dependencies.js b/web/pgadmin/misc/dependencies/static/js/dependencies.js
index 67377c9a5..2098b035f 100644
--- a/web/pgadmin/misc/dependencies/static/js/dependencies.js
+++ b/web/pgadmin/misc/dependencies/static/js/dependencies.js
@@ -168,7 +168,7 @@ define('misc.dependencies', [
         $container = panel.layout().scene().find('.pg-panel-content'),
         $msgContainer = $container.find('.pg-panel-depends-message'),
         $gridContainer = $container.find('.pg-panel-dependencies-container'),
-        treeHierarchy = node.getTreeNodeHierarchy(item);
+        treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
       if (node) {
         /* We fetch the Dependencies and Dependencies tab only for
@@ -294,6 +294,128 @@ define('misc.dependencies', [
         }
       }
     },
+    showReactDependencies: function(item, data, node) {
+      let self = this,
+        msg = gettext('Please select an object in the tree view.'),
+        panel = this.dependenciesPanel,
+        $container = panel.layout().scene().find('.pg-panel-content'),
+        $msgContainer = $container.find('.pg-panel-depends-message'),
+        $gridContainer = $container.find('.pg-panel-dependencies-container'),
+        treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item),
+        n_type = data._type,
+        url = node.generate_url_react(item, 'dependency');
+
+      if (node) {
+        /* We fetch the Dependencies and Dependencies tab only for
+         * those node who set the parameter hasDepends to true.
+         */
+        msg = gettext('No dependency information is available for the selected object.');
+        if (node.hasDepends) {
+          /* Updating the label for the 'field' type of the backbone model.
+           * Label should be "Database" if the node type is tablespace or role
+           * and dependencies tab is selected. For other nodes and dependencies tab
+           * it should be 'Restriction'.
+           */
+
+          this.dependenciesGrid.columns.models[2].set({
+            'label': gettext('Restriction'),
+          });
+
+          // Hide message container and show grid container.
+          $msgContainer.addClass('d-none');
+          $gridContainer.removeClass('d-none');
+
+          var timer = '';
+          $.ajax({
+            url: url,
+            type: 'GET',
+            beforeSend: function(xhr) {
+              xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token);
+              // Generate a timer for the request
+              timer = setTimeout(function() {
+                // notify user if request is taking longer than 1 second
+
+                $msgContainer.text(gettext('Fetching dependency information from the server...'));
+                $msgContainer.removeClass('d-none');
+                msg = '';
+
+              }, 1000);
+            },
+          })
+            .done(function(res) {
+              clearTimeout(timer);
+
+              if (res.length > 0) {
+
+                if (!$msgContainer.hasClass('d-none')) {
+                  $msgContainer.addClass('d-none');
+                }
+                $gridContainer.removeClass('d-none');
+
+                self.dependenciesData = res;
+
+                // Load only 100 rows
+                self.dependenciesCollection.reset(self.dependenciesData.splice(0, 100), {parse: true});
+
+                // Load more rows on scroll down
+                pgBrowser.Events.on(
+                  'pgadmin-browser:panel-dependencies:' +
+                wcDocker.EVENT.SCROLLED,
+                  self.__loadMoreRows
+                );
+
+              } else {
+                // Do not listen the scroll event
+                pgBrowser.Events.off(
+                  'pgadmin-browser:panel-dependencies:' +
+                wcDocker.EVENT.SCROLLED
+                );
+
+                self.dependenciesCollection.reset({silent: true});
+                $msgContainer.text(msg);
+                $msgContainer.removeClass('d-none');
+
+                if (!$gridContainer.hasClass('d-none')) {
+                  $gridContainer.addClass('d-none');
+                }
+              }
+
+
+            })
+            .fail(function(xhr, error, message) {
+              var _label = treeHierarchy[n_type].label;
+              pgBrowser.Events.trigger(
+                'pgadmin:node:retrieval:error', 'depends', xhr, error, message
+              );
+              if (!Alertify.pgHandleItemError(xhr, error, message, {
+                item: item,
+                info: treeHierarchy,
+              })) {
+                Alertify.pgNotifier(
+                  error, xhr,
+                  gettext('Error retrieving data from the server: %s', message || _label),
+                  function(alertMsg) {
+                    if(alertMsg === 'CRYPTKEY_SET') {
+                      self.showDependencies(item, data, node);
+                    } else {
+                      console.warn(arguments);
+                    }
+                  });
+              }
+              // show failed message.
+              $msgContainer.text(gettext('Failed to retrieve data from the server.'));
+            });
+        }
+      }
+      if (msg != '') {
+        $msgContainer.text(msg);
+        $msgContainer.removeClass('d-none');
+        if (!$gridContainer.hasClass('d-none')) {
+          $gridContainer.addClass('d-none');
+        }
+      }
+    },
+
     __loadMoreRows: function() {
       if (this.dependenciesPanel.length < 1) return ;
 
diff --git a/web/pgadmin/misc/dependents/static/js/dependents.js b/web/pgadmin/misc/dependents/static/js/dependents.js
index 6564979d7..e0766e767 100644
--- a/web/pgadmin/misc/dependents/static/js/dependents.js
+++ b/web/pgadmin/misc/dependents/static/js/dependents.js
@@ -168,7 +168,7 @@ define('misc.dependents', [
         $container = panel.layout().scene().find('.pg-panel-content'),
         $msgContainer = $container.find('.pg-panel-depends-message'),
         $gridContainer = $container.find('.pg-panel-dependents-container'),
-        treeHierarchy = node.getTreeNodeHierarchy(item);
+        treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
       if (node) {
         /* We fetch the Dependencies and Dependents tab only for
diff --git a/web/pgadmin/misc/sql/static/js/sql.js b/web/pgadmin/misc/sql/static/js/sql.js
index 4abd054fa..c1722bee6 100644
--- a/web/pgadmin/misc/sql/static/js/sql.js
+++ b/web/pgadmin/misc/sql/static/js/sql.js
@@ -57,6 +57,9 @@ define('misc.sql', [
               pgBrowser.Events.on(
                 'pgadmin-browser:tree:selected', this.showSQL
               );
+              pgBrowser.Events.on(
+                'pgadmin-browser:tree:reactSelected', this.reactShowSQL
+              );
               pgBrowser.Events.on(
                 'pgadmin-browser:tree:refreshing', this.refreshSQL, this
               );
@@ -66,6 +69,7 @@ define('misc.sql', [
       } else {
         if ((sqlPanels[0].isVisible()) || sqlPanels.length != 1) {
           pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showSQL);
+          pgBrowser.Events.on('pgadmin-browser:tree:reactSelected', this.reactShowSQL);
           pgBrowser.Events.on(
             'pgadmin-browser:tree:refreshing', this.refreshSQL, this
           );
@@ -92,6 +96,7 @@ define('misc.sql', [
        * through. We will wait for some time before fetching the Reversed
        * Engineering SQL.
        **/
+
       this.timeout && clearTimeout(this.timeout);
 
       var that = this;
@@ -102,7 +107,7 @@ define('misc.sql', [
             sql = '-- ' + gettext('No SQL could be generated for the selected object.');
             var n_type = data._type,
               url = node.generate_url(item, 'sql', data, true),
-              treeHierarchy = node.getTreeNodeHierarchy(item),
+              treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item),
               cache_flag = {
                 node_type: n_type,
                 url: url,
diff --git a/web/pgadmin/misc/statistics/static/js/statistics.js b/web/pgadmin/misc/statistics/static/js/statistics.js
index f0dbc6a3b..6298caef3 100644
--- a/web/pgadmin/misc/statistics/static/js/statistics.js
+++ b/web/pgadmin/misc/statistics/static/js/statistics.js
@@ -199,7 +199,7 @@ define('misc.statistics', [
          */
 
         // Avoid unnecessary reloads
-        var treeHierarchy = node.getTreeNodeHierarchy(item);
+        var treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
         var cache_flag = {
           node_type: node_type,
           url: url,
@@ -210,7 +210,7 @@ define('misc.statistics', [
         // Cache the current IDs for next time
         $(panel[0]).data('node-prop', cache_flag);
 
-        if (statisticsHelper.nodeHasStatistics(node, item)) {
+        if (statisticsHelper.nodeHasStatistics(pgBrowser, node, item)) {
           msg = '';
           var timer;
           // Set the url, fetch the data and update the collection
diff --git a/web/pgadmin/preferences/static/js/preferences.js b/web/pgadmin/preferences/static/js/preferences.js
index 6dd88151f..5b5d1087a 100644
--- a/web/pgadmin/preferences/static/js/preferences.js
+++ b/web/pgadmin/preferences/static/js/preferences.js
@@ -495,7 +495,7 @@ define('pgadmin.preferences', [
               view: {duration: 75},
             });
 
-            modifyAnimation.modifyAcitreeAnimation(pgBrowser, jTree.aciTree('api'));
+            if (jTree.aciTree('api')) modifyAnimation.modifyAcitreeAnimation(pgBrowser, jTree.aciTree('api'));
 
             this.show();
           },
diff --git a/web/pgadmin/static/bundle/app.js b/web/pgadmin/static/bundle/app.js
index c8bd8f74b..6b11fefea 100644
--- a/web/pgadmin/static/bundle/app.js
+++ b/web/pgadmin/static/bundle/app.js
@@ -13,11 +13,22 @@ define('app', [
   var initializeModules = function(Object) {
     for (var key in Object) {
       var module = Object[key];
-      if (module.init && typeof module.init == 'function') {
-        module.init();
+
+      if (module && module.init && typeof module.init == 'function') {
+        try {
+          module.init();
+        }
+        catch (e) {
+          console.warn(e.stack || e);
+        }
       }
-      else if (module.Init && typeof module.Init == 'function') {
-        module.Init();
+      else if (module && module.Init && typeof module.Init == 'function') {
+        try {
+          module.init();
+        }
+        catch (e) {
+          console.warn(e.stack || e);
+        }
       }
     }
   };
diff --git a/web/pgadmin/static/js/alertify/dialog.js b/web/pgadmin/static/js/alertify/dialog.js
index 6b7c41c50..27ba62a5f 100644
--- a/web/pgadmin/static/js/alertify/dialog.js
+++ b/web/pgadmin/static/js/alertify/dialog.js
@@ -10,7 +10,6 @@
 import gettext from '../gettext';
 import {DialogFactory} from './dialog_factory';
 import Backform from '../backform.pgadmin';
-import {getTreeNodeHierarchyFromIdentifier} from '../tree/pgadmin_tree_node';
 
 /**
  * This class can be extended to create new dialog boxes.
@@ -35,8 +34,8 @@ export class Dialog {
 
   retrieveAncestorOfTypeServer(item) {
     let serverInformation = null;
-    let aciTreeItem = item || this.pgBrowser.treeMenu.selected();
-    let treeNode = this.pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem);
+    let aciTreeItem = item || this.pgBrowser.tree.selected();
+    let treeNode = this.pgBrowser.tree.findNodeByDomElement(aciTreeItem);
 
     if (treeNode) {
       let nodeData;
@@ -107,7 +106,7 @@ export class Dialog {
   }
 
   canExecuteOnCurrentDatabase(aciTreeItem) {
-    const treeInfo = getTreeNodeHierarchyFromIdentifier.apply(this.pgBrowser, [aciTreeItem]);
+    const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(aciTreeItem);
 
     if (treeInfo.database && treeInfo.database._label.indexOf('=') >= 0) {
       this.alertify.alert(
diff --git a/web/pgadmin/static/js/misc/statistics/statistics.js b/web/pgadmin/static/js/misc/statistics/statistics.js
index a004a61bd..1549db990 100644
--- a/web/pgadmin/static/js/misc/statistics/statistics.js
+++ b/web/pgadmin/static/js/misc/statistics/statistics.js
@@ -7,9 +7,9 @@
 //
 //////////////////////////////////////////////////////////////////////////
 
-export function nodeHasStatistics(node, item) {
+export function nodeHasStatistics(pgBrowser, node, item) {
   if(typeof(node.hasStatistics) === 'function') {
-    const treeHierarchy = node.getTreeNodeHierarchy(item);
+    const treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
     return node.hasStatistics(treeHierarchy);
   }
   return node.hasStatistics;
diff --git a/web/pgadmin/static/js/nodes/dashboard.js b/web/pgadmin/static/js/nodes/dashboard.js
index 137fde684..f4688cd10 100644
--- a/web/pgadmin/static/js/nodes/dashboard.js
+++ b/web/pgadmin/static/js/nodes/dashboard.js
@@ -12,7 +12,7 @@ import pgBrowser from 'pgadmin.browser';
 
 
 export function url(itemData, item, treeHierarchy) {
-  let treeNode = pgBrowser.treeMenu.findNodeByDomElement(item);
+  let treeNode = pgBrowser.tree.findNodeByDomElement(item);
   let return_url = null;
 
   if (treeNode) {
diff --git a/web/pgadmin/static/js/nodes/supported_database_node.js b/web/pgadmin/static/js/nodes/supported_database_node.js
index e174363ad..469ac47b3 100644
--- a/web/pgadmin/static/js/nodes/supported_database_node.js
+++ b/web/pgadmin/static/js/nodes/supported_database_node.js
@@ -8,6 +8,7 @@
 //////////////////////////////////////////////////////////////
 
 import {isValidTreeNodeData} from 'sources/tree/tree';
+import pgAdmin from 'sources/pgadmin';
 
 function checkAllowConnIfDatabaseNode(treeNodeData) {
   return (treeNodeData._type === 'database' && treeNodeData.allowConn)
@@ -24,7 +25,8 @@ export function enabled(tree, supportedNodes, treeNodeData, domTreeNode) {
   if (!isValidTreeNodeData(treeNodeData))
     return false;
 
-  let treeNode = tree.findNodeByDomElement(domTreeNode);
+  let _tree = tree ? tree : pgAdmin.Browser.tree;
+  let treeNode = _tree.findNodeByDomElement(domTreeNode);
   if (!treeNode) {
     return false;
   }
diff --git a/web/pgadmin/static/js/tree/pgadmin_tree_node.js b/web/pgadmin/static/js/tree/pgadmin_tree_node.js
deleted file mode 100644
index 55c35e374..000000000
--- a/web/pgadmin/static/js/tree/pgadmin_tree_node.js
+++ /dev/null
@@ -1,75 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2021, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * This method received pgBrowser and new TreeNode object
- *
- * This method retrieves all the data that exists in the tree node and in
- * `pgBrowser.Nodes` for all the parent node of the provided node.
- *
- * The 2 condition to get the information from pgBrowser.Nodes are:
- *  1 - the variable _type of the tree node
- *  2 - the presence of hasId in the pgBrowser.Nodes for the specific node
- *
- * Number 2 is used to ignore coll-* nodes as they do not add any useful
- * information
- */
-export function getTreeNodeHierarchyFromElement(pgBrowser, treeNode) {
-  return getTreeNodeHierarchy.call(pgBrowser, treeNode);
-}
-
-/**
- * This method received an ACI Tree JQuery node
- *
- * NOTE: this function need to be called on pgBrowser instance.
- * getTreeNodeHierarchyFromIdentifier.apply(pgBrowser, [aciTreeNodeIdentifier])
- *
- * This method retrieves all the data that exists in the tree node and in
- * `pgBrowser.Nodes` for all the parent node of the provided node.
- *
- * The 2 condition to get the information from pgBrowser.Nodes are:
- *  1 - the variable _type of the tree node
- *  2 - the presence of hasId in the pgBrowser.Nodes for the specific node
- *
- * Number 2 is used to ignore coll-* nodes as they do not add any useful
- * information
- */
-export function getTreeNodeHierarchyFromIdentifier(aciTreeNodeIdentifier) {
-  let identifier = this.treeMenu.translateTreeNodeIdFromACITree(aciTreeNodeIdentifier);
-  let currentNode = this.treeMenu.findNode(identifier);
-  if (currentNode === null) return null;
-  return getTreeNodeHierarchy.call(this, currentNode);
-}
-
-export function getTreeNodeHierarchy(currentNode) {
-  let idx = 0;
-  let node_cnt = 0;
-  let result = {};
-
-  do {
-    const currentNodeData = currentNode.getData();
-    if (currentNodeData._type in this.Nodes && this.Nodes[currentNodeData._type].hasId) {
-      const nodeType = mapType(currentNodeData._type, node_cnt);
-      if (result[nodeType] === undefined) {
-        result[nodeType] = _.extend({}, currentNodeData, {
-          'priority': idx,
-        });
-        idx -= 1;
-      }
-    }
-    node_cnt += 1;
-    currentNode = currentNode.hasParent() ? currentNode.parent() : null;
-  } while (currentNode);
-
-  return result;
-}
-
-function mapType(type, idx) {
-  return (type === 'partition' && idx > 0) ? 'table' : type;
-}
diff --git a/web/pgadmin/static/js/tree/pgadmin_tree_save_state.js b/web/pgadmin/static/js/tree/pgadmin_tree_save_state.js
index 1a1ac11fc..950d00528 100644
--- a/web/pgadmin/static/js/tree/pgadmin_tree_save_state.js
+++ b/web/pgadmin/static/js/tree/pgadmin_tree_save_state.js
@@ -150,12 +150,10 @@ _.extend(pgBrowser.browserTreeState, {
       });
   },
   update_cache: function(item) {
-
     let data = item && pgBrowser.tree.itemData(item),
-      node = data && pgBrowser.Nodes[data._type],
-      treeHierarchy = node.getTreeNodeHierarchy(item),
+      treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item),
       topParent = undefined,
-      pathIDs = pgBrowser.tree.pathId(item),
+      pathIDs = pgBrowser.tree.pathId(pgBrowser.tree.parent(item)),
       oldPath = pathIDs.join(),
       path = [],
       tmpIndex = -1;
@@ -208,8 +206,7 @@ _.extend(pgBrowser.browserTreeState, {
     let self= this,
       treeData = self.stored_state || {},
       data = item && pgBrowser.tree.itemData(item),
-      node = data && pgBrowser.Nodes[data._type],
-      treeHierarchy = node && node.getTreeNodeHierarchy(item);
+      treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
     if (treeHierarchy === null || !pgBrowser.tree.hasParent(item) || !(treeHierarchy.hasOwnProperty(self.parent)))
       return;
@@ -265,8 +262,7 @@ _.extend(pgBrowser.browserTreeState, {
     let self = this,
       treeData = self.stored_state || {},
       data = item && pgBrowser.tree.itemData(item),
-      node = data && pgBrowser.Nodes[data._type],
-      treeHierarchy = node && node.getTreeNodeHierarchy(item);
+      treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
 
     if (treeHierarchy === null || !pgBrowser.tree.hasParent(item) || !(treeHierarchy.hasOwnProperty(self.parent)))
@@ -305,7 +301,7 @@ _.extend(pgBrowser.browserTreeState, {
 
             let index = tmpItemData.indexOf(data.id);
 
-            pgBrowser.tree.toggle(item);
+            pgBrowser.tree.open(item);
 
             if (index == (tmpItemData.length - 1 )) {
               let tIndex = treeData[treeHierarchy[self.parent]['_id']]['paths'].indexOf(tData);
@@ -322,8 +318,7 @@ _.extend(pgBrowser.browserTreeState, {
   },
   update_database_status: function(item) {
     let data = item && pgBrowser.tree.itemData(item),
-      node = data && pgBrowser.Nodes[data._type],
-      treeHierarchy = node.getTreeNodeHierarchy(item);
+      treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item);
 
     if (treeHierarchy.hasOwnProperty('database')) {
       let databaseItem = treeHierarchy['database']['id'],
@@ -374,8 +369,7 @@ _.extend(pgBrowser.browserTreeState, {
   select_tree_item(item) {
     let treeData = this.stored_state || {},
       data = item && pgBrowser.tree.itemData(item),
-      node = data && pgBrowser.Nodes[data._type],
-      treeHierarchy = node && node.getTreeNodeHierarchy(item),
+      treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item),
       tmpTreeData = treeData[treeHierarchy[this.parent]['_id']];
 
 
diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js
index 68ade0715..1885f6d5d 100644
--- a/web/pgadmin/static/js/tree/tree.js
+++ b/web/pgadmin/static/js/tree/tree.js
@@ -7,245 +7,292 @@
 //
 //////////////////////////////////////////////////////////////////////////
 
-import {isValidData} from 'sources/utils';
+import _ from 'lodash';
 import $ from 'jquery';
-import Alertify from 'pgadmin.alertifyjs';
+import pgAdmin from 'sources/pgadmin';
+
+import { FileType } from 'react-aspen';
+import { TreeNode } from './tree_nodes';
+
+import {isValidData} from 'sources/utils';
+
+function manageTreeEvents(event, eventName, item) {
+  let d = item ? item._metadata.data: [];
+  let node;
+  let obj = pgAdmin.Browser;
+
+  if (d && obj.Nodes[d._type]) {
+    node = obj.Nodes[d._type];
+
+    // If the Browser tree is not initialised yet
+    if (obj.tree === null) return;
+
+    if (eventName == 'dragstart') {
+      obj.tree.handleDraggable(event, item);
+    }
+    if (eventName == 'added' || eventName == 'beforeopen' || eventName == 'loaded') {
+      obj.tree.addNewNode(item.getMetadata('data').id, item.getMetadata('data') ,item), item.parent.path;
+    }
+    if (_.isObject(node.callbacks) &&
+      eventName in node.callbacks &&
+        typeof node.callbacks[eventName] == 'function' &&
+        !node.callbacks[eventName].apply(
+          node, [item, d, obj, [], eventName])) {
+      return true;
+    }
+    /* Raise tree events for the nodes */
+    try {
+      node.trigger(
+        'browser-node.' + eventName, node, item, d
+      );
+      obj.Events.trigger(
+        'pgadmin-browser:tree:' + eventName, item, d, node
+      );
+    } catch (e) {
+      console.warn(e.stack || e);
+      return false;
+    }
+  }
+  return true;
+}
+
+
+export class Tree {
+  constructor(tree, manageTree, pgBrowser) {
+    this.tree = tree;
+    this.tree.onTreeEvents(manageTreeEvents);
+
+    this.rootNode = manageTree.tempTree;
+    this.Nodes = pgBrowser ? pgBrowser.Nodes : pgAdmin.Browser.Nodes;
+
+    this.draggableTypes = {};
+  }
+
+  async refresh(item) {
+    await this.tree.refresh(item);
+  }
+
+  async add(item, data) {
+    await this.tree.create(item.parent, data.itemData);
+  }
 
-export class TreeNode {
-  constructor(id, data, domNode, parent) {
-    this.id = id;
-    this.data = data;
-    this.setParent(parent);
-    this.children = [];
-    this.domNode = domNode;
+  async before(item, data) {
+    await this.tree.create(item.parent, data.itemData);
   }
 
-  hasParent() {
-    return this.parentNode !== null && this.parentNode !== undefined;
+  async update(item, data) {
+    await this.tree.update(item, data.itemData);
   }
 
-  parent() {
-    return this.parentNode;
+  async remove(item) {
+    return await this.tree.remove(item);
   }
 
-  setParent(parent) {
-    this.parentNode = parent;
-    this.path = this.id;
-    if (parent !== null && parent !== undefined && parent.path !== undefined) {
-      this.path = parent.path + '.' + this.id;
+  async append(item, data) {
+    return await this.tree.create(item, data);
+  }
+
+  next(item) {
+    if(item) {
+      let parent = this.parent(item);
+      if(parent && parent.children.length > 0) {
+        let idx = parent.children.indexOf(item);
+        if(idx !== -1 && parent.children.length !== idx+1) {
+          return parent.children[idx+1];
+        }
+      }
     }
+    return null;
   }
 
-  getData() {
-    if (this.data === undefined) {
-      return undefined;
-    } else if (this.data === null) {
-      return null;
+  prev(item) {
+    if(item) {
+      let parent = this.parent(item);
+      if(parent && parent.children.length > 0) {
+        let idx = parent.children.indexOf(item);
+        if(idx !== -1 && idx !== 0) {
+          return parent.children[idx-1];
+        }
+      }
     }
-    return Object.assign({}, this.data);
+    return null;
   }
 
-  getHtmlIdentifier() {
-    return this.domNode;
+  async open(item) {
+    if (this.isOpen(item)) { return true; }
+    await this.tree.toggleDirectory(item);
   }
 
-  reload(tree) {
-    return new Promise((resolve)=>{
-      this.unload(tree)
-        .then(()=>{
-          tree.aciTreeApi.setInode(this.domNode);
-          tree.aciTreeApi.deselect(this.domNode);
-          setTimeout(() => {
-            tree.selectNode(this.domNode);
-          }, 0);
-          resolve();
-        });
-    });
-  }
-
-  unload(tree) {
-    return new Promise((resolve, reject)=>{
-      this.children = [];
-      tree.aciTreeApi.unload(this.domNode, {
-        success: ()=>{
-          resolve(true);
-        },
-        fail: ()=>{
-          reject();
-        },
-      });
-    });
+  async ensureVisible(item){
+    await this.tree.ensureVisible(item);
   }
 
-  open(tree, suppressNoDom) {
-    return new Promise((resolve, reject)=>{
-      if(suppressNoDom && (this.domNode == null || typeof(this.domNode) === 'undefined')) {
-        resolve(true);
-      } else if(tree.aciTreeApi.isOpen(this.domNode)) {
-        resolve(true);
-      } else {
-        tree.aciTreeApi.open(this.domNode, {
-          success: ()=>{
-            resolve(true);
-          },
-          fail: ()=>{
-            reject(true);
-          },
-        });
-      }
-    });
+  async openPath(item) {
+    parent = item.parent;
+    await this.tree.openDirectory(parent);
   }
 
-  /*
-   * Find the ancestor with matches this condition
-   */
-  ancestorNode(condition) {
-    let node = this;
+  async close(item) {
+    await this.tree.closeDirectory(item);
+  }
 
-    while (node.hasParent()) {
-      node = node.parent();
-      if (condition(node)) {
-        return node;
-      }
+  async toggle(item) {
+    await this.tree.toggleDirectory(item);
+  }
+
+  async select(item) {
+    await this.tree.setActiveFile(item);
+  }
+
+  async selectNode(item) {
+    this.tree.setActiveFile(item);
+  }
+
+  async unload(item) {
+    await this.tree.unload(item);
+  }
+
+  async addIcon(item, icon) {
+    if (item !== undefined && item.getMetadata('data') !== undefined) {
+      item.getMetadata('data').icon = icon.icon;
     }
+    await this.tree.addIcon(item, icon);
+  }
 
-    return null;
+  removeIcon() {
+    // TBD
   }
 
-  /**
-   * Given a condition returns true if the current node
-   * or any of the parent nodes condition result is true
-   */
-  anyFamilyMember(condition) {
-    if(condition(this)) {
-      return true;
+  setLeaf() {
+    // TBD
+  }
+  async setLabel(item, label) {
+    if(item) {
+      await this.tree.setLabel(item, label);
     }
+  }
 
-    return this.ancestorNode(condition) !== null;
+  async setInode(item) {
+    if(item._children) item._children = null;
+    await this.tree.closeDirectory(item);
   }
-  anyParent(condition) {
-    return this.ancestorNode(condition) !== null;
+
+  deselect(item) {
+    this.tree.deSelectActiveFile(item);
   }
-}
 
-export class Tree {
-  constructor() {
-    this.rootNode = new TreeNode(undefined, {});
-    this.aciTreeApi = undefined;
-    this.draggableTypes = {};
+  wasInit() {
+    // TBD
+    return true;
   }
 
-  /*
-   *
-   * The dropDetailsFunc should return an object of sample
-   * {text: 'xyz', cur: {from:0, to:0} where text is the drop text and
-   * cur is selection range of text after dropping. If returned as
-   * string, by default cursor will be set to the end of text
-   */
-  registerDraggableType(typeOrTypeDict, dropDetailsFunc=null) {
-    if(typeof typeOrTypeDict == 'object') {
-      Object.keys(typeOrTypeDict).forEach((type)=>{
-        this.registerDraggableType(type, typeOrTypeDict[type]);
-      });
-    } else {
-      if(dropDetailsFunc != null) {
-        typeOrTypeDict.replace(/ +/, ' ').split(' ').forEach((type)=>{
-          this.draggableTypes[type] = dropDetailsFunc;
-        });
-      }
+  wasLoad(item) {
+    if (item && item.type === FileType.Directory) {
+      return item.isExpanded;
     }
+    return true;
   }
 
-  getDraggable(type) {
-    if(this.draggableTypes[type]) {
-      return this.draggableTypes[type];
-    } else {
-      return null;
+  parent(item) {
+    return item.parent;
+  }
+
+  first(item) {
+    const model = this.tree.getModel();
+    if (item === undefined || item === null) {
+      return model.root.children[0];
+    }
+
+    if (item.branchSize > 0) {
+      return item.children[0];
     }
+
+    return null;
   }
 
-  prepareDraggable(data, item) {
-    let dropDetailsFunc = this.getDraggable(data._type);
+  children(item) {
+    const model = this.tree.getModel();
+    return item ? (item.children !== null ? item.children : []) : model.root.children;
+  }
 
-    if(dropDetailsFunc != null) {
+  itemFrom(domElem) {
+    return this.tree.getItemFromDOM(domElem[0]);
+  }
 
-      /* addEventListener is used here because import jquery.drag.event
-       * overrides the dragstart event set using element.on('dragstart')
-       * This will avoid conflict.
-       */
-      item.find('.aciTreeItem')
-        .attr('draggable', true)[0]
-        .addEventListener('dragstart', (e)=> {
-          let dropDetails = dropDetailsFunc(data, item);
-
-          if(typeof dropDetails == 'string') {
-            dropDetails = {
-              text:dropDetails,
-              cur:{
-                from:dropDetails.length,
-                to: dropDetails.length,
-              },
-            };
-          } else {
-            if(!dropDetails.cur) {
-              dropDetails = {
-                ...dropDetails,
-                cur:{
-                  from:dropDetails.text.length,
-                  to: dropDetails.text.length,
-                },
-              };
-            }
-          }
-
-          e.dataTransfer.setData('text', JSON.stringify(dropDetails));
-          /* Required by Firefox */
-          if(e.dataTransfer.dropEffect) {
-            e.dataTransfer.dropEffect = 'move';
-          }
-
-          /* setDragImage is not supported in IE. We leave it to
-           * its default look and feel
-           */
-          if(e.dataTransfer.setDragImage) {
-            let dragItem = $(`
-              <div class="drag-tree-node">
-                <span>${_.escape(dropDetails.text)}</span>
-              </div>`
-            );
-
-            $('body .drag-tree-node').remove();
-            $('body').append(dragItem);
-
-            e.dataTransfer.setDragImage(dragItem[0], 0, 0);
-          }
-        });
+  path(item) {
+    if (item) return item.path;
+  }
+
+  pathId(item) {
+    if (item) {
+      let pathIds = item.path.split('/');
+      pathIds.splice(0, 1);
+      return pathIds;
     }
+    return [];
   }
 
-  addNewNode(id, data, domNode, parentPath) {
-    const parent = this.findNode(parentPath);
-    return this.createOrUpdateNode(id, data, parent, domNode);
+  itemFromDOM(domElem) {
+    return this.tree.getItemFromDOM(domElem[0]);
   }
 
-  findNode(path) {
-    if (path === null || path === undefined || path.length === 0) {
-      return this.rootNode;
+  siblings(item) {
+    if (this.hasParent(item)) {
+      let _siblings = this.parent(item).children.filter((_item) => _item.path !== item.path);
+      if (typeof(_siblings) !== 'object') return [_siblings];
+      else _siblings;
+    }
+    return [];
+  }
+
+  hasParent(item) {
+    return item && item.parent ? true : false;
+  }
+
+  isOpen(item) {
+    if (item.type === FileType.Directory) {
+      return item.isExpanded;
+    }
+    return false;
+  }
+
+  isClosed(item) {
+    if (item.type === FileType.Directory) {
+      return !item.isExpanded;
     }
-    return findInTree(this.rootNode, path.join('.'));
+    return false;
+  }
+
+  itemData(item) {
+    return (item !== undefined && item.getMetadata('data') !== undefined) ? item._metadata.data : [];
   }
 
+  getData(item) {
+    return (item !== undefined && item.getMetadata('data') !== undefined) ? item._metadata.data : [];
+  }
+
+  isInode(item) {
+    const children = this.children(item);
+    if (children === null || children === undefined) return false;
+    return children.length > 0 ? true : false;
+  }
+
+  selected() {
+    return this.tree.getActiveFile();
+  }
+
+
   findNodeWithToggle(path) {
     let tree = this;
 
     if(path == null || !Array.isArray(path)) {
       return Promise.reject();
     }
-    path = path.join('.');
+    path = '/browser/' + path.join('/');
 
     let onCorrectPath = function(matchPath) {
       return (matchPath !== undefined && path !== undefined
-        && (path.startsWith(matchPath + '.') || path === matchPath));
+        && (path.startsWith(matchPath) || path === matchPath));
     };
 
     return (function findInNode(currentNode) {
@@ -261,10 +308,11 @@ export class Tree {
         } else if (currentNode.path === path) {
           resolve(currentNode);
         } else {
-          currentNode.open(tree, true)
+          tree.open(currentNode)
             .then(()=>{
-              for (let i = 0, length = currentNode.children.length; i < length; i++) {
-                let childNode = currentNode.children[i];
+              let children = currentNode.children;
+              for (let i = 0, length = children.length; i < length; i++) {
+                let childNode = children[i];
                 if(onCorrectPath(childNode.path)) {
                   resolve(findInNode(childNode));
                   return;
@@ -277,11 +325,11 @@ export class Tree {
             });
         }
       });
-    })(this.rootNode);
+    })(tree.tree.getModel().root);
   }
 
   findNodeByDomElement(domElement) {
-    const path = this.translateTreeNodeIdFromACITree(domElement);
+    const path = domElement.path;
     if(!path || !path[0]) {
       return undefined;
     }
@@ -289,29 +337,23 @@ export class Tree {
     return this.findNode(path);
   }
 
-  selected() {
-    return this.aciTreeApi.selected();
+  addNewNode(id, data, item, parentPath) {
+    let parent;
+    parent = this.findNode(parentPath);
+    return this.createOrUpdateNode(id, data, parent, item);
   }
 
-  /* scrollIntoView will scroll only to top and bottom
-   * Logic can be added for scroll to middle
-   */
-  scrollTo(domElement) {
-    domElement.scrollIntoView();
-  }
-
-  selectNode(aciTreeIdentifier, scrollOnSelect) {
-    this.aciTreeApi.select(aciTreeIdentifier);
-
-    if(scrollOnSelect) {
-      this.scrollTo(aciTreeIdentifier[0]);
+  findNode(path) {
+    if (path === null || path === undefined || path.length === 0) {
+      return this.rootNode;
     }
+    return findInTree(this.rootNode, path);
   }
 
   createOrUpdateNode(id, data, parent, domNode) {
-    let oldNodePath = [id];
-    if(parent !== null && parent !== undefined) {
-      oldNodePath = [parent.path, id];
+    let oldNodePath = id;
+    if(parent !== null && parent !== undefined && parent.path !== undefined && parent.path != '/browser') {
+      oldNodePath = parent.path + '/' + id;
     }
     const oldNode = this.findNode(oldNodePath);
     if (oldNode !== null) {
@@ -330,108 +372,145 @@ export class Tree {
     return node;
   }
 
-  unloadNode(id, data, domNode, parentPath) {
-    let oldNodePath = [id];
-    const parent = this.findNode(parentPath);
-    if(parent !== null && parent !== undefined) {
-      oldNodePath = [parent.path, id];
-    }
-    const oldNode = this.findNode(oldNodePath);
-    if(oldNode) {
-      oldNode.children = [];
+  translateTreeNodeIdFromReactTree(aciTreeNode) {
+    let currentTreeNode = aciTreeNode;
+    let path = [];
+    while (currentTreeNode !== null && currentTreeNode !== undefined) {
+      if (currentTreeNode.path !== '/browser') path.unshift(currentTreeNode.path);
+      if (this.hasParent(currentTreeNode)) {
+        currentTreeNode = this.parent(currentTreeNode);
+      } else {
+        break;
+      }
     }
+    return path;
   }
 
-  /**
-   * Given the JQuery object that contains the ACI Tree
-   * this method is responsible for registering this tree class
-   * to listen to all the events that happen in the ACI Tree.
-   *
-   * At this point in time the only event that we care about is
-   * the addition of a new node.
-   * The function will create a new tree node to store the information
-   * that exist in the ACI for it.
-   */
-  register($treeJQuery) {
-    $treeJQuery.on('acitree', function (event, api, item, eventName) {
-      if (api.isItem(item)) {
-        /* If the id of node is changed, the path should also be changed */
-        if (['added', 'idset', 'beforeunload'].indexOf(eventName) != -1) {
-          const id = api.getId(item);
-          const data = api.itemData(item);
-          const parentId = this.translateTreeNodeIdFromACITree(api.parent(item));
-
-          if(eventName === 'beforeunload') {
-            this.unloadNode(id, data, item, parentId);
-          } else {
-            if(eventName === 'added') {
-              this.prepareDraggable(data, item);
-            }
-
-            this.addNewNode(id, data, item, parentId);
-          }
-          if(data.errmsg) {
-            Alertify.error(data.errmsg);
-          }
+  getTreeNodeHierarchy(identifier) {
+    let idx = 0;
+    let node_cnt = 0;
+    let result = {};
+    if (identifier === undefined) return;
+    let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path);
+    if (item === undefined) return;
+    do {
+      const currentNodeData = item.getData();
+      if (currentNodeData._type in this.Nodes && this.Nodes[currentNodeData._type].hasId) {
+        const nodeType = mapType(currentNodeData._type, node_cnt);
+        if (result[nodeType] === undefined) {
+          result[nodeType] = _.extend({}, currentNodeData, {
+            'priority': idx,
+          });
+          idx -= 1;
         }
       }
-    }.bind(this));
-    this.aciTreeApi = $treeJQuery.aciTree('api');
+      node_cnt += 1;
+      item = item.hasParent() ? item.parent() : null;
+    } while (item);
 
-    /* Ctrl + Click will trigger context menu. Select the node when Ctrl+Clicked.
-     * When the context menu is visible, the tree should lose focus
-     * to use context menu with keyboard. Otherwise, the tree functions
-     * overrides the keyboard events.
-     */
-    let contextHandler = (ev)=>{
-      let treeItem = this.aciTreeApi.itemFrom(ev.target);
-      if(treeItem.length) {
-        if(ev.ctrlKey) {
-          this.aciTreeApi.select(treeItem);
-        }
-        $(treeItem).on('contextmenu:visible', ()=>{
-          $(treeItem).trigger('blur');
-          $(treeItem).off('contextmenu:visible');
-        });
-      }
-    };
-    $treeJQuery
-      .off('mousedown', contextHandler)
-      .on('mousedown', contextHandler);
+    return result;
   }
 
-  /**
-   * As the name hints this functions works as a layer in between ACI and
-   * the adaptor. Given a ACITree JQuery node find the location of it in the
-   * Tree and then returns and array with the path to the Tree Node in
-   * question
+  /*
    *
-   * This is not optimized and will always go through the full tree
+   * The dropDetailsFunc should return an object of sample
+   * {text: 'xyz', cur: {from:0, to:0} where text is the drop text and
+   * cur is selection range of text after dropping. If returned as
+   * string, by default cursor will be set to the end of text
    */
-  translateTreeNodeIdFromACITree(aciTreeNode) {
-    let currentTreeNode = aciTreeNode;
-    let path = [];
-    while (currentTreeNode !== null && currentTreeNode !== undefined && currentTreeNode.length > 0) {
-      path.unshift(this.aciTreeApi.getId(currentTreeNode));
-      if (this.aciTreeApi.hasParent(currentTreeNode)) {
-        currentTreeNode = this.aciTreeApi.parent(currentTreeNode);
+  registerDraggableType(typeOrTypeDict, dropDetailsFunc=null) {
+    if(typeof typeOrTypeDict == 'object') {
+      Object.keys(typeOrTypeDict).forEach((type)=>{
+        this.registerDraggableType(type, typeOrTypeDict[type]);
+      });
+    } else {
+      if(dropDetailsFunc != null) {
+        typeOrTypeDict.replace(/ +/, ' ').split(' ').forEach((type)=>{
+          this.draggableTypes[type] = dropDetailsFunc;
+        });
+      }
+    }
+  }
+
+  getDraggable(type) {
+    if(this.draggableTypes[type]) {
+      return this.draggableTypes[type];
+    } else {
+      return null;
+    }
+  }
+
+  handleDraggable(e, item) {
+    let data = item.getMetadata('data');
+    let dropDetailsFunc = this.getDraggable(data._type);
+
+    if(dropDetailsFunc != null) {
+
+      /* addEventListener is used here because import jquery.drag.event
+       * overrides the dragstart event set using element.on('dragstart')
+       * This will avoid conflict.
+       */
+      let dropDetails = dropDetailsFunc(data, item);
+
+      if(typeof dropDetails == 'string') {
+        dropDetails = {
+          text:dropDetails,
+          cur:{
+            from:dropDetails.length,
+            to: dropDetails.length,
+          },
+        };
       } else {
-        break;
+        if(!dropDetails.cur) {
+          dropDetails = {
+            ...dropDetails,
+            cur:{
+              from:dropDetails.text.length,
+              to: dropDetails.text.length,
+            },
+          };
+        }
+      }
+
+      e.dataTransfer.setData('text', JSON.stringify(dropDetails));
+      /* Required by Firefox */
+      if(e.dataTransfer.dropEffect) {
+        e.dataTransfer.dropEffect = 'move';
+      }
+
+      /* setDragImage is not supported in IE. We leave it to
+         * its default look and feel
+         */
+      if(e.dataTransfer.setDragImage) {
+        let dragItem = $(`
+            <div class="drag-tree-node">
+              <span>${_.escape(dropDetails.text)}</span>
+            </div>`
+        );
+
+        $('body .drag-tree-node').remove();
+        $('body').append(dragItem);
+
+        e.dataTransfer.setDragImage(dragItem[0], 0, 0);
       }
     }
-    return path;
   }
 }
 
+function mapType(type, idx) {
+  return (type === 'partition' && idx > 0) ? 'table' : type;
+}
+
+
+
 /**
  * Given an initial node and a path, it will navigate through
  * the new tree to find the node that matches the path
  */
-function findInTree(rootNode, path) {
+export function findInTree(rootNode, path) {
   if (path === null) {
     return rootNode;
   }
-
   return (function findInNode(currentNode) {
 
     /* No point in checking the children if
diff --git a/web/pgadmin/static/js/tree/tree_init.tsx b/web/pgadmin/static/js/tree/tree_init.tsx
new file mode 100644
index 000000000..4d67ecf21
--- /dev/null
+++ b/web/pgadmin/static/js/tree/tree_init.tsx
@@ -0,0 +1,87 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import * as React from 'react';
+import { render } from 'react-dom';
+import { FileTreeX, TreeModelX } from 'pgadmin4-tree';
+import {Tree} from './tree';
+
+import { IBasicFileSystemHost } from 'react-aspen';
+import { ManageTreeNodes } from './tree_nodes'
+
+var initBrowserTree = async (pgBrowser) => {
+  const MOUNT_POINT = '/browser'
+
+  // Setup host
+  let mtree = new ManageTreeNodes();
+
+  // Init Tree with the Tree Parent node '/browser'
+  mtree.init(MOUNT_POINT);
+
+  const host: IBasicFileSystemHost = {
+    pathStyle: 'unix',
+    getItems: async (path) => {
+      let nodes = await mtree.readNode(path);
+      return nodes;
+    },
+  }
+
+  // Create Node
+  const create = async (parentPath, _data): Promise<IFileEntryItem> => {
+    try {
+      let _node_path = parentPath + "/" + _data.id
+      return mtree.addNode(parentPath, _node_path, _data)
+    } catch (error) {
+      return null // or throw error as you see fit
+    }
+  }
+
+
+  // Remove Node
+  const remove = async (path: string, _removeOnlyChild): Promise<boolean> => {
+    try {
+      await mtree.removeNode(path, _removeOnlyChild);
+      return true
+    } catch (error) {
+      return false // or throw error as you see fit
+    }
+  }
+
+  // Update Node
+  const update = async (path: string, data): Promise<boolean> => {
+    try {
+      await mtree.updateNode(path, data);
+      return true
+    } catch (error) {
+      return false // or throw error as you see fit
+    }
+  }
+
+  const treeModelX = new TreeModelX(host, MOUNT_POINT)
+
+  const itemHandle = function onReady(handler) {
+    // Initialize pgBrowser Tree
+    pgBrowser.tree = new Tree(handler, mtree, pgBrowser);
+    return true;
+  }
+
+  await treeModelX.root.ensureLoaded()
+
+  // Render Browser Tree
+  await render(
+    <div>
+      <FileTreeX height={999} width={'100%'} model={treeModelX}
+        onReady={itemHandle} create={create} remove={remove} update={update}/>
+     </div>, document.getElementById('tree'));
+}
+
+module.exports = {
+  initBrowserTree: initBrowserTree,
+};
+
diff --git a/web/pgadmin/static/js/tree/tree_nodes.ts b/web/pgadmin/static/js/tree/tree_nodes.ts
new file mode 100644
index 000000000..d1a40e6c8
--- /dev/null
+++ b/web/pgadmin/static/js/tree/tree_nodes.ts
@@ -0,0 +1,298 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import * as BrowserFS from 'browserfs'
+import url_for from 'sources/url_for';
+import pgAdmin from 'sources/pgadmin';
+import _ from 'underscore';
+import { FileType } from 'react-aspen'
+import { findInTree } from './tree';
+
+import { dirname } from 'path-fx';
+
+export class ManageTreeNodes {
+  constructor(fs) {
+    this.tree = {}
+	this.tempTree = new TreeNode(undefined, {});
+  }
+
+  public init = (_root: string) => new Promise((res, rej) => {
+    let node = {parent: null, children: [], data: null};
+    this.tree = {};
+    this.tree[_root] = {name: 'root', type: FileType.Directory, metadata: node};
+    res();
+  })
+
+  public updateNode = (_path, _data)  => new Promise((res, rej) => {
+    if (_path in this.tree) {
+      const item = this.tree[_path];
+      item.name = _data.label;
+      item.metadata.data = _data;
+    }
+    res(true);
+  })
+
+  public removeNode = async (_path, _removeOnlyChild)  => {
+    const item = this.findNode(_path);
+
+    if (item && item.parentNode) {
+      item.children = [];
+      item.parentNode.children.splice(item.parentNode.children.indexOf(item), 1);
+    }
+    return true;
+  };
+
+  findNode(path) {
+    if (path === null || path === undefined || path.length === 0 || path == '/browser') {
+      return this.tempTree;
+    }
+    return findInTree(this.tempTree, path);
+  }
+
+  public addNode = (_parent: string, _path: string, _data: []) => new Promise((res, rej) => {
+    _data.type = _data.inode ? FileType.Directory : FileType.File;
+    _data._label = _data.label;
+    _data.label = _.escape(_data.label);
+
+    _data.is_collection = isCollectionNode(_data._type);
+    let nodeData = {parent: _parent, children: [], data: _data};
+
+    let tmpParentNode = this.findNode(_parent);
+    let treeNode = new TreeNode(_data.id, _data, {}, tmpParentNode, nodeData, _data.type);
+
+    if (tmpParentNode !== null && tmpParentNode !== undefined) tmpParentNode.children.push(treeNode);
+
+    res(treeNode);
+  })
+
+  public readNode = (_path: string) => new Promise<string[]>((res, rej) => {
+      let temp_tree_path = _path;
+      let node = this.findNode(_path);
+
+      if (node && node.children.length > 0) {
+        if (!node.type === FileType.File) {
+          rej("It's a leaf node")
+        }
+        else {
+          if (node.children.length != 0) res(node.children)
+        }
+      }
+
+      var self = this;
+
+      async function loadData() {
+        let url = '';
+        if (_path == '/browser') {
+          url = url_for('browser.nodes');
+        } else {
+          let _parent_url = self.generate_url(_path);
+          if (node.metadata.data._pid == null ) {
+            url = node.metadata.data._type + '/children/' + node.metadata.data._id;
+          }
+          else {
+            if (node.metadata.data._type.includes("coll-")) {
+              let _type = node.metadata.data._type.replace("coll-", "")
+              url = _type + '/nodes/' + _parent_url;
+            }
+            else {
+              url = node.metadata.data._type + '/children/' + _parent_url + '/' + node.metadata.data._id;
+            }
+        }
+
+        temp_tree_path = node.path;
+
+        if (node.metadata.data._type == 'server' && !node.metadata.data.connected) {
+          url = null;
+        }
+      }
+
+      async function jsonData(url) {
+        let res = await fetch(url, {
+          headers: {
+            'X-Requested-With': 'XMLHttpRequest',
+            'X-pgA-CSRFToken': pgAdmin.csrf_token
+          },
+        });
+
+        if (res.status == 200) {
+          try {
+            let json = await res.json();
+            return json.data;
+          } catch (e) {
+            console.warn(e);
+          }
+        }
+        throw new Error("Node Load Error...");
+        return [];
+      }
+
+      let treeData = null;
+      if (url) treeData = await jsonData(url);
+
+      const Path = BrowserFS.BFSRequire('path')
+      const fill = async (tree) => {
+        for (let idx in tree) {
+          const _node = tree[idx]
+          const _pathl = Path.join(_path, _node.id)
+          await self.addNode(temp_tree_path, _pathl, _node);
+        }
+      }
+
+      let d = await fill(treeData);
+      if (node.children.length > 0) res(node.children);
+      else res(null);
+
+    }
+    loadData();
+  })
+
+  public generate_url = (path: string) => {
+    let _path = path;
+    let _parent_path = [];
+    while(_path != '/') {
+      let node = this.findNode(_path);
+      let _parent = dirname(_path);
+      if(node.parentNode && node.parentNode.path == _parent) {
+        if (node.parentNode.metadata.data !== null && !node.parentNode.metadata.data._type.includes('coll-'))
+          _parent_path.push(node.parentNode.metadata.data._id);
+     }
+     _path = _parent;
+    }
+    let _rev_arr = _parent_path.reverse();
+    return _rev_arr.join("/");
+  }
+}
+
+
+
+export class TreeNode {
+  constructor(id, data, domNode, parent, metadata, type) {
+    this.id = id;
+    this.data = data;
+    this.setParent(parent);
+    this.children = [];
+    this.domNode = domNode;
+    this.metadata = metadata;
+    this.name = metadata ? metadata.data.label : "";
+    this.type = type ? type : undefined;
+  }
+
+  hasParent() {
+    return this.parentNode !== null && this.parentNode !== undefined;
+  }
+
+  parent() {
+    return this.parentNode;
+  }
+
+  setParent(parent) {
+    this.parentNode = parent;
+    this.path = this.id;
+    if (this.id)
+      if (parent !== null && parent !== undefined && parent.path !== undefined) {
+        this.path = parent.path + '/' + this.id;
+      } else {
+        this.path =  '/browser/' + this.id;
+      }
+  }
+
+  getData() {
+    if (this.data === undefined) {
+      return undefined;
+    } else if (this.data === null) {
+      return null;
+    }
+    return Object.assign({}, this.data);
+  }
+
+  getHtmlIdentifier() {
+    return this.domNode;
+  }
+
+  /*
+   * Find the ancestor with matches this condition
+   */
+  ancestorNode(condition) {
+    let node = this;
+
+    while (node.hasParent()) {
+      node = node.parent();
+      if (condition(node)) {
+        return node;
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Given a condition returns true if the current node
+   * or any of the parent nodes condition result is true
+   */
+  anyFamilyMember(condition) {
+    if(condition(this)) {
+      return true;
+    }
+
+    return this.ancestorNode(condition) !== null;
+  }
+  anyParent(condition) {
+    return this.ancestorNode(condition) !== null;
+  }
+
+  reload(tree) {
+    return new Promise((resolve)=>{
+      this.unload(tree)
+        .then(()=>{
+          tree.setInode(this.domNode);
+          tree.deselect(this.domNode);
+          setTimeout(() => {
+            tree.selectNode(this.domNode);
+          }, 0);
+          resolve();
+        });
+    });
+  }
+
+  unload(tree) {
+    return new Promise((resolve, reject)=>{
+      this.children = [];
+      tree.unload(this.domNode)
+        .then(
+          ()=>{
+            resolve(true);
+          },
+          ()=>{
+            reject();
+          });
+    });
+  }
+
+
+  open(tree, suppressNoDom) {
+    return new Promise((resolve, reject)=>{
+      if(suppressNoDom && (this.domNode == null || typeof(this.domNode) === 'undefined')) {
+        resolve(true);
+      } else if(tree.isOpen(this.domNode)) {
+        resolve(true);
+      } else {
+        tree.open(this.domNode).then(val => resolve(true), err => reject(true));
+      }
+    });
+  }
+
+}
+
+export function isCollectionNode(node) {
+    if (pgAdmin.Browser.Nodes && node in pgAdmin.Browser.Nodes) {
+      if (pgAdmin.Browser.Nodes[node].is_collection !== undefined) return pgAdmin.Browser.Nodes[node].is_collection;
+      else return false;
+    }
+    return false;
+}
diff --git a/web/pgadmin/static/js/tree/tree_utils.js b/web/pgadmin/static/js/tree/tree_utils.js
index be6ca6df0..97b009ab4 100644
--- a/web/pgadmin/static/js/tree/tree_utils.js
+++ b/web/pgadmin/static/js/tree/tree_utils.js
@@ -11,8 +11,8 @@ import gettext from 'sources/gettext';
 
 export function retrieveAncestorOfTypeServer(pgBrowser, item, errorAlertTitle, alertify) {
   let serverInformation = null;
-  let aciTreeItem = item || pgBrowser.treeMenu.selected();
-  let treeNode = pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem);
+  let aciTreeItem = item || pgBrowser.tree.selected();
+  let treeNode = pgBrowser.tree.findNodeByDomElement(aciTreeItem);
 
   if (treeNode) {
     let nodeData;
@@ -58,9 +58,8 @@ export function retrieveAncestorOfTypeServer(pgBrowser, item, errorAlertTitle, a
 
 export function retrieveAncestorOfTypeDatabase(pgBrowser, item, errorAlertTitle, alertify) {
   let databaseInfo = null;
-  let aciTreeItem = item || pgBrowser.treeMenu.selected();
-  let treeNode = pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem);
-
+  let aciTreeItem = item || pgBrowser.tree.selected();
+  let treeNode = pgBrowser.tree.findNodeByDomElement(aciTreeItem);
   if (treeNode) {
     if(treeNode.getData()._type === 'database') {
       databaseInfo = treeNode.getData();
diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js
index 63186edf5..bd3e38578 100644
--- a/web/pgadmin/static/js/utils.js
+++ b/web/pgadmin/static/js/utils.js
@@ -8,7 +8,6 @@
 //////////////////////////////////////////////////////////////////////////
 
 import _ from 'underscore';
-import { getTreeNodeHierarchyFromIdentifier } from 'sources/tree/pgadmin_tree_node';
 import $ from 'jquery';
 import gettext from 'sources/gettext';
 import 'wcdocker';
@@ -237,7 +236,7 @@ export function quote_ident(value) {
 }
 
 export function fully_qualify(pgBrowser, data, item) {
-  const parentData = getTreeNodeHierarchyFromIdentifier.call(pgBrowser, item);
+  const parentData = pgBrowser.tree.getTreeNodeHierarchy(item);
   let namespace = '';
 
   if (parentData.schema !== undefined) {
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index d990b5509..9266f82e4 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -166,6 +166,7 @@
   right:0px;
   bottom:0px;
   height: 100%!important;
+  overflow: scroll;
 }
 
 .pg-prop-footer {
@@ -1089,12 +1090,15 @@ textarea {
     border-radius: $border-radius*2;
     background-clip: content-box;
     background-color: rgba($scrollbar-base-color, 0.7);
+    background: rgba($scrollbar-base-color, 0.7) !important;
 }
 
 ::-webkit-scrollbar-thumb:hover {
     background-color: $scrollbar-base-color;
+    background: $scrollbar-base-color !important;
 }
 
+
 input:-webkit-autofill,
 input:-webkit-autofill:hover,
 input:-webkit-autofill:focus,
diff --git a/web/pgadmin/static/scss/_pgadmin4-tree.overrides.scss b/web/pgadmin/static/scss/_pgadmin4-tree.overrides.scss
new file mode 100644
index 000000000..859d075b7
--- /dev/null
+++ b/web/pgadmin/static/scss/_pgadmin4-tree.overrides.scss
@@ -0,0 +1,123 @@
+.file-tree {
+	font-family: $font-family-primary !important;
+	font-size: $tree-font-size !important;
+	background-color: $color-bg !important;
+	display: inline-block;
+	color: $tree-text-fg !important;
+	&, & * {
+	  box-sizing: border-box;
+	}
+	width: 100%;
+}
+
+.file-tree > {
+	div {
+	    position: absolute !important;
+      height: 100% !important;
+      top: 0px !important;
+	}
+}
+
+.file-entry
+{
+  color: $tree-text-fg !important;
+  span.file-name {
+    color: $tree-text-fg !important;
+    white-space: nowrap;
+  }
+  &:hover, &.pseudo-active {
+    background-color: $tree-bg-hover !important;
+  }
+}
+
+.file-entry
+{
+    font: inherit;
+    text-align: left;
+    display: flex;
+    align-items: center;
+    white-space: nowrap;
+    padding: 2px 0;
+    padding-left: 2px;
+    cursor: default;
+    &:hover, &.pseudo-active {
+      background-color: $tree-bg-hover !important;
+    }
+    &.active, &.prompt {
+      background-color: $tree-bg-selected !important;
+      border-color: $color-primary-light;
+      border-right: $active-border !important;
+    }
+    i {
+        display: inline-block;
+        font: normal normal normal 18px/1 "default-icons";
+        font-size: 18px;
+        text-align: center;
+        height: 21px !important;
+        width: 20px;
+        &:before {
+            height: inherit;
+            width: inherit;
+            display: inline-block;
+        }
+        &.directory-toggle {
+            &:before {
+                background-position: 6px center !important;
+                font-family: $font-family-icon;
+                content: "\f054" !important;
+                border-style: none;
+                margin-left: 5px;
+                font-weight: 900;
+                right: 15px;
+                top: 3px;
+                font-size: 0.6rem;
+                line-height: 2;
+            }
+            &.open:before {
+              background-position: -14px center !important;
+              font-family: $font-family-icon;
+              content: "\f078" !important;
+              border-style: none;
+              margin-left: 5px;
+              font-weight: 900;
+              transform: none !important;
+            }
+            &.loading:before {
+              background-position: 6px center !important;
+              font-weight: 900;
+              font-size: 0.6rem;
+              line-height: 2;
+              content: '' !important;
+              font-family: $font-family-icon;
+              margin-left: 5px;
+              border-style: none;
+              background: $loader-icon-small 0 0 no-repeat;
+            }
+        }
+    }
+    span.file-label {
+        display: flex;
+        align-items: center;
+        padding:0 2px 0 2px;
+        border:1px solid transparent;
+        height:auto;
+        white-space:normal;
+        cursor:pointer;
+        margin-right:24px;
+    }
+    &.prompt.new .file-label, &.file .file-label {
+        margin-left: 18px;
+    }
+    span.file-name {
+        font: inherit;
+        flex-grow: 1;
+        user-select: none;
+        cursor: default;
+        color: #c1c1c1;
+        margin-left: 3px;
+    }
+}
+
+.children-count {
+    margin-left: 3px;
+}
diff --git a/web/pgadmin/static/scss/pgadmin.scss b/web/pgadmin/static/scss/pgadmin.scss
index 955f41d0f..d5b1e0864 100644
--- a/web/pgadmin/static/scss/pgadmin.scss
+++ b/web/pgadmin/static/scss/pgadmin.scss
@@ -33,3 +33,5 @@ $theme-colors: (
 @import 'pickr.overrides';
 @import 'tippy.overrides';
 @import 'jsoneditor.overrides';
+@import 'pgadmin4-tree.overrides';
+@import 'pgadmin4-tree/src/css/styles';
diff --git a/web/pgadmin/tools/backup/static/js/backup.js b/web/pgadmin/tools/backup/static/js/backup.js
index 9bb32f172..8d6c49819 100644
--- a/web/pgadmin/tools/backup/static/js/backup.js
+++ b/web/pgadmin/tools/backup/static/js/backup.js
@@ -199,7 +199,7 @@ define([
         if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
           var t = pgBrowser.tree,
             i = t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined;
+            d = i ? t.itemData(i) : undefined;
           return _.isUndefined(d) ? false : d.version >= 110000;
         }
         return true;
@@ -391,7 +391,7 @@ define([
         visible: function() {
           var t = pgBrowser.tree,
             i = t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
+            d = i  ? t.itemData(i) : undefined,
             s = _.isUndefined(d) ? undefined : pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
 
           return _.isUndefined(s) ? false : s.version >= 110000;
@@ -466,7 +466,7 @@ define([
 
           var t = pgBrowser.tree,
             i = t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
+            d = i  ? t.itemData(i) : undefined,
             s = _.isUndefined(d) ? undefined : pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
 
           return _.isUndefined(s) ? false : s.version >= 110000;
@@ -518,7 +518,7 @@ define([
         disabled: function(m) {
           var t = pgBrowser.tree,
             i = t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
+            d = i  ? t.itemData(i) : undefined,
             s = _.isUndefined(d) ? undefined : pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
 
           if (!_.isUndefined(s) && s.version >= 120000)
@@ -632,7 +632,7 @@ define([
         label: gettext('Backup...'),
         icon: 'fa fa-save',
         enable: supportedNodes.enabled.bind(
-          null, pgBrowser.treeMenu, menuUtils.backupSupportedNodes
+          null, pgBrowser.tree, menuUtils.backupSupportedNodes
         ),
         data: {
           data_disabled: gettext('Please select any database or schema or table from the browser tree to take Backup.'),
@@ -650,7 +650,7 @@ define([
           label: gettext('Backup...'),
           icon: 'fa fa-save',
           enable: supportedNodes.enabled.bind(
-            null, pgBrowser.treeMenu, menuUtils.backupSupportedNodes
+            null, pgBrowser.tree, menuUtils.backupSupportedNodes
           ),
         });
       }
diff --git a/web/pgadmin/tools/backup/static/js/backup_dialog.js b/web/pgadmin/tools/backup/static/js/backup_dialog.js
index 5f54b77c7..fb18ffd41 100644
--- a/web/pgadmin/tools/backup/static/js/backup_dialog.js
+++ b/web/pgadmin/tools/backup/static/js/backup_dialog.js
@@ -55,18 +55,15 @@ export class BackupDialog extends Dialog {
         );
         return;
       }
-
       const typeOfDialog = BackupDialog.typeOfDialog(params);
 
       if (!that.canExecuteOnCurrentDatabase(aciTreeItem)) {
         return;
       }
-
       const dialog = that.createOrGetDialog(
         BackupDialog.dialogTitle(typeOfDialog),
         typeOfDialog
       );
-
       dialog(true).resizeTo(width, height);
     }).catch(function() {
       that.alertify.alert(
diff --git a/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js b/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js
index 5a86bf82e..b45cb8008 100644
--- a/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js
+++ b/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js
@@ -7,7 +7,6 @@
 //
 //////////////////////////////////////////////////////////////
 
-import {getTreeNodeHierarchyFromElement} from '../../../../static/js/tree/pgadmin_tree_node';
 import axios from 'axios/index';
 import gettext from '../../../../static/js/gettext';
 import url_for from '../../../../static/js/url_for';
@@ -105,7 +104,7 @@ export class BackupDialogWrapper extends DialogWrapper {
       this.main(title);
     }
 
-    const treeInfo = getTreeNodeHierarchyFromElement(this.pgBrowser, selectedTreeNode);
+    const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
     const dialog = this.createDialog(node, treeInfo, this.typeOfDialog, $container);
     this.addAlertifyClassToBackupNodeChildNodes();
     dialog.render();
@@ -162,10 +161,7 @@ export class BackupDialogWrapper extends DialogWrapper {
         'sid': serverIdentifier,
       });
 
-      const treeInfo = getTreeNodeHierarchyFromElement(
-        this.pgBrowser,
-        selectedTreeNode
-      );
+      const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
 
       this.setExtraParameters(selectedTreeNode, treeInfo);
       let backupDate = this.view.model.toJSON();
@@ -222,7 +218,7 @@ export class BackupDialogWrapper extends DialogWrapper {
   }
 
   getSelectedNode() {
-    const tree = this.pgBrowser.treeMenu;
+    const tree = this.pgBrowser.tree;
     const selectedNode = tree.selected();
     if (selectedNode) {
       return tree.findNodeByDomElement(selectedNode);
@@ -260,10 +256,7 @@ export class BackupDialogWrapper extends DialogWrapper {
   }
 
   retrieveServerIdentifier(node, selectedTreeNode) {
-    const treeInfo = getTreeNodeHierarchyFromElement(
-      this.pgBrowser,
-      selectedTreeNode
-    );
+    const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
     return treeInfo.server._id;
   }
 
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid.js b/web/pgadmin/tools/datagrid/static/js/datagrid.js
index 84995d235..cabad10cc 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid.js
@@ -213,7 +213,7 @@ define('pgadmin.datagrid', [
         const transId = commonUtils.getRandomInt(1, 9999999);
         var t = pgBrowser.tree,
           i = aciTreeIdentifier || t.selected(),
-          d = i && i.length == 1 ? t.itemData(i) : undefined;
+          d = i ? t.itemData(i) : undefined;
 
         //Open query tool with create script if copy_sql_to_query_tool is true else open blank query tool
         var preference = pgBrowser.get_preference('sqleditor', 'copy_sql_to_query_tool');
@@ -312,7 +312,7 @@ define('pgadmin.datagrid', [
                   if(panel_data.$titleText[0].innerHTML.includes('File - ')) {
                     is_file = true;
                   }
-                  var selected_item = pgBrowser.treeMenu.selected();
+                  var selected_item = pgBrowser.tree.selected();
                   var panel_titles = '';
 
                   if(is_query_tool) {
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js b/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
index 368da487c..660fd3c81 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid_panel_title.js
@@ -7,7 +7,6 @@
 //
 //////////////////////////////////////////////////////////////
 
-import {getTreeNodeHierarchyFromIdentifier} from '../../../../static/js/tree/pgadmin_tree_node';
 import gettext from 'sources/gettext';
 import Alertify from 'pgadmin.alertifyjs';
 import pgWindow from 'sources/window';
@@ -26,11 +25,12 @@ function isServerInformationAvailable(parentData) {
 export function getPanelTitle(pgBrowser, selected_item=null, custom_title=null, parentData=null, conn_title=false, db_label=null) {
   var preferences = pgBrowser.get_preferences_for_module('browser');
   if(selected_item == null && parentData == null) {
-    selected_item = pgBrowser.treeMenu.selected();
+    selected_item = pgBrowser.tree.selected();
   }
 
   if(parentData == null) {
-    parentData = getTreeNodeHierarchyFromIdentifier.call(pgBrowser, selected_item);
+    parentData = pgBrowser.tree.getTreeNodeHierarchy(selected_item);
+    if(parentData == null) return;
     if (isServerInformationAvailable(parentData)) {
       return;
     }
diff --git a/web/pgadmin/tools/datagrid/static/js/show_data.js b/web/pgadmin/tools/datagrid/static/js/show_data.js
index b1e19aaa4..018f51607 100644
--- a/web/pgadmin/tools/datagrid/static/js/show_data.js
+++ b/web/pgadmin/tools/datagrid/static/js/show_data.js
@@ -8,7 +8,6 @@
 //////////////////////////////////////////////////////////////
 import gettext from '../../../../static/js/gettext';
 import url_for from '../../../../static/js/url_for';
-import {getTreeNodeHierarchyFromIdentifier} from '../../../../static/js/tree/pgadmin_tree_node';
 import {getDatabaseLabel, generateTitle} from './datagrid_panel_title';
 import CodeMirror from 'bundled_codemirror';
 import * as SqlEditorUtils from 'sources/sqleditor_utils';
@@ -25,7 +24,7 @@ export function showDataGrid(
   filter=false,
   preferences=null
 ) {
-  const node = pgBrowser.treeMenu.findNodeByDomElement(aciTreeIdentifier);
+  const node = pgBrowser.tree.findNodeByDomElement(aciTreeIdentifier);
   if (node === undefined || !node.getData()) {
     alertify.alert(
       gettext('Data Grid Error'),
@@ -34,9 +33,7 @@ export function showDataGrid(
     return;
   }
 
-  const parentData = getTreeNodeHierarchyFromIdentifier.call(
-    pgBrowser,
-    aciTreeIdentifier
+  const parentData = pgBrowser.tree.getTreeNodeHierarchy(  aciTreeIdentifier
   );
 
   if (hasServerOrDatabaseConfiguration(parentData)
@@ -293,14 +290,13 @@ function hasSchemaOrCatalogOrViewInformation(parentData) {
 export function generateDatagridTitle(pgBrowser, aciTreeIdentifier, custom_title=null, backend_entity=null) {
   //const baseTitle = getPanelTitle(pgBrowser, aciTreeIdentifier);
   var preferences = pgBrowser.get_preferences_for_module('browser');
-  const parentData = getTreeNodeHierarchyFromIdentifier.call(
-    pgBrowser,
+  const parentData = pgBrowser.tree.getTreeNodeHierarchy(
     aciTreeIdentifier
   );
 
   const namespaceName = retrieveNameSpaceName(parentData);
   const db_label = !_.isUndefined(backend_entity) && backend_entity != null && backend_entity.hasOwnProperty('db_name') ? backend_entity['db_name'] : getDatabaseLabel(parentData);
-  const node = pgBrowser.treeMenu.findNodeByDomElement(aciTreeIdentifier);
+  const node = pgBrowser.tree.findNodeByDomElement(aciTreeIdentifier);
 
   var dtg_title_placeholder = '';
   if(custom_title) {
diff --git a/web/pgadmin/tools/datagrid/static/js/show_query_tool.js b/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
index 33b894788..11e9d1f98 100644
--- a/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
+++ b/web/pgadmin/tools/datagrid/static/js/show_query_tool.js
@@ -9,7 +9,6 @@
 
 import gettext from '../../../../static/js/gettext';
 import url_for from '../../../../static/js/url_for';
-import {getTreeNodeHierarchyFromIdentifier} from '../../../../static/js/tree/pgadmin_tree_node';
 import {getPanelTitle} from './datagrid_panel_title';
 import {getRandomInt} from 'sources/utils';
 import $ from 'jquery';
@@ -52,7 +51,7 @@ export function showQueryTool(datagrid, pgBrowser, alertify, url, aciTreeIdentif
   const sURL = url || '';
   const queryToolTitle = generateTitle(pgBrowser, aciTreeIdentifier);
 
-  const currentNode = pgBrowser.treeMenu.findNodeByDomElement(aciTreeIdentifier);
+  const currentNode = pgBrowser.tree.findNodeByDomElement(aciTreeIdentifier);
   if (currentNode === undefined) {
     alertify.alert(
       gettext('Query Tool Error'),
@@ -61,8 +60,7 @@ export function showQueryTool(datagrid, pgBrowser, alertify, url, aciTreeIdentif
     return;
   }
 
-  const parentData = getTreeNodeHierarchyFromIdentifier.call(
-    pgBrowser, aciTreeIdentifier);
+  const parentData = pgBrowser.tree.getTreeNodeHierarchy(currentNode);
 
   if (hasServerInformations(parentData)) {
     return;
diff --git a/web/pgadmin/tools/debugger/static/js/debugger.js b/web/pgadmin/tools/debugger/static/js/debugger.js
index 6632b83c1..ea34c2bd5 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger.js
@@ -227,13 +227,12 @@ define([
       // Find the function is really available in database
       var tree = pgBrowser.tree,
         info = tree.selected(),
-        d_ = info && info.length == 1 ? tree.itemData(info) : undefined,
-        node = d_ && pgBrowser.Nodes[d_._type];
+        d_ = info ? tree.itemData(info) : undefined;
 
       if (!d_)
         return false;
 
-      var treeInfo = node.getTreeNodeHierarchy.apply(node, [info]);
+      var treeInfo = tree.getTreeNodeHierarchy(info);
 
       // For indirect debugging user must be super user
       if (data && data.debug_type && data.debug_type == 'indirect' &&
@@ -302,13 +301,13 @@ define([
     check_func_debuggable: function(args, item) {
       var t = pgBrowser.tree,
         i = item || t.selected(),
-        d = i && i.length == 1 ? t.itemData(i) : undefined,
+        d = i ? t.itemData(i) : undefined,
         node = d && pgBrowser.Nodes[d._type];
 
       if (!d)
         return;
 
-      var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
+      var treeInfo = t.getTreeNodeHierarchy(i),
         _url = this.generate_url('init', treeInfo, node);
 
       var self = this;
@@ -338,16 +337,15 @@ define([
       var self = this;
       var t = pgBrowser.tree,
         i = item || t.selected(),
-        d = i && i.length == 1 ? t.itemData(i) : undefined,
-        node = d && pgBrowser.Nodes[d._type],
-        tree_data = pgBrowser.treeMenu.translateTreeNodeIdFromACITree(i),
-        db_data = pgBrowser.treeMenu.findNode(tree_data.slice(0,4)),
+        d = i ? t.itemData(i) : undefined,
+        tree_data = pgBrowser.tree.translateTreeNodeIdFromReactTree(i),
+        db_data = pgBrowser.tree.findNode(tree_data[3]),
         dbNode = db_data.domNode;
 
       if (!d)
         return;
 
-      var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
+      var treeInfo = t.getTreeNodeHierarchy(i),
         baseUrl;
 
       if (d._type == 'function' || d._type == 'edbfunc') {
@@ -515,10 +513,10 @@ define([
 
       var t = pgBrowser.tree,
         i = item || t.selected(),
-        d = i && i.length == 1 ? t.itemData(i) : undefined,
+        d = i ? t.itemData(i) : undefined,
         node = d && pgBrowser.Nodes[d._type],
-        tree_data = pgBrowser.treeMenu.translateTreeNodeIdFromACITree(i),
-        db_data = pgBrowser.treeMenu.findNode(tree_data.slice(0,4)),
+        tree_data = pgBrowser.tree.translateTreeNodeIdFromReactTree(i),
+        db_data = pgBrowser.tree.findNode(tree_data[3]),
         dbNode = db_data.domNode;
 
       if (!d)
@@ -526,7 +524,7 @@ define([
 
       var is_edb_proc = d._type == 'edbproc';
 
-      var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
+      var treeInfo = t.getTreeNodeHierarchy(i),
         _url = this.generate_url('init', treeInfo, node);
 
       $.ajax({
@@ -546,13 +544,12 @@ define([
           // Directly open the panel
             var _t = pgBrowser.tree,
               _i = _t.selected(),
-              _d = _i && _i.length == 1 ? _t.itemData(_i) : undefined,
-              _node = _d && pgBrowser.Nodes[_d._type];
+              _d = _i ? _t.itemData(_i) : undefined;
 
             if (!_d)
               return;
 
-            var newTreeInfo = _node.getTreeNodeHierarchy.apply(_node, [_i]),
+            var newTreeInfo = _t.getTreeNodeHierarchy(_i),
               baseUrl;
 
             if (_d._type == 'function' || _d._type == 'edbfunc') {
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_ui.js b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
index 43ee2f3f6..2d6717144 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_ui.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
@@ -188,13 +188,12 @@ define([
             if (restart_debug == 0) {
               var t = pgBrowser.tree,
                 i = t.selected(),
-                d = i && i.length == 1 ? t.itemData(i) : undefined,
-                node = d && pgBrowser.Nodes[d._type];
+                d = i ? t.itemData(i) : undefined;
 
               if (!d)
                 return;
 
-              var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]),
+              var treeInfo = t.getTreeNodeHierarchy(i),
                 _Url;
 
               if (d._type == 'function') {
@@ -623,13 +622,12 @@ define([
               if (self.setting('restart_debug') == 0) {
                 var t = pgBrowser.tree,
                   i = t.selected(),
-                  d = i && i.length == 1 ? t.itemData(i) : undefined,
-                  node = d && pgBrowser.Nodes[d._type];
+                  d = i ? t.itemData(i) : undefined;
 
                 if (!d)
                   return;
 
-                var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
+                var treeInfo = t.getTreeNodeHierarchy(i);
               }
 
               var args_value_list = [];
@@ -939,8 +937,7 @@ define([
                 if (!item_data)
                   return;
 
-                let node_ele = pgBrowser.Nodes[item_data._type];
-                let tree_info = node_ele.getTreeNodeHierarchy.call(node_ele, selected_item);
+                let tree_info = pgBrowser.tree.getTreeNodeHierarchy(selected_item);
 
                 base_url = url_for('debugger.clear_arguments', {
                   'sid': tree_info.server._id,
diff --git a/web/pgadmin/tools/erd/static/js/erd_module.js b/web/pgadmin/tools/erd/static/js/erd_module.js
index 61327214f..70f671ad6 100644
--- a/web/pgadmin/tools/erd/static/js/erd_module.js
+++ b/web/pgadmin/tools/erd/static/js/erd_module.js
@@ -8,7 +8,6 @@
 //////////////////////////////////////////////////////////////
 
 import Alertify from 'pgadmin.alertifyjs';
-import {getTreeNodeHierarchyFromIdentifier} from 'sources/tree/pgadmin_tree_node';
 import {getPanelTitle} from 'tools/datagrid/static/js/datagrid_panel_title';
 import {getRandomInt, registerDetachEvent} from 'sources/utils';
 
@@ -98,10 +97,9 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, pgBrowser
       return isEnabled;
     },
 
-    // Callback to draw schema diff for objects
+    // Callback to draw ERD Tool for objects
     showErdTool: function(data, aciTreeIdentifier, gen=false) {
-      const node = pgBrowser.treeMenu.findNodeByDomElement(aciTreeIdentifier);
-      if (node === undefined || !node.getData()) {
+      if (aciTreeIdentifier === undefined) {
         Alertify.alert(
           gettext('ERD Error'),
           gettext('No object selected.')
@@ -109,10 +107,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, pgBrowser
         return;
       }
 
-      const parentData = getTreeNodeHierarchyFromIdentifier.call(
-        pgBrowser,
-        aciTreeIdentifier
-      );
+      const parentData = pgBrowser.tree.getTreeNodeHierarchy(aciTreeIdentifier);
 
       if(_.isUndefined(parentData.database)) {
         Alertify.alert(
diff --git a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
index efc8fe56b..1f26c8d8e 100644
--- a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
+++ b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
@@ -52,7 +52,7 @@ define([
         label: gettext('Grant Wizard...'),
         icon: 'fa fa-unlock',
         enable: supportedNodes.enabled.bind(
-          null, pgBrowser.treeMenu, menuUtils.supportedNodes
+          null, pgBrowser.tree, menuUtils.supportedNodes
         ),
         data: {
           data_disabled: gettext('Please select any database, schema or schema objects from the browser tree to access Grant Wizard Tool.'),
@@ -71,7 +71,7 @@ define([
           label: gettext('Grant Wizard...'),
           icon: 'fa fa-unlock',
           enable: supportedNodes.enabled.bind(
-            null, pgBrowser.treeMenu, menuUtils.supportedNodes
+            null, pgBrowser.tree, menuUtils.supportedNodes
           ),
         });
       }
@@ -112,8 +112,8 @@ define([
               Alertify.pgDialogBuild.apply(this);
               var t = pgBrowser.tree,
                 i = t.selected(),
-                d = this.d = i && i.length == 1 ? t.itemData(i) : undefined,
-                info = this.info = pgBrowser.Node.getTreeNodeHierarchy(i);
+                d = this.d = i ? t.itemData(i) : undefined,
+                info = this.info = pgBrowser.tree.getTreeNodeHierarchy(i);
 
               var sid = info.server._id,
                 did = info.database._id;
diff --git a/web/pgadmin/tools/import_export/static/js/import_export.js b/web/pgadmin/tools/import_export/static/js/import_export.js
index 1dd8e1a91..92f112ba1 100644
--- a/web/pgadmin/tools/import_export/static/js/import_export.js
+++ b/web/pgadmin/tools/import_export/static/js/import_export.js
@@ -410,7 +410,7 @@ define([
         label: gettext('Import/Export...'),
         icon: 'fa fa-shopping-cart',
         enable: supportedNodes.enabled.bind(
-          null, pgBrowser.treeMenu, ['table']
+          null, pgBrowser.tree, ['table']
         ),
         data: {
           data_disabled: gettext('Please select any table from the browser tree to Import/Export data.'),
@@ -433,7 +433,7 @@ define([
         }
 
         if (pgBrowser.tree.hasParent(i)) {
-          i = $(pgBrowser.tree.parent(i));
+          i = pgBrowser.tree.parent(i);
         } else {
           Alertify.alert(gettext('Please select server or child node from tree.'));
           break;
@@ -450,13 +450,13 @@ define([
 
       var t = pgBrowser.tree;
       i = item || t.selected();
-      var d = i && i.length == 1 ? t.itemData(i) : undefined,
+      var d = i  ? t.itemData(i) : undefined,
         node = d && pgBrowser.Nodes[d._type];
 
       if (!d)
         return;
 
-      var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
+      var treeInfo = t && t.getTreeNodeHierarchy(i);
 
       if (!Alertify.ImportDialog) {
         Alertify.dialog('ImportDialog', function factory() {
diff --git a/web/pgadmin/tools/maintenance/static/js/maintenance.js b/web/pgadmin/tools/maintenance/static/js/maintenance.js
index 6df2d94fd..93dc5ffd9 100644
--- a/web/pgadmin/tools/maintenance/static/js/maintenance.js
+++ b/web/pgadmin/tools/maintenance/static/js/maintenance.js
@@ -166,7 +166,7 @@ define([
         label: gettext('Maintenance...'),
         icon: 'fa fa-wrench',
         enable: supportedNodes.enabled.bind(
-          null, pgBrowser.treeMenu, menuUtils.maintenanceSupportedNodes
+          null, pgBrowser.tree, menuUtils.maintenanceSupportedNodes
         ),
         data: {
           data_disabled: gettext('Please select any database from the browser tree to do Maintenance.'),
@@ -185,7 +185,7 @@ define([
           label: gettext('Maintenance...'),
           icon: 'fa fa-wrench',
           enable: supportedNodes.enabled.bind(
-            null, pgBrowser.treeMenu, menuUtils.maintenanceSupportedNodes
+            null, pgBrowser.tree, menuUtils.maintenanceSupportedNodes
           ),
           data: {
             data_disabled: gettext('Please select any database from the browser tree to do Maintenance.'),
@@ -210,7 +210,7 @@ define([
         }
 
         if (pgBrowser.tree.hasParent(i)) {
-          i = $(pgBrowser.tree.parent(i));
+          i = pgBrowser.tree.parent(i);
         } else {
           Alertify.alert(gettext('Please select server or child node from tree.'));
           break;
@@ -230,13 +230,12 @@ define([
 
       i = item || t.selected();
 
-      var d = i && i.length == 1 ? t.itemData(i) : undefined;
+      var d = i  ? t.itemData(i) : undefined;
 
       if (!d)
         return;
 
-      var node = pgBrowser.Nodes[d._type],
-        treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
+      var treeInfo = t && t.getTreeNodeHierarchy(i);
 
       if (treeInfo.database._label.indexOf('=') >= 0) {
         Alertify.alert(
@@ -325,7 +324,7 @@ define([
                 if (!itemData)
                   return;
 
-                var node_hierarchy = sel_node.getTreeNodeHierarchy.apply(sel_node, [sel_item]);
+                var node_hierarchy = pgBrowser.tree.getTreeNodeHierarchy.apply(sel_item);
 
                 if (node_hierarchy.schema != undefined) {
                   schema = node_hierarchy.schema._label;
@@ -415,7 +414,7 @@ define([
               if (!itemInfo)
                 return;
 
-              var treeData = nodeData.getTreeNodeHierarchy.apply(nodeData, [sel_item]);
+              var treeData = tree.getTreeNodeHierarchy.apply(nodeData, [sel_item]);
 
               var newModel = new MaintenanceModel({}, {
                   node_info: treeData,
diff --git a/web/pgadmin/tools/psql/static/js/psql_module.js b/web/pgadmin/tools/psql/static/js/psql_module.js
index 94a66ec57..8feb15cd4 100644
--- a/web/pgadmin/tools/psql/static/js/psql_module.js
+++ b/web/pgadmin/tools/psql/static/js/psql_module.js
@@ -18,7 +18,6 @@ import {getRandomInt, hasBinariesConfiguration, registerDetachEvent} from 'sourc
 import {retrieveAncestorOfTypeServer} from 'sources/tree/tree_utils';
 import pgWindow from 'sources/window';
 
-import {getTreeNodeHierarchyFromIdentifier} from 'sources/tree/pgadmin_tree_node';
 import {generateTitle, refresh_db_node} from 'tools/datagrid/static/js/datagrid_panel_title';
 
 
@@ -120,7 +119,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
         return;
       }
 
-      const node = pgBrowser.treeMenu.findNodeByDomElement(aciTreeIdentifier);
+      const node = pgBrowser.tree.findNodeByDomElement(aciTreeIdentifier);
       if (node === undefined || !node.getData()) {
         Alertify.alert(
           gettext('PSQL Error'),
@@ -129,10 +128,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
         return;
       }
 
-      parentData = getTreeNodeHierarchyFromIdentifier.call(
-        pgBrowser,
-        aciTreeIdentifier
-      );
+      parentData = pgBrowser.tree.translateTreeNodeIdFromReactTree(aciTreeIdentifier);
 
       if(_.isUndefined(parentData.server)) {
         Alertify.alert(
@@ -366,9 +362,9 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
     check_db_name_change: function(db_name, o_db_name) {
       if (db_name != o_db_name) {
 
-        var selected_item = pgWindow.pgAdmin.Browser.treeMenu.selected(),
-          tree_data = pgWindow.pgAdmin.Browser.treeMenu.translateTreeNodeIdFromACITree(selected_item),
-          database_data = pgWindow.pgAdmin.Browser.treeMenu.findNode(tree_data.slice(0,4)),
+        var selected_item = pgWindow.pgAdmin.Browser.tree.selected(),
+          tree_data = pgWindow.pgAdmin.Browser.tree.translateTreeNodeIdFromReactTree(selected_item),
+          database_data = pgWindow.pgAdmin.Browser.tree.findNode(tree_data[3]),
           dbNode = database_data.domNode;
 
         var message = `Current database has been moved or renamed to ${o_db_name}. Click on the OK button to refresh the database name, and reopen the psql again.`;
diff --git a/web/pgadmin/tools/restore/static/js/restore.js b/web/pgadmin/tools/restore/static/js/restore.js
index b0d43f9e5..50bd63dc5 100644
--- a/web/pgadmin/tools/restore/static/js/restore.js
+++ b/web/pgadmin/tools/restore/static/js/restore.js
@@ -271,8 +271,8 @@ define('tools.restore', [
         visible: function() {
           var t = pgBrowser.tree,
             i = t.selected(),
-            d = i && i.length == 1 ? t.itemData(i) : undefined,
-            s = _.isUndefined(d) ? undefined : pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
+            d = i  ? t.itemData(i) : undefined,
+            s = _.isUndefined(d) ? undefined : pgBrowser.tree.getTreeNodeHierarchy(i)['server'];
 
           return _.isUndefined(s) ? false : s.version >= 110000;
         },
@@ -396,7 +396,7 @@ define('tools.restore', [
         label: gettext('Restore...'),
         icon: 'fa fa-upload',
         enable: supportedNodes.enabled.bind(
-          null, pgBrowser.treeMenu, menuUtils.restoreSupportedNodes
+          null, pgBrowser.tree, menuUtils.restoreSupportedNodes
         ),
         data: {
           data_disabled: gettext('Please select any schema or table from the browser tree to Restore data.'),
@@ -414,7 +414,7 @@ define('tools.restore', [
           label: gettext('Restore...'),
           icon: 'fa fa-upload',
           enable: supportedNodes.enabled.bind(
-            null, pgBrowser.treeMenu, menuUtils.restoreSupportedNodes
+            null, pgBrowser.tree, menuUtils.restoreSupportedNodes
           ),
         });
       }
diff --git a/web/pgadmin/tools/restore/static/js/restore_dialog.js b/web/pgadmin/tools/restore/static/js/restore_dialog.js
index 20a22aa8d..f2e95caec 100644
--- a/web/pgadmin/tools/restore/static/js/restore_dialog.js
+++ b/web/pgadmin/tools/restore/static/js/restore_dialog.js
@@ -57,8 +57,8 @@ export class RestoreDialog extends Dialog {
         return;
       }
 
-      let aciTreeItem1 = aciTreeItem || that.pgBrowser.treeMenu.selected();
-      let item = that.pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem1);
+      let aciTreeItem1 = aciTreeItem || that.pgBrowser.tree.selected();
+      let item = that.pgBrowser.tree.findNodeByDomElement(aciTreeItem1);
       const data = item.getData();
       const node = that.pgBrowser.Nodes[data._type];
 
diff --git a/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js b/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js
index c9cda5d66..ee57cb2f9 100644
--- a/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js
+++ b/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js
@@ -7,7 +7,6 @@
 //
 //////////////////////////////////////////////////////////////
 
-import {getTreeNodeHierarchyFromElement} from '../../../../static/js/tree/pgadmin_tree_node';
 import axios from 'axios/index';
 import _ from 'underscore';
 import gettext from '../../../../static/js/gettext';
@@ -93,8 +92,7 @@ export class RestoreDialogWrapper extends DialogWrapper {
     }
 
     const node = this.pgBrowser.Nodes[selectedTreeNodeData._type];
-
-    const treeInfo = getTreeNodeHierarchyFromElement(this.pgBrowser, selectedTreeNode);
+    const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
     const dialog = this.createDialog(node, treeInfo, $container);
     this.addAlertifyClassToRestoreNodeChildNodes();
     dialog.render();
@@ -149,10 +147,7 @@ export class RestoreDialogWrapper extends DialogWrapper {
         'sid': serverIdentifier,
       });
 
-      const treeInfo = getTreeNodeHierarchyFromElement(
-        this.pgBrowser,
-        selectedTreeNode
-      );
+      const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
 
       this.setExtraParameters(selectedTreeNode, treeInfo);
 
@@ -190,7 +185,7 @@ export class RestoreDialogWrapper extends DialogWrapper {
   }
 
   getSelectedNode() {
-    const tree = this.pgBrowser.treeMenu;
+    const tree = this.pgBrowser.tree;
     const selectedNode = tree.selected();
     if (selectedNode) {
       return tree.findNodeByDomElement(selectedNode);
@@ -225,10 +220,7 @@ export class RestoreDialogWrapper extends DialogWrapper {
   }
 
   retrieveServerIdentifier(node, selectedTreeNode) {
-    const treeInfo = getTreeNodeHierarchyFromElement(
-      this.pgBrowser,
-      selectedTreeNode
-    );
+    const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
     return treeInfo.server._id;
   }
 
diff --git a/web/pgadmin/tools/search_objects/static/js/search_objects_dialog_wrapper.js b/web/pgadmin/tools/search_objects/static/js/search_objects_dialog_wrapper.js
index 2bec153d2..62d37edc1 100644
--- a/web/pgadmin/tools/search_objects/static/js/search_objects_dialog_wrapper.js
+++ b/web/pgadmin/tools/search_objects/static/js/search_objects_dialog_wrapper.js
@@ -1,4 +1,12 @@
-import {getTreeNodeHierarchyFromElement} from 'sources/tree/pgadmin_tree_node';
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
 import axios from 'axios/index';
 import gettext from 'sources/gettext';
 import url_for from 'sources/url_for';
@@ -261,7 +269,7 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
 
     this.grid.onDblClick.subscribe((event, args) => {
       let rowData = this.dataview.getItem(args.row);
-      let treeMenu = this.pgBrowser.treeMenu;
+      let tree = this.pgBrowser.tree;
 
       if(!rowData.show_node) {
         this.showMessage(
@@ -278,9 +286,9 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
         return false;
       }
       this.showMessage(gettext('Locating...'));
-      treeMenu.findNodeWithToggle(rowData.id_path)
+      tree.findNodeWithToggle(rowData.id_path)
         .then((treeItem)=>{
-          treeMenu.selectNode(treeItem.domNode, true);
+          tree.select(treeItem, true);
           this.showMessage(null);
         })
         .catch((error)=>{
@@ -349,7 +357,7 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
   }
 
   getSelectedNode() {
-    const tree = this.pgBrowser.treeMenu;
+    const tree = this.pgBrowser.tree;
     const selectedNode = tree.selected();
     if (selectedNode) {
       return tree.findNodeByDomElement(selectedNode);
@@ -404,7 +412,7 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
     let id_path = [
       this.treeInfo.server_group.id,
       this.treeInfo.server.id,
-      this.getCollNode('database').type + '/' + this.treeInfo.server._id,
+      this.getCollNode('database').type + '_' + this.treeInfo.server._id,
       this.treeInfo.database.id,
     ];
 
@@ -435,10 +443,10 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
       let coll_node = this.getCollNode(node_type);
       if(coll_node) {
         /* Add coll node to the path */
-        if(prev_node_id != null) id_path.push(`${coll_node.type}/${prev_node_id}`);
+        if(prev_node_id != null) id_path.push(`${coll_node.type}_${prev_node_id}`);
 
         /* Add the node to the path */
-        id_path.push(`${node_type}/${node_oid}`);
+        id_path.push(`${node_type}_${node_oid}`);
 
         /* This will be needed for coll node */
         prev_node_id = node_oid;
@@ -447,7 +455,7 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
         return  `/${coll_node.label}/`;
       } else if(node_type in this.pgBrowser.Nodes) {
         /* Add the node to the path */
-        id_path.push(`${node_type}/${node_oid}`);
+        id_path.push(`${node_type}_${node_oid}`);
 
         /* This will be need for coll node id path */
         prev_node_id = node_oid;
@@ -652,7 +660,7 @@ export default class SearchObjectsDialogWrapper extends DialogWrapper {
       return;
     }
 
-    this.treeInfo = getTreeNodeHierarchyFromElement(this.pgBrowser, selectedTreeNode);
+    this.treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
     this.prepareDialog();
     this.focusOnDialog(this);
   }
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index f221161eb..a641ecba8 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -2720,26 +2720,20 @@ define('tools.querytool', [
 
           $('#btn-conn-status i').removeClass('obtaining-conn');
 
-          var tree_data = pgWindow.default.pgAdmin.Browser.treeMenu.translateTreeNodeIdFromACITree(pgWindow.default.pgAdmin.Browser.treeMenu.selected());
-
-          var server_data = pgWindow.default.pgAdmin.Browser.treeMenu.findNode(tree_data.slice(0,2));
-          var database_data = pgWindow.default.pgAdmin.Browser.treeMenu.findNode(tree_data.slice(0,4));
-          var dbData = tree_data.slice(0,3);
-          dbData.push('database/' + url_params.did);
-          var dbName = pgWindow.default.pgAdmin.Browser.treeMenu.findNode(dbData).data.label;
-          let conn_title = panelTitleFunc.getPanelTitle(pgWindow.default.pgAdmin.Browser, null, null, null, true, dbName);
+          var tree_data = pgWindow.default.pgAdmin.Browser.tree.getTreeNodeHierarchy(pgWindow.default.pgAdmin.Browser.tree.selected());
+          let conn_title = panelTitleFunc.getPanelTitle(pgWindow.default.pgAdmin.Browser, null, null, null, true, tree_data.database.label);
           self.gridView.set_editor_title(_.unescape(conn_title));
           let connection_data = {
             'server_group': self.gridView.handler.url_params.sgid,
             'server': self.gridView.handler.url_params.sid,
             'database': self.gridView.handler.url_params.did,
-            'user': server_data.data.user.name,
+            'user': tree_data.server.user.name,
             'role': null,
             'title': _.unescape(url_params.title),
             'conn_title': _.unescape(conn_title),
             'is_allow_new_connection': false,
-            'database_name': _.unescape(database_data.data.label),
-            'server_name': _.unescape(server_data.data.label),
+            'database_name': _.unescape(tree_data.database.label),
+            'server_name': _.unescape(tree_data.server.label),
             'is_selected': true,
           };
           delete connection_data.password;
@@ -5171,10 +5165,10 @@ define('tools.querytool', [
 
         var self = this;
 
-        var selected_item = pgWindow.default.pgAdmin.Browser.treeMenu.selected(),
-          tree_data = pgWindow.default.pgAdmin.Browser.treeMenu.translateTreeNodeIdFromACITree(selected_item),
-          server_data = pgWindow.default.pgAdmin.Browser.treeMenu.findNode(tree_data.slice(0,2)),
-          database_data = pgWindow.default.pgAdmin.Browser.treeMenu.findNode(tree_data.slice(0,4)),
+        var selected_item = pgWindow.default.pgAdmin.Browser.tree.selected(),
+          tree_data = pgWindow.default.pgAdmin.Browser.tree.translateTreeNodeIdFromReactTree(selected_item),
+          server_data = pgWindow.default.pgAdmin.Browser.tree.findNode(tree_data[1]),
+          database_data = pgWindow.default.pgAdmin.Browser.tree.findNode(tree_data[3]),
           db_name = database_data.data.label,
           db_did = database_data.data._id;
 
diff --git a/web/regression/javascript/backup/backup_dialog_spec.js b/web/regression/javascript/backup/backup_dialog_spec.js
index 8793e0976..2ac646760 100644
--- a/web/regression/javascript/backup/backup_dialog_spec.js
+++ b/web/regression/javascript/backup/backup_dialog_spec.js
@@ -22,7 +22,6 @@ describe('BackupDialog', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
       Nodes: {
         server: {
           hasId: true,
@@ -53,6 +52,7 @@ describe('BackupDialog', () => {
         default: 550,
       },
     };
+    pgBrowser.tree = new TreeFake(pgBrowser);
     pgBrowser.Nodes.server.hasId = true;
     pgBrowser.Nodes.database.hasId = true;
     jquerySpy = jasmine.createSpy('jquerySpy');
@@ -126,7 +126,7 @@ describe('BackupDialog', () => {
       ],
     };
 
-    pgBrowser.treeMenu = TreeFake.build(hierarchy);
+    pgBrowser.tree = TreeFake.build(hierarchy, pgBrowser);
   });
 
   describe('#draw', () => {
@@ -151,7 +151,7 @@ describe('BackupDialog', () => {
 
     context('there are no ancestors of the type server', () => {
       it('does not create a dialog', () => {
-        pgBrowser.treeMenu.selectNode([{id: 'root'}]);
+        pgBrowser.tree.selectNode([{id: 'root'}]);
         backupDialog.draw(null, null, null);
         expect(alertifySpy['backup_objects']).not.toHaveBeenCalled();
       });
diff --git a/web/regression/javascript/backup/backup_dialog_wrapper_spec.js b/web/regression/javascript/backup/backup_dialog_wrapper_spec.js
index 1fcb44c04..e3c91ecea 100644
--- a/web/regression/javascript/backup/backup_dialog_wrapper_spec.js
+++ b/web/regression/javascript/backup/backup_dialog_wrapper_spec.js
@@ -12,7 +12,7 @@ import {BackupDialogWrapper} from '../../../pgadmin/tools/backup/static/js/backu
 import axios from 'axios/index';
 import MockAdapter from 'axios-mock-adapter';
 import {FakeModel} from '../fake_model';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 
 let context = describe;
 
@@ -34,7 +34,6 @@ describe('BackupDialogWrapper', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
       Nodes: {
         server: {
           hasId: true,
@@ -47,8 +46,10 @@ describe('BackupDialogWrapper', () => {
       keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
     };
 
-    noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
-    serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
+    pgBrowser.tree = new TreeFake(pgBrowser);
+
+    noDataNode = pgBrowser.tree.addNewNode('level1.1', undefined, [{id: 'level1'}]);
+    serverTreeNode = pgBrowser.tree.addNewNode('level2.1', {
       _type: 'server',
       _id: 10,
       label: 'some-tree-label',
@@ -57,7 +58,7 @@ describe('BackupDialogWrapper', () => {
       _type: 'database',
       _label: 'some-database-label',
     }, [{id: 'database-tree-node'}]);
-    pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
+    pgBrowser.tree.addChild(serverTreeNode, databaseTreeNode);
 
     jquerySpy = jasmine.createSpy('jquerySpy');
     backupNode = {
@@ -132,7 +133,7 @@ describe('BackupDialogWrapper', () => {
 
     context('selected tree node has no data', () => {
       beforeEach(() => {
-        pgBrowser.treeMenu.selectNode(noDataNode.domNode);
+        pgBrowser.tree.selectNode(noDataNode.domNode);
       });
 
       it('does not create a backform dialog', () => {
@@ -159,7 +160,7 @@ describe('BackupDialogWrapper', () => {
             label: 'some-tree-label',
           },
         };
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         pgBrowser.Nodes['server'].getTreeNodeHierarchy.and
           .returnValue(treeHierarchyInformation);
         dialogSpy = jasmine.createSpyObj('newView', ['render']);
@@ -238,7 +239,7 @@ describe('BackupDialogWrapper', () => {
           networkCalled = true;
           return [200, {}];
         });
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         pgBrowser.showHelp = jasmine.createSpy('showHelp');
 
         const event = {
@@ -278,7 +279,7 @@ describe('BackupDialogWrapper', () => {
           networkCalled = true;
           return [200, {}];
         });
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         pgBrowser.showHelp = jasmine.createSpy('showHelp');
 
         const event = {
@@ -337,7 +338,7 @@ describe('BackupDialogWrapper', () => {
 
       context('tree node has no data', () => {
         it('does not start the backup', () => {
-          pgBrowser.treeMenu.selectNode(noDataNode.domNode);
+          pgBrowser.tree.selectNode(noDataNode.domNode);
 
           let networkCalled = false;
           networkMock.onAny(/.*/).reply(() => {
@@ -365,7 +366,7 @@ describe('BackupDialogWrapper', () => {
         context('when dialog type is global', () => {
           let event;
           beforeEach(() => {
-            pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+            pgBrowser.tree.selectNode(serverTreeNode.domNode);
 
             backupDialogWrapper.view = {
               model: new FakeModel(),
@@ -465,7 +466,7 @@ describe('BackupDialogWrapper', () => {
               backform
             );
 
-            pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
+            pgBrowser.tree.selectNode(databaseTreeNode.domNode);
 
             backupDialogWrapper.view = {
               model: new FakeModel(),
diff --git a/web/regression/javascript/backup/global_server_backup_dialog_spec.js b/web/regression/javascript/backup/global_server_backup_dialog_spec.js
index 8497e7a71..b16dfa33e 100644
--- a/web/regression/javascript/backup/global_server_backup_dialog_spec.js
+++ b/web/regression/javascript/backup/global_server_backup_dialog_spec.js
@@ -26,7 +26,6 @@ describe('GlobalServerBackupDialog', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
       Nodes: {
         server: jasmine.createSpyObj('Node[server]', ['getTreeNodeHierarchy']),
       },
@@ -43,35 +42,36 @@ describe('GlobalServerBackupDialog', () => {
         default: 550,
       },
     };
+    pgBrowser.tree = new TreeFake(pgBrowser);
     pgBrowser.Nodes.server.hasId = true;
     jquerySpy = jasmine.createSpy('jquerySpy');
     backupModelSpy = jasmine.createSpy('backupModelSpy');
 
-    rootNode = pgBrowser.treeMenu.addNewNode('level1', {}, undefined, []);
-    serverTreeNode = pgBrowser.treeMenu.addNewNode('level1.1', {
+    rootNode = pgBrowser.tree.addNewNode('level1', {}, undefined, []);
+    serverTreeNode = pgBrowser.tree.addNewNode('level1.1', {
       _type: 'server',
       _id: 10,
       server_type: 'pg',
       version: 100000,
     }, undefined, ['level1']);
-    serverTreeNodeWrongPath = pgBrowser.treeMenu.addNewNode('level1.2', {
+    serverTreeNodeWrongPath = pgBrowser.tree.addNewNode('level1.2', {
       _type: 'server',
       _id: 11,
       server_type: 'pg',
       version: 90600,
     }, undefined, ['level1']);
-    ppasServerTreeNode = pgBrowser.treeMenu.addNewNode('level1.3', {
+    ppasServerTreeNode = pgBrowser.tree.addNewNode('level1.3', {
       _type: 'server',
       server_type: 'ppas',
       version: 130000,
     }, undefined, ['level1']);
-    ppasServerTreeNodeWrongPath = pgBrowser.treeMenu.addNewNode('level1.4', {
+    ppasServerTreeNodeWrongPath = pgBrowser.tree.addNewNode('level1.4', {
       _type: 'server',
       server_type: 'ppas',
       version: 90600,
     }, undefined, ['level1']);
-    pgBrowser.treeMenu.addNewNode('level3', {}, undefined, ['level1', 'level1.2', 'level1.3', 'level1.4']);
-    pgBrowser.treeMenu.addNewNode('level3.1', undefined, undefined, ['level1', 'level1.2', 'level3']);
+    pgBrowser.tree.addNewNode('level3', {}, undefined, ['level1', 'level1.2', 'level1.3', 'level1.4']);
+    pgBrowser.tree.addNewNode('level3.1', undefined, undefined, ['level1', 'level1.2', 'level3']);
   });
 
   describe('#draw', () => {
@@ -97,7 +97,7 @@ describe('GlobalServerBackupDialog', () => {
 
     context('there are no ancestors of the type server', () => {
       it('does not create a dialog', () => {
-        pgBrowser.treeMenu.selectNode([{id: 'level1'}]);
+        pgBrowser.tree.selectNode([{id: 'level1'}]);
         backupDialog.draw(null, null, null);
         expect(alertifySpy['BackupDialog_globals']).not.toHaveBeenCalled();
         expect(alertifySpy['BackupDialog_server']).not.toHaveBeenCalled();
diff --git a/web/regression/javascript/datagrid/get_panel_title_spec.js b/web/regression/javascript/datagrid/get_panel_title_spec.js
index 28d2a4609..ed295be11 100644
--- a/web/regression/javascript/datagrid/get_panel_title_spec.js
+++ b/web/regression/javascript/datagrid/get_panel_title_spec.js
@@ -9,7 +9,7 @@
 
 import {getPanelTitle} from '../../../pgadmin/tools/datagrid/static/js/datagrid_panel_title';
 import {TreeFake} from '../tree/tree_fake';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 import {pgBrowser} from 'pgadmin.browser.preferences';
 
 const context = describe;
@@ -28,7 +28,6 @@ describe('#getPanelTitle', () => {
   let tree;
   beforeEach(() => {
     pgBrowser.preferences_cache = dummy_cache;
-    tree = new TreeFake();
     pgBrowser.Nodes = {
       server: {
         hasId: true,
@@ -39,10 +38,11 @@ describe('#getPanelTitle', () => {
         _type: 'database',
       },
     };
-    pgBrowser.treeMenu = tree;
     pgBrowser.preferences = {
       'qt_tab_title_placeholder': '',
     };
+    tree = new TreeFake(pgBrowser);
+    pgBrowser.tree = tree;
   });
 
   context('selected node does not belong to a server', () => {
diff --git a/web/regression/javascript/datagrid/show_data_spec.js b/web/regression/javascript/datagrid/show_data_spec.js
index a5c5e9323..13cd96c56 100644
--- a/web/regression/javascript/datagrid/show_data_spec.js
+++ b/web/regression/javascript/datagrid/show_data_spec.js
@@ -9,7 +9,7 @@
 
 import {showDataGrid} from '../../../pgadmin/tools/datagrid/static/js/show_data';
 import {TreeFake} from '../tree/tree_fake';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 import {pgBrowser} from 'pgadmin.browser.preferences';
 
 const context = describe;
@@ -34,7 +34,6 @@ describe('#show_data', () => {
     datagrid = {
       launch_grid: jasmine.createSpy('launch_grid'),
     };
-    pgBrowser.treeMenu = new TreeFake();
     pgBrowser.Nodes = {
       server_group: {
         _type: 'server_group',
@@ -61,12 +60,13 @@ describe('#show_data', () => {
         hasId: true,
       },
     };
-    const parent = pgBrowser.treeMenu.addNewNode('parent', {_type: 'parent'}, []);
+    pgBrowser.tree = new TreeFake(pgBrowser);
+    const parent = pgBrowser.tree.addNewNode('parent', {_type: 'parent'}, []);
     const serverGroup1 = new TreeNode('server_group1', {
       _type: 'server_group',
       _id: 1,
     });
-    pgBrowser.treeMenu.addChild(parent, serverGroup1);
+    pgBrowser.tree.addChild(parent, serverGroup1);
 
     const server1 = new TreeNode('server1', {
       _type: 'server',
@@ -75,35 +75,35 @@ describe('#show_data', () => {
       _id: 2,
       user: {name: 'someuser'},
     }, ['parent', 'server_group1']);
-    pgBrowser.treeMenu.addChild(serverGroup1, server1);
+    pgBrowser.tree.addChild(serverGroup1, server1);
 
     const database1 = new TreeNode('database1', {
       _type: 'database',
       label: 'database1',
       _id: 3,
     }, ['parent', 'server_group1', 'server1']);
-    pgBrowser.treeMenu.addChild(server1, database1);
+    pgBrowser.tree.addChild(server1, database1);
 
     const schema1 = new TreeNode('schema1', {
       _type: 'schema',
       label: 'schema1',
       _id: 4,
     });
-    pgBrowser.treeMenu.addChild(database1, schema1);
+    pgBrowser.tree.addChild(database1, schema1);
 
     const view1 = new TreeNode('view1', {
       _type: 'view',
       label: 'view1',
       _id: 5,
     }, ['parent', 'server_group1', 'server1', 'database1']);
-    pgBrowser.treeMenu.addChild(database1, view1);
+    pgBrowser.tree.addChild(database1, view1);
 
     const catalog1 = new TreeNode('catalog1', {
       _type: 'catalog',
       label: 'catalog1',
       _id: 6,
     }, ['parent', 'server_group1', 'server1', 'database1']);
-    pgBrowser.treeMenu.addChild(database1, catalog1);
+    pgBrowser.tree.addChild(database1, catalog1);
   });
 
   context('cannot find the tree node', () => {
diff --git a/web/regression/javascript/datagrid/show_query_tool_spec.js b/web/regression/javascript/datagrid/show_query_tool_spec.js
index 33f6b00f8..8938bb00e 100644
--- a/web/regression/javascript/datagrid/show_query_tool_spec.js
+++ b/web/regression/javascript/datagrid/show_query_tool_spec.js
@@ -9,7 +9,7 @@
 
 import {TreeFake} from '../tree/tree_fake';
 import {showQueryTool} from '../../../pgadmin/tools/datagrid/static/js/show_query_tool';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 import {pgBrowser} from 'pgadmin.browser.preferences';
 
 const context = describe;
@@ -34,7 +34,6 @@ describe('#showQueryTool', () => {
     queryTool = {
       launch_grid: jasmine.createSpy('launch_grid'),
     };
-    pgBrowser.treeMenu = new TreeFake();
     pgBrowser.Nodes = {
       server_group: {
         _type: 'server_group',
@@ -49,13 +48,14 @@ describe('#showQueryTool', () => {
         hasId: true,
       },
     };
+    pgBrowser.tree = new TreeFake(pgBrowser);
 
-    const parent = pgBrowser.treeMenu.addNewNode('parent', {_type: 'parent'});
+    const parent = pgBrowser.tree.addNewNode('parent', {_type: 'parent'});
     const serverGroup1 =  new TreeNode('server_group1', {
       _type: 'server_group',
       _id: 1,
     }, ['parent']);
-    pgBrowser.treeMenu.addChild(parent, serverGroup1);
+    pgBrowser.tree.addChild(parent, serverGroup1);
 
     const server1 = new TreeNode('server1', {
       _type: 'server',
@@ -65,14 +65,14 @@ describe('#showQueryTool', () => {
       user: {name: 'someuser'},
       db: 'otherdblabel',
     });
-    pgBrowser.treeMenu.addChild(serverGroup1, server1);
+    pgBrowser.tree.addChild(serverGroup1, server1);
 
     const database1 = new  TreeNode('database1', {
       _type: 'database',
       label: 'database1',
       _id: 3,
     });
-    pgBrowser.treeMenu.addChild(server1, database1);
+    pgBrowser.tree.addChild(server1, database1);
   });
 
   context('cannot find the tree node', () => {
diff --git a/web/regression/javascript/misc/statistics/statistics_spec.js b/web/regression/javascript/misc/statistics/statistics_spec.js
index 4fe2b1af3..79f5af52f 100644
--- a/web/regression/javascript/misc/statistics/statistics_spec.js
+++ b/web/regression/javascript/misc/statistics/statistics_spec.js
@@ -15,7 +15,7 @@ describe('#nodeHasStatistics', () => {
       const node = {
         hasStatistics: true,
       };
-      expect(nodeHasStatistics(node, {})).toEqual(true);
+      expect(nodeHasStatistics({}, node, {})).toEqual(true);
     });
   });
 
@@ -24,12 +24,16 @@ describe('#nodeHasStatistics', () => {
       it('returns true', () => {
         const node = {
           hasStatistics: () => true,
-          getTreeNodeHierarchy: jasmine.createSpy(),
+        };
+        const pgBrowser = {
+          tree: {
+            getTreeNodeHierarchy: jasmine.createSpy(),
+          }
         };
         const item = {};
 
-        expect(nodeHasStatistics(node, item)).toEqual(true);
-        expect(node.getTreeNodeHierarchy).toHaveBeenCalledWith(item);
+        expect(nodeHasStatistics(pgBrowser, node, item)).toEqual(true);
+        expect(pgBrowser.tree.getTreeNodeHierarchy).toHaveBeenCalledWith(item);
       });
     });
   });
diff --git a/web/regression/javascript/nodes/schema/child_menu_spec.js b/web/regression/javascript/nodes/schema/child_menu_spec.js
index 61acb01c3..23952f241 100644
--- a/web/regression/javascript/nodes/schema/child_menu_spec.js
+++ b/web/regression/javascript/nodes/schema/child_menu_spec.js
@@ -10,13 +10,14 @@
 import {
   isTreeItemOfChildOfSchema, childCreateMenuEnabled,
 } from 'pgadmin.schema.dir/schema_child_tree_node';
-
-import * as pgBrowser from 'pgbrowser/browser';
+import pgAdmin from 'sources/pgadmin';
 import {TreeFake} from '../../tree/tree_fake';
 
+
 describe('#childCreateMenuEnabled', () => {
-  let data;
-  let tree;
+  let data,
+    tree,
+    pgBrowser = pgAdmin.Browser;
 
   describe(' - when data is not null', () => {
     beforeEach(() => {
@@ -47,8 +48,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
           it(' it is true', () => {
             expect(childCreateMenuEnabled(
@@ -72,8 +73,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
 
           it(' it is true', () => {
@@ -101,8 +102,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
 
           it(' it is true', () => {
@@ -122,8 +123,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
           it(' it is false', () => {
             expect(
@@ -146,8 +147,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
 
           it(' it is false', () => {
@@ -175,8 +176,8 @@ describe('#childCreateMenuEnabled', () => {
               }],
             };
 
-            tree = TreeFake.build(hierarchy);
-            pgBrowser.treeMenu = tree;
+            tree = TreeFake.build(hierarchy, pgBrowser);
+            pgBrowser.tree = tree;
           });
 
           it(' it is false', () => {
@@ -191,7 +192,9 @@ describe('#childCreateMenuEnabled', () => {
 });
 
 describe('#childDropMenuEnabled', () => {
-  let tree;
+  let tree,
+    pgBrowser = pgAdmin.Browser;
+
 
   describe(' - the child node under schema node ', () => {
     beforeEach(() => {
@@ -211,8 +214,8 @@ describe('#childDropMenuEnabled', () => {
         }],
       };
 
-      tree = TreeFake.build(hierarchy);
-      pgBrowser.treeMenu = tree;
+      tree = TreeFake.build(hierarchy, pgBrowser);
+      pgBrowser.tree = tree;
     });
 
     it(' it is true', () => {
@@ -240,8 +243,8 @@ describe('#childDropMenuEnabled', () => {
         }],
       };
 
-      tree = TreeFake.build(hierarchy);
-      pgBrowser.treeMenu = tree;
+      tree = TreeFake.build(hierarchy, pgBrowser);
+      pgBrowser.tree = tree;
     });
 
     it(' it is false', () => {
diff --git a/web/regression/javascript/restore/restore_dialog_spec.js b/web/regression/javascript/restore/restore_dialog_spec.js
index c77f3775a..a62dc82fa 100644
--- a/web/regression/javascript/restore/restore_dialog_spec.js
+++ b/web/regression/javascript/restore/restore_dialog_spec.js
@@ -22,7 +22,7 @@ describe('RestoreDialog', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
+      tree: new TreeFake(),
       Nodes: {
         server: jasmine.createSpyObj('Node[server]', ['getTreeNodeHierarchy']),
         database: jasmine.createSpyObj('Node[database]', ['getTreeNodeHierarchy']),
@@ -113,7 +113,7 @@ describe('RestoreDialog', () => {
       ],
     };
 
-    pgBrowser.treeMenu = TreeFake.build(hierarchy);
+    pgBrowser.tree = TreeFake.build(hierarchy, pgBrowser);
   });
 
   describe('#draw', () => {
@@ -138,7 +138,7 @@ describe('RestoreDialog', () => {
 
     context('there are no ancestors of the type server', () => {
       it('does not create a dialog', () => {
-        pgBrowser.treeMenu.selectNode([{id: 'root'}]);
+        pgBrowser.tree.selectNode([{id: 'root'}]);
         restoreDialog.draw(null, null, null);
         expect(alertifySpy['pg_restore']).not.toHaveBeenCalled();
       });
diff --git a/web/regression/javascript/restore/restore_dialog_wrapper_spec.js b/web/regression/javascript/restore/restore_dialog_wrapper_spec.js
index a328bb5be..cde9b145c 100644
--- a/web/regression/javascript/restore/restore_dialog_wrapper_spec.js
+++ b/web/regression/javascript/restore/restore_dialog_wrapper_spec.js
@@ -11,7 +11,7 @@ import {RestoreDialogWrapper} from '../../../pgadmin/tools/restore/static/js/res
 import MockAdapter from 'axios-mock-adapter';
 import axios from 'axios/index';
 import {FakeModel} from '../fake_model';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 
 let context = describe;
 
@@ -32,7 +32,6 @@ describe('RestoreDialogWrapper', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
       Nodes: {
         server: {
           hasId: true,
@@ -41,9 +40,10 @@ describe('RestoreDialogWrapper', () => {
       },
       keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
     };
+    pgBrowser.tree = new TreeFake(pgBrowser);
 
-    noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
-    serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
+    noDataNode = pgBrowser.tree.addNewNode('level1.1', undefined, [{id: 'level1'}]);
+    serverTreeNode = pgBrowser.tree.addNewNode('level2.1', {
       _type: 'server',
       _id: 10,
       label: 'some-tree-label',
@@ -123,7 +123,7 @@ describe('RestoreDialogWrapper', () => {
 
     context('selected tree node has no data', () => {
       beforeEach(() => {
-        pgBrowser.treeMenu.selectNode(noDataNode.domNode);
+        pgBrowser.tree.selectNode(noDataNode.domNode);
       });
 
       it('does not create a backform dialog', () => {
@@ -149,7 +149,7 @@ describe('RestoreDialogWrapper', () => {
             label: 'some-tree-label',
           },
         };
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         pgBrowser.Nodes['server'].getTreeNodeHierarchy.and
           .returnValue(treeHierarchyInformation);
         dialogSpy = jasmine.createSpyObj('newView', ['render']);
@@ -226,7 +226,7 @@ describe('RestoreDialogWrapper', () => {
       let networkCalled;
       beforeEach(() => {
         networkCalled = false;
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         networkMock.onAny(/.+/).reply(() => {
           networkCalled = true;
           return [200, {}];
@@ -267,7 +267,7 @@ describe('RestoreDialogWrapper', () => {
       let networkCalled;
       beforeEach(() => {
         networkCalled = false;
-        pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
+        pgBrowser.tree.selectNode(serverTreeNode.domNode);
         networkMock.onAny(/.+/).reply(() => {
           networkCalled = true;
           return [200, {}];
@@ -350,7 +350,7 @@ describe('RestoreDialogWrapper', () => {
               },
             },
           };
-          pgBrowser.treeMenu.selectNode(noDataNode.domNode);
+          pgBrowser.tree.selectNode(noDataNode.domNode);
         });
 
         it('does not start the restore', () => {
@@ -364,12 +364,12 @@ describe('RestoreDialogWrapper', () => {
         let databaseTreeNode;
 
         beforeEach(() => {
-          databaseTreeNode = pgBrowser.treeMenu.addNewNode('level3.1', {
+          databaseTreeNode = pgBrowser.tree.addNewNode('level3.1', {
             _type: 'database',
             _id: 10,
             _label: 'some-database-label',
           }, [{id: 'level3.1'}]);
-          pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
+          pgBrowser.tree.addChild(serverTreeNode, databaseTreeNode);
           pgBrowser.Nodes.database = {
             hasId: true,
             _label: 'some-database-label',
@@ -379,7 +379,7 @@ describe('RestoreDialogWrapper', () => {
           restoreDialogWrapper.view = {
             model: fakeModel,
           };
-          pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
+          pgBrowser.tree.selectNode(databaseTreeNode.domNode);
           pgBrowser.Events = jasmine.createSpyObj('pgBrowserEventsSpy', ['trigger']);
           event = {
             button: {
diff --git a/web/regression/javascript/search_objects/search_objects_dialog_spec.js b/web/regression/javascript/search_objects/search_objects_dialog_spec.js
index 465d4152c..eec5ddb0a 100644
--- a/web/regression/javascript/search_objects/search_objects_dialog_spec.js
+++ b/web/regression/javascript/search_objects/search_objects_dialog_spec.js
@@ -32,7 +32,6 @@ describe('SearchObjectsDialog', () => {
 
   beforeEach(() => {
     pgBrowser.preferences_cache = dummy_cache;
-    pgBrowser.treeMenu  = new TreeFake();
     pgBrowser.Nodes  = {
       server: {
         hasId: true,
@@ -50,7 +49,7 @@ describe('SearchObjectsDialog', () => {
         getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
       },
     };
-
+    pgBrowser.tree  = new TreeFake(pgBrowser);
     pgBrowser.stdW = {
       sm: 500,
       md: 700,
@@ -108,7 +107,7 @@ describe('SearchObjectsDialog', () => {
       ],
     };
 
-    pgBrowser.treeMenu = TreeFake.build(hierarchy);
+    pgBrowser.tree = TreeFake.build(hierarchy, pgBrowser);
   });
 
   describe('#draw', () => {
@@ -137,7 +136,7 @@ describe('SearchObjectsDialog', () => {
 
     context('there are no ancestors of the type database', () => {
       it('does not create a dialog', () => {
-        pgBrowser.treeMenu.selectNode([{id: 'serverTreeNode'}]);
+        pgBrowser.tree.selectNode([{id: 'serverTreeNode'}]);
         soDialog.draw(null, null, null);
         expect(alertifySpy['search_objects']).not.toHaveBeenCalled();
       });
diff --git a/web/regression/javascript/search_objects/search_objects_dialog_wrapper_spec.js b/web/regression/javascript/search_objects/search_objects_dialog_wrapper_spec.js
index 9681b4671..ae0e7be35 100644
--- a/web/regression/javascript/search_objects/search_objects_dialog_wrapper_spec.js
+++ b/web/regression/javascript/search_objects/search_objects_dialog_wrapper_spec.js
@@ -11,7 +11,7 @@ import {TreeFake} from '../tree/tree_fake';
 import SearchObjectsDialogWrapper from 'tools/search_objects/static/js/search_objects_dialog_wrapper';
 import axios from 'axios/index';
 import MockAdapter from 'axios-mock-adapter';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 
 let context = describe;
 
@@ -32,7 +32,6 @@ describe('SearchObjectsDialogWrapper', () => {
 
   beforeEach(() => {
     pgBrowser = {
-      treeMenu: new TreeFake(),
       Nodes: {
         server: {
           hasId: true,
@@ -74,8 +73,9 @@ describe('SearchObjectsDialogWrapper', () => {
       },
       keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
     };
-    noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
-    serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
+    pgBrowser.tree =  new TreeFake(pgBrowser),
+    noDataNode = pgBrowser.tree.addNewNode('level1.1', undefined, [{id: 'level1'}]);
+    serverTreeNode = pgBrowser.tree.addNewNode('level2.1', {
       _type: 'server',
       _id: 10,
       label: 'some-tree-label',
@@ -85,7 +85,7 @@ describe('SearchObjectsDialogWrapper', () => {
       _id: 123,
       _label: 'some-database-label',
     }, [{id: 'database-tree-node'}]);
-    pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
+    pgBrowser.tree.addChild(serverTreeNode, databaseTreeNode);
 
     jquerySpy = jasmine.createSpy('jquerySpy');
     soNode = {
@@ -153,7 +153,7 @@ describe('SearchObjectsDialogWrapper', () => {
 
     context('selected tree node has no data', () => {
       beforeEach(() => {
-        pgBrowser.treeMenu.selectNode(noDataNode.domNode);
+        pgBrowser.tree.selectNode(noDataNode.domNode);
       });
 
       it('does not prepare the dialog', () => {
@@ -168,7 +168,7 @@ describe('SearchObjectsDialogWrapper', () => {
       let networkMock;
 
       beforeEach(() => {
-        pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
+        pgBrowser.tree.selectNode(databaseTreeNode.domNode);
         soDialogWrapper.grid = jasmine.createSpyObj('grid', ['destroy']);
         spyOn(soDialogWrapper, 'showMessage');
         gridDestroySpy = spyOn(soDialogWrapper.grid, 'destroy');
@@ -503,9 +503,9 @@ describe('SearchObjectsDialogWrapper', () => {
         };
 
         soDialogWrapper.treeInfo = {
-          'server_group': {'id': 'server_group/1', '_id': 1},
-          'server': {'id': 'server/3', '_id': 3},
-          'database': {'id': 'database/18456', '_id': 18456},
+          'server_group': {'id': 'server_group_1', '_id': 1},
+          'server': {'id': 'server_3', '_id': 3},
+          'database': {'id': 'database_18456', '_id': 18456},
         };
       });
       it('regular schema', ()=>{
@@ -515,7 +515,7 @@ describe('SearchObjectsDialogWrapper', () => {
         let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
         expect(retVal).toEqual([
           'Schemas/test_db/Tables/sampletab',
-          ['server_group/1','server/3','coll-database/3','database/18456','coll-schema/18456','schema/2200','coll-table/2200','table/2604'],
+          ['server_group_1','server_3','coll-database_3','database_18456','coll-schema_18456','schema_2200','coll-table_2200','table_2604'],
         ]);
       });
 
@@ -527,7 +527,7 @@ describe('SearchObjectsDialogWrapper', () => {
           let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
           expect(retVal).toEqual([
             'Catalogs/PostgreSQL Catalog (pg_catalog)/Tables/pg_class',
-            ['server_group/1','server/3','coll-database/3','database/18456','coll-catalog/18456','catalog/11','coll-table/11','table/2604'],
+            ['server_group_1','server_3','coll-database_3','database_18456','coll-catalog_18456','catalog_11','coll-table_11','table_2604'],
           ]);
         });
 
@@ -538,7 +538,7 @@ describe('SearchObjectsDialogWrapper', () => {
           let retVal = soDialogWrapper.translateSearchObjectsPath(path, catalog_level);
           expect(retVal).toEqual([
             'Catalogs/ANSI (information_schema)/Catalog Objects/attributes',
-            ['server_group/1','server/3','coll-database/3','database/18456','coll-catalog/18456','catalog/11','coll-catalog_object/11','catalog_object/2604'],
+            ['server_group_1','server_3','coll-database_3','database_18456','coll-catalog_18456','catalog_11','coll-catalog_object_11','catalog_object_2604'],
           ]);
         });
       });
diff --git a/web/regression/javascript/table/enable_disable_triggers_spec.js b/web/regression/javascript/table/enable_disable_triggers_spec.js
index 8b4694ee5..ff8906ba8 100644
--- a/web/regression/javascript/table/enable_disable_triggers_spec.js
+++ b/web/regression/javascript/table/enable_disable_triggers_spec.js
@@ -14,7 +14,7 @@ import {
   disableTriggers,
 } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/enable_disable_triggers';
 import {TreeFake} from '../tree/tree_fake';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 
 describe('#enableTriggers', () => {
   let networkMock;
@@ -24,6 +24,13 @@ describe('#enableTriggers', () => {
   beforeEach(() => {
     networkMock = new MockAdapter(axios);
     tree = new TreeFake();
+
+    spyOn(tree, 'unload').and.callFake(function() {
+      return new Promise((resolve)=>{
+        resolve('Success!');
+      });
+    });
+
     const server1 = tree.addNewNode('server1', {_id: 1}, ['<li>server1</li>']);
     const database1 = tree.addNewNode('database1', {_type: 'database'}, ['<li>database1</li>']);
     tree.addChild(server1, database1);
@@ -100,7 +107,7 @@ describe('#enableTriggers', () => {
           setTimeout(() => {
             expect(tree.selected()).toEqual(['<li>table1</li>']);
             done();
-          }, 20);
+          }, 30);
         });
 
         it('call backend with the correct parameters', (done) => {
@@ -171,6 +178,12 @@ describe('#disableTriggers', () => {
     alertify = jasmine.createSpyObj('alertify', ['success', 'error']);
     generateUrlSpy = jasmine.createSpy('generateUrl');
     generateUrlSpy.and.returnValue('/some/place');
+    spyOn(tree, 'unload').and.callFake(function() {
+      return new Promise((resolve)=>{
+        resolve('Success!');
+      });
+    });
+
   });
 
   describe('no node is selected', () => {
diff --git a/web/regression/javascript/tree/pgadmin_tree_node_spec.js b/web/regression/javascript/tree/pgadmin_tree_node_spec.js
deleted file mode 100644
index 967f07f09..000000000
--- a/web/regression/javascript/tree/pgadmin_tree_node_spec.js
+++ /dev/null
@@ -1,363 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2021, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////////////////
-
-import {
-  getTreeNodeHierarchyFromElement,
-  getTreeNodeHierarchyFromIdentifier,
-} from '../../../pgadmin/static/js/tree/pgadmin_tree_node';
-import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
-import {TreeFake} from './tree_fake';
-
-const context = describe;
-
-describe('tree#node#getTreeNodeHierarchy', () => {
-  let browser;
-  let newTree;
-  beforeEach(() => {
-    newTree = new TreeFake();
-    browser = {
-      Nodes: {
-        'special one': {hasId: true},
-        'child special': {hasId: true},
-        'other type': {hasId: true},
-        'table': {hasId: true},
-        'partition': {hasId: true},
-        'no id': {hasId: false},
-      },
-    };
-    browser.treeMenu = newTree;
-  });
-
-  context('getTreeNodeHierarchy is called with aciTreeNode object', () => {
-    describe('When the current node is root element', () => {
-      beforeEach(() => {
-        newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'special one',
-        });
-      });
-
-      it('returns a object with the element type passed data and priority == 0', () => {
-        const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'root'}]);
-        expect(result).toEqual({
-          'special one': {
-            'some key': 'some value',
-            '_type': 'special one',
-            'priority': 0,
-          },
-        });
-      });
-    });
-
-    describe('When the current node is not of a known type', () => {
-      beforeEach(() => {
-        newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'do not exist',
-        }, []);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromIdentifier.bind(browser)('root');
-        expect(result).toEqual({});
-      });
-    });
-
-    describe('When the current node type has no id', () => {
-      beforeEach(() => {
-        newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'no id',
-        }, []);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromIdentifier.bind(browser)('root');
-        expect(result).toEqual({});
-      });
-    });
-
-    describe('When the current node is at the second level', () => {
-      beforeEach(() => {
-        const root = newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'special one',
-        });
-        const firstChild = new TreeNode('first child', {
-          'some key': 'some other value',
-          '_type': 'child special',
-        }, ['root']);
-        newTree.addChild(root, firstChild);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'first child'}]);
-        expect(result).toEqual({
-          'child special': {
-            'some key': 'some other value',
-            '_type': 'child special',
-            'priority': 0,
-          },
-          'special one': {
-            'some key': 'some value',
-            '_type': 'special one',
-            'priority': -1,
-          },
-        });
-      });
-    });
-
-    context('When tree as "special type"', () => {
-      context('When "special type" have "other type"', () => {
-        context('When "other type" have "special type"', () => {
-          describe('When retrieving lead node', () => {
-            it('does not override previous node type data', () => {
-              const rootNode = newTree.addNewNode('root', {
-                'some key': 'some value',
-                '_type': 'special one',
-              }, []);
-
-              const level1 = new TreeNode('level 1', {
-                'some key': 'some value',
-                '_type': 'other type',
-              });
-              newTree.addChild(rootNode, level1);
-
-              newTree.addChild(level1, new TreeNode('level 2', {
-                'some key': 'expected value',
-                '_type': 'special one',
-                'some other key': 'some other value',
-              }));
-
-              const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'level 2'}]);
-              expect(result).toEqual({
-                'special one': {
-                  'some key': 'expected value',
-                  '_type': 'special one',
-                  'some other key': 'some other value',
-                  'priority': 0,
-                },
-                'other type': {
-                  'some key': 'some value',
-                  '_type': 'other type',
-                  'priority': -1,
-                },
-              });
-            });
-          });
-        });
-      });
-    });
-
-    context('When tree has table', () => {
-      context('when table has partition', () => {
-        it('returns table with partition parameters', () => {
-          const root = newTree.addNewNode('root', {
-            'some key': 'some value',
-            '_type': 'special one',
-          }, []);
-          const level1 = new TreeNode('level 1', {
-            'some key': 'some value',
-            '_type': 'table',
-          });
-          newTree.addChild(root, level1);
-          newTree.addChild(level1, new TreeNode('level 2', {
-            'some key': 'expected value',
-            '_type': 'partition',
-            'some other key': 'some other value',
-          }));
-
-          const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id:'level 2'}]);
-          expect(result).toEqual({
-            'special one': {
-              'some key': 'some value',
-              '_type': 'special one',
-              'priority': -2,
-            },
-            'table': {
-              'some key': 'some value',
-              '_type': 'table',
-              'priority': -1,
-            },
-            'partition': {
-              'some key': 'expected value',
-              'some other key': 'some other value',
-              '_type': 'partition',
-              'priority': 0,
-            },
-          });
-        });
-      });
-    });
-  });
-
-  context('getTreeNodeHierarchy is called with TreeNode object', () => {
-    let treeNode;
-    describe('When the current node is root element', () => {
-      beforeEach(() => {
-        treeNode = newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'special one',
-        }, []);
-      });
-
-      it('returns a object with the element type passed data and priority == 0', () => {
-        const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-        expect(result).toEqual({
-          'special one': {
-            'some key': 'some value',
-            '_type': 'special one',
-            'priority': 0,
-          },
-        });
-      });
-    });
-
-    describe('When the current node is not of a known type', () => {
-      beforeEach(() => {
-        treeNode = newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'do not exist',
-        }, []);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-        expect(result).toEqual({});
-      });
-    });
-
-    describe('When the current node type has no id', () => {
-      beforeEach(() => {
-        treeNode = newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'no id',
-        }, []);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-        expect(result).toEqual({});
-      });
-    });
-
-    describe('When the current node is at the second level', () => {
-      beforeEach(() => {
-        const root = newTree.addNewNode('root', {
-          'some key': 'some value',
-          '_type': 'special one',
-        }, []);
-        treeNode = new TreeNode('first child', {
-          'some key': 'some other value',
-          '_type': 'child special',
-        });
-        newTree.addChild(root, treeNode);
-      });
-
-      it('returns a empty object', () => {
-        const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-        expect(result).toEqual({
-          'child special': {
-            'some key': 'some other value',
-            '_type': 'child special',
-            'priority': 0,
-          },
-          'special one': {
-            'some key': 'some value',
-            '_type': 'special one',
-            'priority': -1,
-          },
-        });
-      });
-    });
-
-    context('When tree as "special type"', () => {
-      context('When "special type" have "other type"', () => {
-        context('When "other type" have "special type"', () => {
-          describe('When retrieving lead node', () => {
-            it('does not override previous node type data', () => {
-              const root = newTree.addNewNode('root', {
-                'some key': 'some value',
-                '_type': 'special one',
-              }, []);
-              const level1 = new TreeNode('level 1', {
-                'some key': 'some value',
-                '_type': 'other type',
-              });
-              newTree.addChild(root, level1);
-              treeNode = new TreeNode('level 2', {
-                'some key': 'expected value',
-                '_type': 'special one',
-                'some other key': 'some other value',
-              });
-              newTree.addChild(level1, treeNode);
-
-              const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-              expect(result).toEqual({
-                'special one': {
-                  'some key': 'expected value',
-                  '_type': 'special one',
-                  'some other key': 'some other value',
-                  'priority': 0,
-                },
-                'other type': {
-                  'some key': 'some value',
-                  '_type': 'other type',
-                  'priority': -1,
-                },
-              });
-            });
-          });
-        });
-      });
-    });
-
-    context('When tree has table', () => {
-      context('when table has partition', () => {
-        it('returns table with partition parameters', () => {
-          const root = newTree.addNewNode('root', {
-            'some key': 'some value',
-            '_type': 'special one',
-          });
-          const level1 = newTree.addNewNode('level 1', {
-            'some key': 'some value',
-            '_type': 'table',
-          });
-          newTree.addChild(root, level1);
-          treeNode = new TreeNode('level 2', {
-            'some key': 'expected value',
-            '_type': 'partition',
-            'some other key': 'some other value',
-          });
-          newTree.addChild(level1, treeNode);
-
-          const result = getTreeNodeHierarchyFromElement(browser, treeNode);
-          expect(result).toEqual({
-            'special one': {
-              'some key': 'some value',
-              '_type': 'special one',
-              'priority': -2,
-            },
-            'table': {
-              'some key': 'some value',
-              '_type': 'table',
-              'priority': -1,
-            },
-            'partition': {
-              'some key': 'expected value',
-              'some other key': 'some other value',
-              '_type': 'partition',
-              'priority': 0,
-            },
-          });
-        });
-      });
-    });
-  });
-});
diff --git a/web/regression/javascript/tree/pgadmin_tree_state_save_spec.js b/web/regression/javascript/tree/pgadmin_tree_state_save_spec.js
index 6e902768b..e89ef91d1 100644
--- a/web/regression/javascript/tree/pgadmin_tree_state_save_spec.js
+++ b/web/regression/javascript/tree/pgadmin_tree_state_save_spec.js
@@ -107,7 +107,10 @@ describe('#browserTreeState', () => {
         };},
       },
     };
-    pgBrowser.tree = jasmine.createSpyObj('tree', ['itemData', 'pathId', 'hasParent', 'isOpen', 'isClosed', 'selected']);
+    pgBrowser.tree = jasmine.createSpyObj('tree', ['itemData', 'pathId', 'hasParent', 'isOpen', 'isClosed', 'selected', 'parent']);
+    pgBrowser.tree.getTreeNodeHierarchy = function (item) {
+      return pgBrowser.Nodes[item._type].getTreeNodeHierarchy();
+    };
   });
 
   describe('When node is opened tree state is getting updated', () => {
diff --git a/web/regression/javascript/tree/tree_fake.js b/web/regression/javascript/tree/tree_fake.js
index fe647504f..337594f52 100644
--- a/web/regression/javascript/tree/tree_fake.js
+++ b/web/regression/javascript/tree/tree_fake.js
@@ -8,10 +8,11 @@
 //////////////////////////////////////////////////////////////
 
 import {Tree} from '../../../pgadmin/static/js/tree/tree';
+import {ManageTreeNodes, TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
 
 export class TreeFake extends Tree {
-  static build(structure) {
-    let tree = new TreeFake();
+  static build(structure, pgBrowser) {
+    let tree = new TreeFake(pgBrowser);
     let rootNode = tree.rootNode;
 
     if (structure.children !== undefined) {
@@ -27,7 +28,10 @@ export class TreeFake extends Tree {
     let id = newNode.id;
     let data = newNode.data ? newNode.data : {};
     let domNode = newNode.domNode ? newNode.domNode : [{id: id}];
-    tree.addNewNode(id, data, domNode, tree.translateTreeNodeIdFromACITree([parent]));
+
+    let parentPath = tree.translateTreeNodeIdFromReactTree([parent]);
+
+    tree.addNewNode(id, data, domNode, parentPath);
 
     if (newNode.children !== undefined) {
       newNode.children.forEach((child) => {
@@ -36,50 +40,96 @@ export class TreeFake extends Tree {
     }
   }
 
-  constructor() {
-    super();
-    this.aciTreeToOurTreeTranslator = {};
-    this.aciTreeApi = jasmine.createSpyObj(
-      'ACITreeApi', ['setInode', 'unload', 'deselect', 'select']);
-    this.aciTreeApi.unload.and.callFake(function(domNode, config) {
+  constructor(pgBrowser) {
+    let manageTree = new ManageTreeNodes();
+    let tree = jasmine.createSpyObj(
+      'tree', ['unload', 'onTreeEvents',
+        'getActiveFile', 'setActiveFile',
+        'deSelectActiveFile', 'closeDirectory']);
+    tree.unload.and.callFake(function(domNode, config) {
       config.success();
     });
+
+    super(tree, manageTree, pgBrowser);
+    this.aciTreeToOurTreeTranslator = {};
+
   }
 
   addNewNode(id, data, domNode, path) {
-    this.aciTreeToOurTreeTranslator[id] = [id];
+    this.aciTreeToOurTreeTranslator[id] = id;
     if (path !== null && path !== undefined) {
-      this.aciTreeToOurTreeTranslator[id] = path.concat(id);
+      if (typeof(path) === 'object') path = path.join('/');
+      this.aciTreeToOurTreeTranslator[id] = path != '' ? path + '/' + id : id;
+      if (path.indexOf('/browser/') != 0) path = path != '' ? '/browser/' + path : undefined;
     }
     return super.addNewNode(id, data, domNode, path);
   }
 
   addChild(parent, child) {
     child.setParent(parent);
-    this.aciTreeToOurTreeTranslator[child.id] = this.aciTreeToOurTreeTranslator[parent.id].concat(child.id);
+    this.aciTreeToOurTreeTranslator[child.id] = this.aciTreeToOurTreeTranslator[parent.id] + '/' + child.id;
     parent.children.push(child);
   }
 
   hasParent(aciTreeNode) {
-    return this.translateTreeNodeIdFromACITree(aciTreeNode).length > 1;
+    let parents = this.translateTreeNodeIdFromReactTree(aciTreeNode).split('/');
+    return parents.length > 1;
   }
 
   parent(aciTreeNode) {
     if (this.hasParent(aciTreeNode)) {
-      let path = this.translateTreeNodeIdFromACITree(aciTreeNode);
-      return [{id: this.findNode(path).parent().id}];
+      let path = this.translateTreeNodeIdFromReactTree(aciTreeNode);
+      return [{id: this.findNode('/browser/' + path).parent().id}];
     }
 
     return null;
   }
 
-  translateTreeNodeIdFromACITree(aciTreeNode) {
+  translateTreeNodeIdFromReactTree(aciTreeNode) {
     if (aciTreeNode === undefined || aciTreeNode[0] === undefined) {
       return null;
     }
     return this.aciTreeToOurTreeTranslator[aciTreeNode[0].id];
   }
 
+  findNodeByDomElement(domElement) {
+    const path = this.translateTreeNodeIdFromReactTree(domElement);
+
+    if(!path || !path[0]) {
+      return undefined;
+    }
+
+    return this.findNode('/browser/' + path);
+
+  }
+
+  getTreeNodeHierarchy(identifier) {
+    let idx = 0;
+    let node_cnt = 0;
+    let result = {};
+    let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier :
+      (identifier.path ? this.findNode(identifier.path) : this.findNodeByDomElement(identifier));
+
+    if (item == undefined || item == null) return null;
+
+    do {
+      const currentNodeData = item.getData();
+      if (currentNodeData._type in this.Nodes && this.Nodes[currentNodeData._type].hasId) {
+        const nodeType = mapType(currentNodeData._type, node_cnt);
+        if (result[nodeType] === undefined) {
+          result[nodeType] = _.extend({}, currentNodeData, {
+            'priority': idx,
+          });
+          idx -= 1;
+        }
+      }
+      node_cnt += 1;
+      item = item.hasParent() ? item.parent() : null;
+    } while (item);
+
+    return result;
+  }
+
   itemData(aciTreeNode) {
     let node = this.findNodeByDomElement(aciTreeNode);
     if (node === undefined || node === null) {
@@ -96,3 +146,7 @@ export class TreeFake extends Tree {
     this.selectedNode = selectedNode;
   }
 }
+
+function mapType(type, idx) {
+  return (type === 'partition' && idx > 0) ? 'table' : type;
+}
diff --git a/web/regression/javascript/tree/tree_spec.js b/web/regression/javascript/tree/tree_spec.js
index 239a3a87d..2f80f6304 100644
--- a/web/regression/javascript/tree/tree_spec.js
+++ b/web/regression/javascript/tree/tree_spec.js
@@ -1,13 +1,14 @@
 //////////////////////////////////////////////////////////////////////////
 //
-// pgAdmin 4 - PostgreSQL Tools
+// pgAdmin 4  PostgreSQL Tools
 //
-// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// Copyright (C) 2013  2021, The pgAdmin Development Team
 // This software is released under the PostgreSQL Licence
 //
 //////////////////////////////////////////////////////////////////////////
 
-import {Tree, TreeNode} from '../../../pgadmin/static/js/tree/tree';
+import {Tree} from '../../../pgadmin/static/js/tree/tree';
+import {TreeNode, ManageTreeNodes} from '../../../pgadmin/static/js/tree/tree_nodes';
 import {TreeFake} from './tree_fake';
 
 const context = describe;
@@ -15,28 +16,34 @@ const context = describe;
 const treeTests = (treeClass, setDefaultCallBack) => {
   let tree;
   beforeEach(() => {
-    tree = new treeClass();
+    let manageTree = new ManageTreeNodes();
+    let reactTree = jasmine.createSpyObj(
+      'tree', ['onTreeEvents', 'getActiveFile']);
+    tree = new treeClass(reactTree, manageTree);
   });
 
   describe('#addNewNode', () => {
+    beforeEach(() => {
+      tree.rootNode = new TreeNode(undefined, {});
+    });
     describe('when add a new root element', () => {
-      context('using [] as the parent', () => {
+      context('using undefined as the parent', () => {
         beforeEach(() => {
-          tree.addNewNode('some new node', {data: 'interesting'}, undefined, []);
+          tree.addNewNode('some new node', {data: 'interesting'}, undefined, undefined);
         });
 
         it('can be retrieved', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.data).toEqual({data: 'interesting'});
         });
 
         it('return false for #hasParent()', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.hasParent()).toEqual(false);
         });
 
         it('return null for #parent()', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.parent()).toBeNull();
         });
       });
@@ -47,38 +54,17 @@ const treeTests = (treeClass, setDefaultCallBack) => {
         });
 
         it('can be retrieved', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.data).toEqual({data: 'interesting'});
         });
 
         it('return false for #hasParent()', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.hasParent()).toEqual(false);
         });
 
         it('return null for #parent()', () => {
-          const node = tree.findNode(['some new node']);
-          expect(node.parent()).toBeNull();
-        });
-      });
-
-      context('using undefined as the parent', () => {
-        beforeEach(() => {
-          tree.addNewNode('some new node', {data: 'interesting'});
-        });
-
-        it('can be retrieved', () => {
-          const node = tree.findNode(['some new node']);
-          expect(node.data).toEqual({data: 'interesting'});
-        });
-
-        it('return false for #hasParent()', () => {
-          const node = tree.findNode(['some new node']);
-          expect(node.hasParent()).toEqual(false);
-        });
-
-        it('return null for #parent()', () => {
-          const node = tree.findNode(['some new node']);
+          const node = tree.findNode('/browser/some new node');
           expect(node.parent()).toBeNull();
         });
       });
@@ -87,101 +73,46 @@ const treeTests = (treeClass, setDefaultCallBack) => {
     describe('when add a new element as a child', () => {
       let parentNode;
       beforeEach(() => {
-        parentNode = tree.addNewNode('parent node', {data: 'parent data'}, undefined, []);
-        tree.addNewNode('some new node', {data: 'interesting'}, undefined, ['parent' +
-        ' node']);
+        parentNode = tree.addNewNode('parent node', {data: 'parent data'}, undefined, undefined);
+        tree.addNewNode('some new node', {data: 'interesting'}, undefined, '/browser/parent node');
       });
 
       it('can be retrieved', () => {
-        const node = tree.findNode(['parent node', 'some new node']);
+        const node = tree.findNode('/browser/parent node/some new node');
         expect(node.data).toEqual({data: 'interesting'});
       });
 
       it('return true for #hasParent()', () => {
-        const node = tree.findNode(['parent node', 'some new node']);
+        const node = tree.findNode('/browser/parent node/some new node');
         expect(node.hasParent()).toEqual(true);
       });
 
       it('return "parent node" object for #parent()', () => {
-        const node = tree.findNode(['parent node', 'some new node']);
+        const node = tree.findNode('/browser/parent node/some new node');
         expect(node.parent()).toEqual(parentNode);
       });
     });
 
     describe('when add an element that already exists under a parent', () => {
       beforeEach(() => {
-        tree.addNewNode('parent node', {data: 'parent data'}, undefined, []);
-        tree.addNewNode('some new node', {data: 'interesting'}, undefined, ['parent' +
-        ' node']);
+        tree.addNewNode('parent node', {data: 'parent data'}, undefined, undefined);
+        tree.addNewNode('some new node', {data: 'interesting'}, undefined, '/browser/parent node');
       });
 
       it('does not add a new child', () => {
-        tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, ['parent' +
-        ' node']);
-        const parentNode = tree.findNode(['parent node']);
+        tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, '/browser/parent node');
+        const parentNode = tree.findNode('/browser/parent node');
         expect(parentNode.children.length).toEqual(1);
       });
 
       it('updates the existing node data', () => {
-        tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, ['parent' +
-        ' node']);
-        const node = tree.findNode(['parent node', 'some new node']);
+        tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, '/browser/parent node');
+        const node = tree.findNode('/browser/parent node/some new node');
         expect(node.data).toEqual({data: 'interesting 1'});
       });
     });
   });
 
-  describe('#translateTreeNodeIdFromACITree', () => {
-    let aciTreeApi;
-    beforeEach(() => {
-      aciTreeApi = jasmine.createSpyObj('ACITreeApi', [
-        'hasParent',
-        'parent',
-        'getId',
-      ]);
-
-      aciTreeApi.getId.and.callFake((node) => {
-        return node[0].id;
-      });
-      tree.aciTreeApi = aciTreeApi;
-    });
-
-    describe('When tree as a single level', () => {
-      beforeEach(() => {
-        aciTreeApi.hasParent.and.returnValue(false);
-      });
-
-      it('returns an array with the ID of the first level', () => {
-        let node = [{
-          id: 'some id',
-        }];
-        tree.addNewNode('some id', {}, undefined, []);
-
-        expect(tree.translateTreeNodeIdFromACITree(node)).toEqual(['some id']);
-      });
-    });
-
-    describe('When tree as a 2 levels', () => {
-      describe('When we try to retrieve the node in the second level', () => {
-        it('returns an array with the ID of the first level and second level', () => {
-          aciTreeApi.hasParent.and.returnValues(true, false);
-          aciTreeApi.parent.and.returnValue([{
-            id: 'parent id',
-          }]);
-          let node = [{
-            id: 'some id',
-          }];
-
-          tree.addNewNode('parent id', {}, undefined, []);
-          tree.addNewNode('some id', {}, undefined, ['parent id']);
-
-          expect(tree.translateTreeNodeIdFromACITree(node))
-            .toEqual(['parent id', 'some id']);
-        });
-      });
-    });
-  });
-
   describe('#selected', () => {
     context('a node in the tree is selected', () => {
       it('returns that node object', () => {
@@ -195,16 +126,17 @@ const treeTests = (treeClass, setDefaultCallBack) => {
   describe('#findNodeByTreeElement', () => {
     context('retrieve data from node not found', () => {
       it('return undefined', () => {
-        let aciTreeApi = jasmine.createSpyObj('ACITreeApi', [
+        let reactTree = jasmine.createSpyObj('tree', [
           'hasParent',
           'parent',
           'getId',
+          'onTreeEvents',
         ]);
 
-        aciTreeApi.getId.and.callFake((node) => {
+        reactTree.getId.and.callFake((node) => {
           return node[0].id;
         });
-        tree.aciTreeApi = aciTreeApi;
+        tree.tree = reactTree;
         expect(tree.findNodeByDomElement(['<li>something</li>'])).toBeUndefined();
       });
     });
@@ -240,14 +172,18 @@ describe('tree tests', () => {
       let level2;
       beforeEach(() => {
         tree = new TreeFake();
-        tree.addNewNode('level1', {data: 'interesting'}, [{id: 'level1'}], []);
+        tree.addNewNode('level1', {data: 'interesting'}, [{id: 'level1'}], undefined);
         level2 = tree.addNewNode('level2', {data: 'data'}, [{id: 'level2'}], ['level1']);
         tree.addNewNode('level3', {data: 'more data'}, [{id: 'level3'}], ['level1', 'level2']);
 
-        tree.aciTreeApi = jasmine.createSpyObj(
-          'ACITreeApi', ['setInode', 'unload', 'deselect', 'select']);
-        tree.aciTreeApi.unload.and.callFake((domNode, config) => {
-          config.success();
+        tree.tree = jasmine.createSpyObj(
+          'tree', ['unload', 'onTreeEvents',
+            'setActiveFile', 'closeDirectory', 'getActiveFile',
+            'deSelectActiveFile']);
+        tree.tree.unload.and.callFake(function() {
+          return new Promise((resolve)=>{
+            resolve('Success!');
+          });
         });
       });
 
@@ -286,11 +222,11 @@ describe('tree tests', () => {
           });
       });
 
-      describe('ACITree specific', () => {
+      describe('ReactTree specific', () => {
         it('sets the current node as a Inode, changing the Icon back to +', (done) => {
           level2.reload(tree)
             .then(()=>{
-              expect(tree.aciTreeApi.setInode).toHaveBeenCalledWith([{id: 'level2'}]);
+              expect(tree.tree.closeDirectory).toHaveBeenCalledWith([{id: 'level2'}]);
               done();
             })
             .catch((error)=>{
@@ -298,12 +234,12 @@ describe('tree tests', () => {
             });
         });
 
-        it('deselect the node and selects it again to trigger ACI tree' +
-          ' events', (done) => {
+        it('deselect the node and selects it again to trigger React tree' +
+              ' events', (done) => {
           level2.reload(tree)
             .then(()=>{
               setTimeout(() => {
-                expect(tree.aciTreeApi.deselect).toHaveBeenCalledWith([{id: 'level2'}]);
+                expect(tree.tree.deSelectActiveFile).toHaveBeenCalledWith([{id: 'level2'}]);
                 done();
               }, 20);
             })
@@ -319,12 +255,14 @@ describe('tree tests', () => {
       let level2;
       beforeEach(() => {
         tree = new TreeFake();
-        tree.addNewNode('level1', {data: 'interesting'}, ['<li>level1</li>'], []);
+        tree.addNewNode('level1', {data: 'interesting'}, ['<li>level1</li>'], undefined);
         level2 = tree.addNewNode('level2', {data: 'data'}, ['<li>level2</li>'], ['level1']);
-        tree.addNewNode('level3', {data: 'more data'}, ['<li>level3</li>'], ['level1', 'level2']);
-        tree.aciTreeApi = jasmine.createSpyObj('ACITreeApi', ['unload']);
-        tree.aciTreeApi.unload.and.callFake((domNode, config) => {
-          config.success();
+        tree.addNewNode('level3', {data: 'more data'}, ['<li>level3</li>'], ['level1','level2']);
+        tree.tree = jasmine.createSpyObj('tree', ['unload']);
+        tree.tree.unload.and.callFake(() => {
+          return new Promise((resolve)=>{
+            resolve('Success!');
+          });
         });
       });
 
@@ -340,10 +278,10 @@ describe('tree tests', () => {
           });
       });
 
-      it('calls unload on the ACI Tree', (done) => {
+      it('calls unload on the React Tree', (done) => {
         level2.unload(tree)
           .then(()=>{
-            expect(tree.aciTreeApi.unload).toHaveBeenCalledWith(['<li>level2</li>'], jasmine.any(Object));
+            expect(tree.tree.unload).toHaveBeenCalledWith(['<li>level2</li>']);
             done();
           })
           .catch((error)=>{
@@ -355,11 +293,11 @@ describe('tree tests', () => {
 
   describe('Tree', () => {
     function realTreeSelectNode(tree, selectedNode) {
-      let aciTreeApi = jasmine.createSpyObj('ACITreeApi', [
-        'selected',
+      let reactTree = jasmine.createSpyObj('tree', [
+        'getActiveFile',
       ]);
-      tree.aciTreeApi = aciTreeApi;
-      aciTreeApi.selected.and.returnValue(selectedNode);
+      tree.tree = reactTree;
+      reactTree.getActiveFile.and.returnValue(selectedNode);
     }
 
     treeTests(Tree, realTreeSelectNode);
@@ -377,8 +315,8 @@ describe('tree tests', () => {
         let tree;
         beforeEach(() => {
           tree = new TreeFake();
-          tree.addNewNode('level1', {data: 'interesting'}, undefined, []);
-          tree.addNewNode('level2', {data: 'interesting'}, undefined, ['level1']);
+          tree.addNewNode('level1', {data: 'interesting'}, undefined, undefined);
+          tree.addNewNode('level2', {data: 'interesting'}, undefined, '/browser/level1');
         });
 
         context('node is at the first level', () => {
@@ -399,7 +337,7 @@ describe('tree tests', () => {
       let tree;
       beforeEach(() => {
         tree = new TreeFake();
-        tree.addNewNode('level1', {data: 'interesting'}, undefined, []);
+        tree.addNewNode('level1', {data: 'interesting'}, undefined, undefined);
         tree.addNewNode('level2', {data: 'interesting'}, undefined, ['level1']);
       });
 
@@ -416,30 +354,6 @@ describe('tree tests', () => {
       });
     });
 
-    describe('#itemData', () => {
-      let tree;
-      beforeEach(() => {
-        tree = new TreeFake();
-        tree.addNewNode('level1', {data: 'interesting'}, undefined, []);
-        tree.addNewNode('level2', {data: 'expected data'}, undefined, ['level1']);
-      });
-
-      context('retrieve data from the node', () => {
-        it('return the node data', () => {
-          expect(tree.itemData([{id: 'level2'}])).toEqual({
-            data: 'expected' +
-            ' data',
-          });
-        });
-      });
-
-      context('retrieve data from node not found', () => {
-        it('return undefined', () => {
-          expect(tree.itemData([{id: 'bamm'}])).toBeUndefined();
-        });
-      });
-    });
-
     describe('#addChild', () => {
       let root, child;
       beforeEach(() => {
@@ -459,7 +373,7 @@ describe('tree tests', () => {
       });
 
       it('changes the path of the child', () => {
-        expect(child.path).toEqual('root.node.1');
+        expect(child.path).toEqual('/browser/root/node.1');
       });
     });
   });
diff --git a/web/webpack.config.js b/web/webpack.config.js
index 1ed1761dc..54b7af79f 100644
--- a/web/webpack.config.js
+++ b/web/webpack.config.js
@@ -190,7 +190,7 @@ var themeCssRules = function(theme_name) {
       filename: 'img/[name].[ext]',
     },
     exclude: /vendor/,
-  }, {
+  },{
     test: /\.(eot|svg|ttf|woff|woff2)$/,
     type: 'asset/resource',
     generator: {
@@ -203,7 +203,7 @@ var themeCssRules = function(theme_name) {
       path.join(sourceDir, '/fonts/'),
     ],
     exclude: /vendor/,
-  }, {
+  },{
     test: /\.scss$/,
     use: [
       {
@@ -212,7 +212,13 @@ var themeCssRules = function(theme_name) {
           publicPath: '',
         },
       },
-      {loader: 'css-loader'},
+      {
+        loader: 'css-loader',
+        options: {
+          url: false,
+          sourceMap: true,
+        },
+      },
       {
         loader: 'postcss-loader',
         options: {
@@ -403,8 +409,17 @@ module.exports = [{
       use: {
         loader: 'babel-loader',
         options: {
-          presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react'],
-          plugins: ['@babel/plugin-proposal-class-properties'],
+          presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react', '@babel/preset-typescript'],
+          plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
+        },
+      },
+    }, {
+      test: /\.tsx?$|\.ts?$/,
+      use: {
+        loader: 'babel-loader',
+        options: {
+          presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react', '@babel/preset-typescript'],
+          plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
         },
       },
     }, {
@@ -544,7 +559,7 @@ module.exports = [{
   resolve: {
     alias: webpackShimConfig.resolveAlias,
     modules: ['node_modules', '.'],
-    extensions: ['.js', '.jsx'],
+    extensions: ['.js', '.jsx', '.ts', '.tsx'],
     unsafeCache: true,
   },
   // Watch mode Configuration: After initial build, webpack will watch for
diff --git a/web/webpack.shim.js b/web/webpack.shim.js
index 868fc3047..7afb81b66 100644
--- a/web/webpack.shim.js
+++ b/web/webpack.shim.js
@@ -155,6 +155,7 @@ var webpackShimConfig = {
     'react-dom': path.join(__dirname, 'node_modules/react-dom'),
     'stylis': path.join(__dirname, 'node_modules/stylis'),
     'popper.js': path.join(__dirname, 'node_modules/popper.js'),
+    'pgadmin4-tree': path.join(__dirname, 'node_modules/pgadmin4-tree'),
 
     // AciTree
     'jquery.acitree': path.join(__dirname, './node_modules/acitree/js/jquery.aciTree.min'),
diff --git a/web/webpack.test.config.js b/web/webpack.test.config.js
index c05e9dacb..fe01129a2 100644
--- a/web/webpack.test.config.js
+++ b/web/webpack.test.config.js
@@ -44,105 +44,115 @@ module.exports = {
   ],
 
   module: {
-    rules: [
-      {
-        test: /\.jsx?$/,
-        exclude: [/node_modules/, /vendor/],
-        use: {
-          loader: 'babel-loader',
+    rules: [{
+      test: /\.jsx?$/,
+      exclude: [/node_modules/, /vendor/],
+      use: {
+        loader: 'babel-loader',
+        options: {
+          presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react'],
+          plugins: ['@babel/plugin-proposal-class-properties'],
+          sourceMap: 'inline',
+        },
+      },
+    }, {
+      test: /\.tsx?$|\.ts?$/,
+      exclude: [/node_modules/, /vendor/],
+      use: {
+        loader: 'babel-loader',
+        options: {
+          presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react', '@babel/preset-typescript'],
+          plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
+          sourceMap: 'inline',
+        },
+      },
+    }, {
+      test: /\.css$/,
+      type: 'asset/source',
+      use: ['style-loader'],
+    }, {
+      test: /\.(jpe?g|png|gif|svg)$/i,
+      type: 'asset',
+      parser: {
+        dataUrlCondition: {
+          maxSize: 4 * 1024, // 4kb
+        },
+      },
+      generator: {
+        filename: 'img/[name].[ext]',
+      },
+      exclude: /vendor/,
+    }, {
+      test: /.*slickgrid[\\\/]+slick\.(?!core)*/,
+      use:[
+        {
+          loader: 'imports-loader',
           options: {
-            presets: [['@babel/preset-env', {'modules': 'commonjs', 'useBuiltIns': 'usage', 'corejs': 3}], '@babel/preset-react'],
-            plugins: ['@babel/plugin-proposal-class-properties'],
-            sourceMap: 'inline',
+            type: 'commonjs',
+            imports: [
+              'pure|jquery.ui',
+              'pure|jquery.event.drag',
+              'pure|slickgrid',
+            ],
           },
         },
-      }, {
-        test: /\.css$/,
-        type: 'asset/source',
-        use: ['style-loader'],
-      }, {
-        test: /\.(jpe?g|png|gif|svg)$/i,
-        type: 'asset',
-        parser: {
-          dataUrlCondition: {
-            maxSize: 4 * 1024, // 4kb
+      ],
+    }, {
+      test: /.*slickgrid\.plugins[\\\/]+slick\.cellrangeselector/,
+      use:[
+        {
+          loader: 'imports-loader',
+          options: {
+            type: 'commonjs',
+            imports: [
+              'pure|jquery.ui',
+              'pure|jquery.event.drag',
+              'pure|slickgrid',
+            ],
           },
-        },
-        generator: {
-          filename: 'img/[name].[ext]',
-        },
-        exclude: /vendor/,
-      }, {
-        test: /.*slickgrid[\\\/]+slick\.(?!core)*/,
-        use:[
-          {
-            loader: 'imports-loader',
-            options: {
-              type: 'commonjs',
-              imports: [
-                'pure|jquery.ui',
-                'pure|jquery.event.drag',
-                'pure|slickgrid',
-              ],
-            },
+        }, {
+          loader: 'exports-loader',
+          options: {
+            type: 'commonjs',
+            exports: 'single|Slick.CellRangeSelector',
           },
-        ],
-      }, {
-        test: /.*slickgrid\.plugins[\\\/]+slick\.cellrangeselector/,
-        use:[
-          {
-            loader: 'imports-loader',
-            options: {
-              type: 'commonjs',
-              imports: [
-                'pure|jquery.ui',
-                'pure|jquery.event.drag',
-                'pure|slickgrid',
-              ],
-            },
-          }, {
-            loader: 'exports-loader',
-            options: {
-              type: 'commonjs',
-              exports: 'single|Slick.CellRangeSelector',
-            },
+        },
+      ],
+    }, {
+      test: /.*slickgrid[\\\/]+slick\.core.*/,
+      use:[
+        {
+          loader: 'imports-loader',
+          options: {
+            type: 'commonjs',
+            imports: [
+              'pure|jquery.ui',
+              'pure|jquery.event.drag',
+            ],
           },
-        ],
-      }, {
-        test: /.*slickgrid[\\\/]+slick\.core.*/,
-        use:[
-          {
-            loader: 'imports-loader',
-            options: {
-              type: 'commonjs',
-              imports: [
-                'pure|jquery.ui',
-                'pure|jquery.event.drag',
-              ],
-            },
-          }, {
-            loader: 'exports-loader',
-            options: {
-              type: 'commonjs',
-              exports: 'single|Slick',
-            },
+        }, {
+          loader: 'exports-loader',
+          options: {
+            type: 'commonjs',
+            exports: 'single|Slick',
           },
-        ],
-      },
-      {
-        test: /\.js$|\.jsx$/,
-        use: {
-          loader: 'istanbul-instrumenter-loader',
-          options: { esModules: true },
         },
-        enforce: 'post',
-        exclude: /node_modules|slickgrid|plugins|bundle|generated|regression|[Tt]est.js|[Ss]pecs.js|[Ss]pec.js|\.spec\.js$/,
+      ],
+    },
+    {
+      test: /\.js$|\.jsx$/,
+      use: {
+        loader: 'istanbul-instrumenter-loader',
+        options: { esModules: true },
       },
+      enforce: 'post',
+      exclude: /node_modules|slickgrid|plugins|bundle|generated|regression|[Tt]est.js|[Ss]pecs.js|[Ss]pec.js|\.spec\.js$/,
+    },
     ],
   },
 
   resolve: {
-    extensions: ['.js', '.jsx'],
+    extensions: ['.js', '.jsx', '.ts', '.tsx'],
     alias: {
       'top': path.join(__dirname, './pgadmin'),
       'jquery': path.join(__dirname, './node_modules/jquery/dist/jquery'),
@@ -173,6 +183,7 @@ module.exports = {
       'pgadmin.alertifyjs': sourcesDir + '/js/alertify.pgadmin.defaults',
       'pgadmin.backgrid': sourcesDir + '/js/backgrid.pgadmin',
       'pgadmin.backform': sourcesDir + '/js/backform.pgadmin',
+      'pgadmin4-tree': path.join(__dirname, 'node_modules/pgadmin4-tree'),
       'pgbrowser': path.resolve(__dirname, 'regression/javascript/fake_browser'),
       'pgadmin.schema.dir': path.resolve(__dirname, 'pgadmin/browser/server_groups/servers/databases/schemas/static/js'),
       'pgadmin.browser.layout': path.join(__dirname, './pgadmin/browser/static/js/layout'),
diff --git a/web/yarn.lock b/web/yarn.lock
index fd246c205..e66108f5d 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -16,11 +16,23 @@
   dependencies:
     "@babel/highlight" "^7.12.13"
 
+"@babel/code-frame@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
+  integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
+  dependencies:
+    "@babel/highlight" "^7.14.5"
+
 "@babel/compat-data@^7.13.0", "@babel/compat-data@^7.13.8":
   version "7.13.8"
   resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6"
   integrity sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog==
 
+"@babel/compat-data@^7.14.5", "@babel/compat-data@^7.14.7":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08"
+  integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==
+
 "@babel/core@^7.10.2", "@babel/core@^7.7.5":
   version "7.13.8"
   resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.8.tgz#c191d9c5871788a591d69ea1dc03e5843a3680fb"
@@ -68,6 +80,15 @@
     jsesc "^2.5.1"
     source-map "^0.5.0"
 
+"@babel/generator@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785"
+  integrity sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==
+  dependencies:
+    "@babel/types" "^7.14.5"
+    jsesc "^2.5.1"
+    source-map "^0.5.0"
+
 "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13":
   version "7.12.13"
   resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab"
@@ -75,6 +96,13 @@
   dependencies:
     "@babel/types" "^7.12.13"
 
+"@babel/helper-annotate-as-pure@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61"
+  integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13":
   version "7.12.13"
   resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz#6bc20361c88b0a74d05137a65cac8d3cbf6f61fc"
@@ -93,6 +121,16 @@
     browserslist "^4.14.5"
     semver "^6.3.0"
 
+"@babel/helper-compilation-targets@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz#7a99c5d0967911e972fe2c3411f7d5b498498ecf"
+  integrity sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==
+  dependencies:
+    "@babel/compat-data" "^7.14.5"
+    "@babel/helper-validator-option" "^7.14.5"
+    browserslist "^4.16.6"
+    semver "^6.3.0"
+
 "@babel/helper-create-class-features-plugin@^7.13.0":
   version "7.13.8"
   resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.8.tgz#0367bd0a7505156ce018ca464f7ac91ba58c1a04"
@@ -104,6 +142,18 @@
     "@babel/helper-replace-supers" "^7.13.0"
     "@babel/helper-split-export-declaration" "^7.12.13"
 
+"@babel/helper-create-class-features-plugin@^7.14.6":
+  version "7.14.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz#f114469b6c06f8b5c59c6c4e74621f5085362542"
+  integrity sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.14.5"
+    "@babel/helper-function-name" "^7.14.5"
+    "@babel/helper-member-expression-to-functions" "^7.14.5"
+    "@babel/helper-optimise-call-expression" "^7.14.5"
+    "@babel/helper-replace-supers" "^7.14.5"
+    "@babel/helper-split-export-declaration" "^7.14.5"
+
 "@babel/helper-create-regexp-features-plugin@^7.12.13":
   version "7.14.3"
   resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.3.tgz#149aa6d78c016e318c43e2409a0ae9c136a86688"
@@ -142,6 +192,15 @@
     "@babel/template" "^7.12.13"
     "@babel/types" "^7.14.2"
 
+"@babel/helper-function-name@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4"
+  integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==
+  dependencies:
+    "@babel/helper-get-function-arity" "^7.14.5"
+    "@babel/template" "^7.14.5"
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-get-function-arity@^7.12.13":
   version "7.12.13"
   resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583"
@@ -149,6 +208,13 @@
   dependencies:
     "@babel/types" "^7.12.13"
 
+"@babel/helper-get-function-arity@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815"
+  integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-hoist-variables@^7.13.0":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz#5d5882e855b5c5eda91e0cadc26c6e7a2c8593d8"
@@ -157,6 +223,13 @@
     "@babel/traverse" "^7.13.0"
     "@babel/types" "^7.13.0"
 
+"@babel/helper-hoist-variables@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d"
+  integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-member-expression-to-functions@^7.13.0":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091"
@@ -164,6 +237,13 @@
   dependencies:
     "@babel/types" "^7.13.0"
 
+"@babel/helper-member-expression-to-functions@^7.14.5":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz#97e56244beb94211fe277bd818e3a329c66f7970"
+  integrity sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12":
   version "7.13.12"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977"
@@ -193,11 +273,23 @@
   dependencies:
     "@babel/types" "^7.12.13"
 
+"@babel/helper-optimise-call-expression@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c"
+  integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af"
   integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==
 
+"@babel/helper-plugin-utils@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
+  integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
+
 "@babel/helper-remap-async-to-generator@^7.13.0":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz#376a760d9f7b4b2077a9dd05aa9c3927cadb2209"
@@ -217,6 +309,16 @@
     "@babel/traverse" "^7.13.0"
     "@babel/types" "^7.13.0"
 
+"@babel/helper-replace-supers@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz#0ecc0b03c41cd567b4024ea016134c28414abb94"
+  integrity sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==
+  dependencies:
+    "@babel/helper-member-expression-to-functions" "^7.14.5"
+    "@babel/helper-optimise-call-expression" "^7.14.5"
+    "@babel/traverse" "^7.14.5"
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-simple-access@^7.12.13":
   version "7.13.12"
   resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6"
@@ -238,16 +340,38 @@
   dependencies:
     "@babel/types" "^7.12.13"
 
+"@babel/helper-split-export-declaration@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a"
+  integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==
+  dependencies:
+    "@babel/types" "^7.14.5"
+
 "@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0":
   version "7.14.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
   integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==
 
+"@babel/helper-validator-identifier@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
+  integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
+
+"@babel/helper-validator-identifier@^7.14.9":
+  version "7.14.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
+  integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
+
 "@babel/helper-validator-option@^7.12.17":
   version "7.12.17"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831"
   integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==
 
+"@babel/helper-validator-option@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
+  integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
+
 "@babel/helper-wrap-function@^7.13.0":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz#bdb5c66fda8526ec235ab894ad53a1235c79fcc4"
@@ -276,11 +400,25 @@
     chalk "^2.0.0"
     js-tokens "^4.0.0"
 
+"@babel/highlight@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
+  integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.5"
+    chalk "^2.0.0"
+    js-tokens "^4.0.0"
+
 "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.4":
   version "7.13.9"
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99"
   integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw==
 
+"@babel/parser@^7.14.5", "@babel/parser@^7.14.7":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595"
+  integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==
+
 "@babel/plugin-proposal-async-generator-functions@^7.13.8":
   version "7.13.8"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.8.tgz#87aacb574b3bc4b5603f6fe41458d72a5a2ec4b1"
@@ -346,7 +484,18 @@
     "@babel/helper-plugin-utils" "^7.13.0"
     "@babel/plugin-syntax-numeric-separator" "^7.10.4"
 
-"@babel/plugin-proposal-object-rest-spread@^7.13.8", "@babel/plugin-proposal-object-rest-spread@^7.9.6":
+"@babel/plugin-proposal-object-rest-spread@^7.10.1":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz#5920a2b3df7f7901df0205974c0641b13fd9d363"
+  integrity sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==
+  dependencies:
+    "@babel/compat-data" "^7.14.7"
+    "@babel/helper-compilation-targets" "^7.14.5"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+    "@babel/plugin-transform-parameters" "^7.14.5"
+
+"@babel/plugin-proposal-object-rest-spread@^7.13.8":
   version "7.13.8"
   resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz#5d210a4d727d6ce3b18f9de82cc99a3964eed60a"
   integrity sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==
@@ -481,6 +630,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.12.13"
 
+"@babel/plugin-syntax-typescript@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716"
+  integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
 "@babel/plugin-transform-arrow-functions@^7.13.0":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz#10a59bebad52d637a027afa692e8d5ceff5e3dae"
@@ -657,6 +813,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.13.0"
 
+"@babel/plugin-transform-parameters@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz#49662e86a1f3ddccac6363a7dfb1ff0a158afeb3"
+  integrity sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+
 "@babel/plugin-transform-property-literals@^7.12.13":
   version "7.12.13"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz#4e6a9e37864d8f1b3bc0e2dce7bf8857db8b1a81"
@@ -758,6 +921,15 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.12.13"
 
+"@babel/plugin-transform-typescript@^7.14.5":
+  version "7.14.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.6.tgz#6e9c2d98da2507ebe0a883b100cde3c7279df36c"
+  integrity sha512-XlTdBq7Awr4FYIzqhmYY80WN0V0azF74DMPyFqVHBvf81ZUgc4X7ZOpx6O8eLDK6iM5cCQzeyJw0ynTaefixRA==
+  dependencies:
+    "@babel/helper-create-class-features-plugin" "^7.14.6"
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/plugin-syntax-typescript" "^7.14.5"
+
 "@babel/plugin-transform-unicode-escapes@^7.12.13":
   version "7.12.13"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.13.tgz#840ced3b816d3b5127dd1d12dcedc5dead1a5e74"
@@ -870,10 +1042,19 @@
     "@babel/plugin-transform-react-jsx-development" "^7.12.17"
     "@babel/plugin-transform-react-pure-annotations" "^7.12.1"
 
+"@babel/preset-typescript@^7.8.3":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz#aa98de119cf9852b79511f19e7f44a2d379bcce0"
+  integrity sha512-u4zO6CdbRKbS9TypMqrlGH7sd2TAJppZwn3c/ZRLeO/wGsbddxgbPDUZVNrie3JWYLQ9vpineKlsrWFvO6Pwkw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.14.5"
+    "@babel/helper-validator-option" "^7.14.5"
+    "@babel/plugin-transform-typescript" "^7.14.5"
+
 "@babel/runtime@^7.0.0":
-  version "7.15.4"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
-  integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
+  version "7.14.6"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
+  integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
   dependencies:
     regenerator-runtime "^0.13.4"
 
@@ -900,6 +1081,15 @@
     "@babel/parser" "^7.12.13"
     "@babel/types" "^7.12.13"
 
+"@babel/template@^7.14.5":
+  version "7.14.5"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
+  integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/parser" "^7.14.5"
+    "@babel/types" "^7.14.5"
+
 "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc"
@@ -915,6 +1105,21 @@
     globals "^11.1.0"
     lodash "^4.17.19"
 
+"@babel/traverse@^7.14.5":
+  version "7.14.7"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753"
+  integrity sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==
+  dependencies:
+    "@babel/code-frame" "^7.14.5"
+    "@babel/generator" "^7.14.5"
+    "@babel/helper-function-name" "^7.14.5"
+    "@babel/helper-hoist-variables" "^7.14.5"
+    "@babel/helper-split-export-declaration" "^7.14.5"
+    "@babel/parser" "^7.14.7"
+    "@babel/types" "^7.14.5"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
 "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.13.0", "@babel/types@^7.4.4":
   version "7.13.0"
   resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80"
@@ -932,6 +1137,14 @@
     "@babel/helper-validator-identifier" "^7.14.0"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.14.5":
+  version "7.15.4"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.4.tgz#74eeb86dbd6748d2741396557b9860e57fce0a0d"
+  integrity sha512-0f1HJFuGmmbrKTCZtbm3cU+b/AqdEYk5toj5iQur58xkVMlS0JWaKxTBSmCXd47uiN7vbcozAupm6Mvs80GNhw==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.14.9"
+    to-fast-properties "^2.0.0"
+
 "@date-io/core@1.x", "@date-io/core@^1.3.13":
   version "1.3.13"
   resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa"
@@ -1326,6 +1539,13 @@
   resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669"
   integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==
 
+"@types/classnames@^2.2.6":
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.3.1.tgz#3c2467aa0f1a93f1f021e3b9bcf938bd5dfdc0dd"
+  integrity sha512-zeOWb0JGBoVmlQoznvqXbE0tEC/HONsnoUNH19Hc96NFsTAwTXbTqb8FMYkru1F/iqp7a18Ws3nWJvtA1sHD1A==
+  dependencies:
+    classnames "*"
+
 "@types/component-emitter@^1.2.10":
   version "1.2.10"
   resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
@@ -1405,6 +1625,13 @@
   resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
   integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
 
+"@types/react-dom@^16.0.11":
+  version "16.9.13"
+  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.13.tgz#5898f0ee68fe200685e6b61d3d7d8828692814d0"
+  integrity sha512-34Hr3XnmUSJbUVDxIw/e7dhQn2BJZhJmlAaPyPwfTQyuVS9mV/CeyghFcXyvkJXxI7notQJz8mF8FeCVvloJrA==
+  dependencies:
+    "@types/react" "^16"
+
 "@types/react-transition-group@^4.2.0":
   version "4.4.1"
   resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.1.tgz#e1a3cb278df7f47f17b5082b1b3da17170bd44b1"
@@ -1421,6 +1648,15 @@
     "@types/scheduler" "*"
     csstype "^3.0.2"
 
+"@types/react@^16", "@types/react@^16.7.18":
+  version "16.14.10"
+  resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.10.tgz#76bc1c42ed5ab0d2ab13e5c58faaccaad3449477"
+  integrity sha512-QadBsMyF6ldjEAXEhsmEW/L0uBDJT8yw7Qoe5sRnEKVrzMkiYoJwqoL5TKJOlArsn/wvIJM/XdVzkdL6+AS64Q==
+  dependencies:
+    "@types/prop-types" "*"
+    "@types/scheduler" "*"
+    csstype "^3.0.2"
+
 "@types/scheduler@*":
   version "0.16.1"
   resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
@@ -1696,7 +1932,12 @@ airbnb-prop-types@^2.16.0:
     prop-types-exact "^1.2.0"
     react-is "^16.13.1"
 
-ajv-keywords@^3.5.2:
+ajv-errors@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
+  integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
+
+ajv-keywords@^3.1.0, ajv-keywords@^3.5.2:
   version "3.5.2"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
   integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
@@ -1711,7 +1952,7 @@ ajv@^5.0.0:
     fast-json-stable-stringify "^2.0.0"
     json-schema-traverse "^0.3.0"
 
-ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.12.6:
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.12.6:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
   integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -1895,6 +2136,30 @@ asn1@~0.2.3:
   dependencies:
     safer-buffer "~2.1.0"
 
+aspen-core@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/aspen-core/-/aspen-core-1.0.4.tgz#a2d6a23c80303e73aaa836c124c116e447ba7a7d"
+  integrity sha512-mQ79JxHstB2rf47Zgw2yduAH9L47b+3bwQtpbEAKeSJsLTPe8X7lsQ6lLP3tFbS204TNILC5LxSkVWv45FXQYg==
+  dependencies:
+    notificar "^1.0.1"
+    p-series "^1.1.0"
+    path-fx "^2.1.1"
+
+aspen-decorations@^1.0.2, aspen-decorations@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/aspen-decorations/-/aspen-decorations-1.1.1.tgz#7d0ca740efab1aa4fd91a1f3db81ac29186607a3"
+  integrity sha512-Ej2tv0Gz3bnhkNCyzzjDeG2V5vd49T30ca0SKywHuLA5RKrZ1NutEyZnUYku4WmUV1/TdpHRiSJ759nbZK4xtQ==
+  dependencies:
+    notificar "^1.0.1"
+
+aspen-tree-model@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/aspen-tree-model/-/aspen-tree-model-1.0.5.tgz#23d5ce7a8fb7ab905d37b17b930cc6f92e4d366e"
+  integrity sha512-kcdL22iAT1sp1HTQ3wJnQqSeA2ANSQiOZJ86RMk9tKBZjb5EFSs2khEFQ6iYE7bvHcWTarGzD7X8XKfxe/zxXg==
+  dependencies:
+    aspen-core "^1.0.4"
+    notificar "^1.0.1"
+
 assert-plus@1.0.0, assert-plus@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
@@ -1918,6 +2183,13 @@ async@0.9.x:
   resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
   integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=
 
+async@^2.1.4:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+  integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+  dependencies:
+    lodash "^4.17.14"
+
 async@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
@@ -2391,6 +2663,14 @@ browser-resolve@^2.0.0:
   dependencies:
     resolve "^1.17.0"
 
+browserfs@^1.4.3:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/browserfs/-/browserfs-1.4.3.tgz#92ffc6063967612daccdb8566d3fc03f521205fb"
+  integrity sha512-tz8HClVrzTJshcyIu8frE15cjqjcBIu15Bezxsvl/i+6f59iNCN3kznlWjz0FEb3DlnDx3gW5szxeT6D1x0s0w==
+  dependencies:
+    async "^2.1.4"
+    pako "^1.0.4"
+
 browserify-aes@^1.0.0, browserify-aes@^1.0.4:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
@@ -2809,6 +3089,11 @@ circular-json-es6@^2.0.1:
   resolved "https://registry.yarnpkg.com/circular-json-es6/-/circular-json-es6-2.0.2.tgz#e4f4a093e49fb4b6aba1157365746112a78bd344"
   integrity sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==
 
+classnames@*, classnames@^2.2.6:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
+  integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
+
 cliui@^7.0.2:
   version "7.0.4"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@@ -3026,6 +3311,13 @@ content-type@~1.0.4:
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
   integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
 
+context-menu@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/context-menu/-/context-menu-2.0.0.tgz#565f13210248e3442700e6b1a2d63406f2b08552"
+  integrity sha512-VQrkvcJDevuq+sde0QADRLOdIRpa4a1ti4knstrPILDLfWU/RB4ZIGpj32Chh/mURjrbi0CoLT1eonr3X86Khg==
+  dependencies:
+    tiny-emitter "^2.0.2"
+
 convert-source-map@^1.1.3, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
@@ -5290,6 +5582,11 @@ inline-style-parser@0.1.1:
   resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1"
   integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==
 
+insert-if@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/insert-if/-/insert-if-1.2.0.tgz#5b878ead294a727eb75598ef8cf9244f33e17157"
+  integrity sha512-UFXvgVVosbyfa7tsowU8nOLHp/fGe7oGi5vYMy9wEQio8olkf+P7sHssmYnUe991du5EDlD+n/5cW17WgM7Cog==
+
 insert-module-globals@^7.2.1:
   version "7.2.1"
   resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.1.tgz#d5e33185181a4e1f33b15f7bf100ee91890d5cb3"
@@ -5535,6 +5832,13 @@ is-regex@^1.1.3:
     call-bind "^1.0.2"
     has-symbols "^1.0.2"
 
+is-relative@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
+  integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
+  dependencies:
+    is-unc-path "^1.0.0"
+
 is-resolvable@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
@@ -5595,6 +5899,13 @@ is-typedarray@~1.0.0:
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
   integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
 
+is-unc-path@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
+  integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
+  dependencies:
+    unc-path-regex "^0.1.2"
+
 is-utf8@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
@@ -6174,7 +6485,7 @@ loader-runner@^4.2.0:
   resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
   integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==
 
-loader-utils@^1.1.0, loader-utils@^1.4.0:
+loader-utils@^1.0.3, loader-utils@^1.1.0, loader-utils@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
   integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@@ -6496,7 +6807,7 @@ mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24:
   dependencies:
     mime-db "1.46.0"
 
-mime@^2.3.1, mime@^2.4.5:
+mime@^2.0.3, mime@^2.3.1, mime@^2.4.5:
   version "2.5.2"
   resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
   integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
@@ -6790,6 +7101,11 @@ normalize-url@^4.5.0:
   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
   integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
 
+notificar@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/notificar/-/notificar-1.0.1.tgz#11ba233c261eee02f5d688ee300ece5f72522887"
+  integrity sha512-jiCay0IY0N+gloyDks+v4WV+OKU4lIXUhQgxw4Iu9bXpw80cNXTezVv46OCK5+E8G8fkt1Bj76DNepULqlQS3Q==
+
 npm-conf@^1.1.0:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
@@ -7064,6 +7380,14 @@ p-reduce@^1.0.0:
   resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
   integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
 
+p-series@^1.0.0, p-series@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/p-series/-/p-series-1.1.0.tgz#f2d8522cdfd58b464eb9685651d465037ee3c957"
+  integrity sha512-356covArc9UCfj2twY/sxCJKGMzzO+pJJtucizsPC6aS1xKSTBc9PQrQhvFR3+7F+fa2KBKdJjdIcv6NEWDcIQ==
+  dependencies:
+    "@sindresorhus/is" "^0.7.0"
+    p-reduce "^1.0.0"
+
 p-timeout@^1.1.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386"
@@ -7083,7 +7407,7 @@ p-try@^2.0.0:
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
-pako@^1.0.0, pako@~1.0.5:
+pako@^1.0.0, pako@^1.0.4, pako@~1.0.5:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
   integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
@@ -7174,6 +7498,13 @@ path-exists@^4.0.0:
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
   integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
 
+path-fx@^2.0.0, path-fx@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/path-fx/-/path-fx-2.1.1.tgz#51594f9f8223d5c1d5b74be55f20a7abb18dc9f6"
+  integrity sha512-YQeSXseFrHZtxesLJVK4AGv/J3bPmmb0mAMeUbf52b2MVwLlzTEY2NatLP8mUE7eR0F4EBOIRmrQjPPvHZI2+Q==
+  dependencies:
+    is-relative "^1.0.0"
+
 path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -7246,6 +7577,26 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
+"pgadmin4-tree@git+https://github.com/EnterpriseDB/pgadmin4-treeview/#383edc329e2b322a5a646b5db75dd2910c1af2a4":
+  version "1.0.0"
+  resolved "git+https://github.com/EnterpriseDB/pgadmin4-treeview/#383edc329e2b322a5a646b5db75dd2910c1af2a4"
+  dependencies:
+    "@types/classnames" "^2.2.6"
+    "@types/react" "^16.7.18"
+    "@types/react-dom" "^16.0.11"
+    aspen-decorations "^1.1.1"
+    browserfs "^1.4.3"
+    classnames "^2.2.6"
+    context-menu "^2.0.0"
+    insert-if "^1.1.0"
+    lodash "4.*"
+    notificar "^1.0.1"
+    path-fx "^2.0.0"
+    react "^16.6.3"
+    react-aspen "^1.1.1"
+    react-dom "^16.6.3"
+    valid-filename "^2.0.1"
+
 picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
@@ -7782,6 +8133,27 @@ raw-body@2.4.0:
     iconv-lite "0.4.24"
     unpipe "1.0.0"
 
+react-aspen@^1.1.0, react-aspen@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/react-aspen/-/react-aspen-1.1.1.tgz#61a85ef43748158322c4a3b73faaa5e563edd038"
+  integrity sha512-m+r+UIAw29PKgt+2on7zR/fCa7dnvLeM/x2HorGPa39xm4ELHY0PhN0oyE2mO95yqha7mqexD7RXd6iKfVKv7g==
+  dependencies:
+    aspen-tree-model "^1.0.5"
+    notificar "^1.0.1"
+    p-series "^1.0.0"
+    path-fx "^2.1.1"
+    react-window "^1.3.1"
+
+react-dom@^16.6.3:
+  version "16.14.0"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89"
+  integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.2"
+    scheduler "^0.19.1"
+
 react-dom@^17.0.1:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
@@ -7869,7 +8241,7 @@ react-virtualized-auto-sizer@^1.0.6:
   resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca"
   integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ==
 
-react-window@^1.8.5:
+react-window@^1.3.1, react-window@^1.8.5:
   version "1.8.6"
   resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112"
   integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==
@@ -7877,6 +8249,15 @@ react-window@^1.8.5:
     "@babel/runtime" "^7.0.0"
     memoize-one ">=3.1.1 <6"
 
+react@^16.6.3:
+  version "16.14.0"
+  resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
+  integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+    prop-types "^15.6.2"
+
 react@^17.0.1:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@@ -8246,6 +8627,14 @@ sax@^1.2.4, sax@~1.2.4:
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
 
+scheduler@^0.19.1:
+  version "0.19.1"
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
+  integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
+  dependencies:
+    loose-envify "^1.1.0"
+    object-assign "^4.1.1"
+
 scheduler@^0.20.2:
   version "0.20.2"
   resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
@@ -8261,6 +8650,15 @@ schema-utils@^0.3.0:
   dependencies:
     ajv "^5.0.0"
 
+schema-utils@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
+  integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==
+  dependencies:
+    ajv "^6.1.0"
+    ajv-errors "^1.0.0"
+    ajv-keywords "^3.1.0"
+
 schema-utils@^2.6.5:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
@@ -8963,7 +9361,15 @@ svgicons2svgfont@^9.0.3:
     string.prototype.codepointat "^0.2.1"
     svg-pathdata "^5.0.2"
 
-svgo@^1.3.2:
+svgo-loader@^2.2.0:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/svgo-loader/-/svgo-loader-2.2.2.tgz#5f54e3e0d77c36a84c42bcb42e812c4db534bf96"
+  integrity sha512-UeE/4yZEK96LoYqvxwh8YqCOJCjXwRY9K6YT99vXE+nYhs/W8hAY2hNf5zg/lRsyKshJkR79V+4beV3cbGL40Q==
+  dependencies:
+    js-yaml "^3.13.1"
+    loader-utils "^1.0.3"
+
+svgo@^1.1.1, svgo@^1.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
   integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==
@@ -9150,6 +9556,11 @@ timsort@^0.3.0:
   resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
   integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
 
+tiny-emitter@^2.0.2:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
+  integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
+
 tiny-warning@^1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
@@ -9305,6 +9716,11 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
+typescript@^3.2.2:
+  version "3.9.10"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
+  integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
+
 ua-parser-js@^0.7.23:
   version "0.7.24"
   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.24.tgz#8d3ecea46ed4f1f1d63ec25f17d8568105dc027c"
@@ -9338,6 +9754,11 @@ unbzip2-stream@^1.0.9:
     buffer "^5.2.1"
     through "^2.3.8"
 
+unc-path-regex@^0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
+  integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
+
 undeclared-identifiers@^1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz#9254c1d37bdac0ac2b52de4b6722792d2a91e30f"
@@ -9409,6 +9830,15 @@ url-join@^4.0.0:
   resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7"
   integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==
 
+url-loader@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8"
+  integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==
+  dependencies:
+    loader-utils "^1.1.0"
+    mime "^2.0.3"
+    schema-utils "^1.0.0"
+
 url-parse-lax@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
@@ -9485,6 +9915,13 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0:
   resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
   integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
 
+valid-filename@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/valid-filename/-/valid-filename-2.0.1.tgz#0768d6f364b1ed3bdf68f0d15abffb0d9d6cecaf"
+  integrity sha1-B2jW82Sx7TvfaPDRWr/7DZ1s7K8=
+  dependencies:
+    filename-reserved-regex "^2.0.0"
+
 validate-npm-package-license@^3.0.1:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
