Port browser tree to React. Fixes #6129

This commit is contained in:
Khushboo Vashi
2021-09-27 16:44:26 +05:30
committed by Akshay Joshi
parent d983225683
commit 483e2ca8d0
99 changed files with 2339 additions and 1785 deletions

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -48,7 +48,7 @@ export default class CollationSchema extends BaseUISchema {
{
id: 'owner', label: gettext('Owner'),
type: 'select', mode: ['properties', 'create', 'edit'],
options: obj.ownerList
options: obj.ownerList, controlProps: { allowClear: false },
},
{
id: 'schema', label: gettext('Schema'),
@@ -65,7 +65,7 @@ export default class CollationSchema extends BaseUISchema {
res.push(d);
});
return res;
}
}, allowClear: false,
}
};
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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')

View File

@@ -409,7 +409,7 @@ define('pgadmin.node.schema', [
});
pgBrowser.tableChildTreeNodeHierarchy = function(i) {
return this.getTreeNodeHierarchy(i);
return pgBrowser.tree.getTreeNodeHierarchy(i);
};
}

View File

@@ -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);

View File

@@ -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')

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {
@@ -81,7 +81,7 @@ define('pgadmin.node.primary_key', [
primary_key_found = false;
_.each(children, function(child){
data = pgBrowser.tree.itemData($(child));
data = pgBrowser.tree.itemData(child);
if (!primary_key_found && data._type == 'primary_key') {
primary_key_found = true;
}

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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);
}
}

View File

@@ -148,7 +148,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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
},

View File

@@ -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

View File

@@ -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({

View File

@@ -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;

View File

@@ -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(

View File

@@ -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);

View File

@@ -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(

View File

@@ -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,
});
'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};
b.tree = $('#tree').aciTree('api');
b.treeMenu.register($('#tree'));
parsedFunc = pgadminUtils.parseFuncParams(newData._label);
newData._label = parsedFunc.func_name;
dropVal = pgadminUtils.fully_qualify(b, newData, item);
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};
if(parsedFunc.params.length > 0) {
dropVal = dropVal + '(';
curPos.from = dropVal.length;
dropVal = dropVal + parsedFunc.params[0][0];
curPos.to = dropVal.length;
parsedFunc = pgadminUtils.parseFuncParams(newData._label);
newData._label = parsedFunc.func_name;
dropVal = pgadminUtils.fully_qualify(b, newData, item);
for(let i=1; i<parsedFunc.params.length; i++) {
dropVal = dropVal + ', ' + parsedFunc.params[i][0];
}
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,11 @@ define('pgadmin.browser', [
}
},
onRefreshTreeNodeReact: function(_i) {
this.tree.refresh(_i);
return;
},
onRefreshTreeNode: function(_i, _opts) {
var _d = _i && this.tree.itemData(_i),
n = _d && _d._type && this.Nodes[_d._type],
@@ -2034,10 +1932,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 +1946,7 @@ define('pgadmin.browser', [
if (nodeToSelect)
tree_local.select(nodeToSelect);
}
tree_local.remove(_node);
return true;
},

View File

@@ -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);
},
});

View File

@@ -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,

View File

@@ -89,7 +89,7 @@ _.extend(pgBrowser, {
browser.reflectLocklayoutChange(docker);
});
}
}, 500);
}, 5000);
},
reflectLocklayoutChange: function(docker) {

View File

@@ -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));
});
}

View File

@@ -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();

View File

@@ -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);
}
});

View File

@@ -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) {

View File

@@ -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 ;

View File

@@ -71,7 +71,7 @@ define('misc.dependents', [
if (visible) {
this.dependentsPanel = pgBrowser.docker.findPanels('dependents')[0];
var t = pgBrowser.tree,
i = t.selected(),
i = t && t.selected(),
d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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();
},

View File

@@ -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);
}
}
}
};

View File

@@ -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(

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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']];

View File

@@ -7,132 +7,408 @@
//
//////////////////////////////////////////////////////////////////////////
import {isValidData} from 'sources/utils';
import _ from 'lodash';
import $ from 'jquery';
import Alertify from 'pgadmin.alertifyjs';
import pgAdmin from 'sources/pgadmin';
export class TreeNode {
constructor(id, data, domNode, parent) {
this.id = id;
this.data = data;
this.setParent(parent);
this.children = [];
this.domNode = domNode;
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 = {};
}
hasParent() {
return this.parentNode !== null && this.parentNode !== undefined;
async refresh(item) {
await this.tree.refresh(item);
}
parent() {
return this.parentNode;
async add(item, data) {
await this.tree.create(item.parent, data.itemData);
}
setParent(parent) {
this.parentNode = parent;
this.path = this.id;
if (parent !== null && parent !== undefined && parent.path !== undefined) {
this.path = parent.path + '.' + this.id;
async before(item, data) {
await this.tree.create(item.parent, data.itemData);
}
async update(item, data) {
await this.tree.update(item, data.itemData);
}
async remove(item) {
return await this.tree.remove(item);
}
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;
}
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 null;
}
async open(item) {
if (this.isOpen(item)) { return true; }
await this.tree.toggleDirectory(item);
}
async ensureVisible(item){
await this.tree.ensureVisible(item);
}
async openPath(item) {
parent = item.parent;
await this.tree.openDirectory(parent);
}
async close(item) {
await this.tree.closeDirectory(item);
}
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);
}
removeIcon() {
// TBD
}
setLeaf() {
// TBD
}
async setLabel(item, label) {
if(item) {
await this.tree.setLabel(item, label);
}
}
getData() {
if (this.data === undefined) {
return undefined;
} else if (this.data === null) {
return null;
async setInode(item) {
if(item._children) item._children = null;
await this.tree.closeDirectory(item);
}
deselect(item) {
this.tree.deSelectActiveFile(item);
}
wasInit() {
// TBD
return true;
}
wasLoad(item) {
if (item && item.type === FileType.Directory) {
return item.isExpanded;
}
return Object.assign({}, this.data);
return true;
}
getHtmlIdentifier() {
return this.domNode;
parent(item) {
return item.parent;
}
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();
});
});
}
first(item) {
const model = this.tree.getModel();
if (item === undefined || item === null) {
return model.root.children[0];
}
unload(tree) {
return new Promise((resolve, reject)=>{
this.children = [];
tree.aciTreeApi.unload(this.domNode, {
success: ()=>{
resolve(true);
},
fail: ()=>{
reject();
},
});
});
}
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);
},
});
}
});
}
/*
* Find the ancestor with matches this condition
*/
ancestorNode(condition) {
let node = this;
while (node.hasParent()) {
node = node.parent();
if (condition(node)) {
return node;
}
if (item.branchSize > 0) {
return item.children[0];
}
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;
children(item) {
const model = this.tree.getModel();
return item ? (item.children !== null ? item.children : []) : model.root.children;
}
itemFrom(domElem) {
return this.tree.getItemFromDOM(domElem[0]);
}
path(item) {
if (item) return item.path;
}
pathId(item) {
if (item) {
let pathIds = item.path.split('/');
pathIds.splice(0, 1);
return pathIds;
}
return [];
}
itemFromDOM(domElem) {
return this.tree.getItemFromDOM(domElem[0]);
}
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 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 = '/browser/' + path.join('/');
let onCorrectPath = function(matchPath) {
return (matchPath !== undefined && path !== undefined
&& (path.startsWith(matchPath) || path === matchPath));
};
return (function findInNode(currentNode) {
return new Promise((resolve, reject)=>{
if (path === null || path === undefined || path.length === 0) {
resolve(null);
}
/* No point in checking the children if
* the path for currentNode itself is not matching
*/
if (currentNode.path !== undefined && !onCorrectPath(currentNode.path)) {
reject(null);
} else if (currentNode.path === path) {
resolve(currentNode);
} else {
tree.open(currentNode)
.then(()=>{
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;
}
}
reject(null);
})
.catch(()=>{
reject(null);
});
}
});
})(tree.tree.getModel().root);
}
findNodeByDomElement(domElement) {
const path = domElement.path;
if(!path || !path[0]) {
return undefined;
}
return this.ancestorNode(condition) !== null;
return this.findNode(path);
}
anyParent(condition) {
return this.ancestorNode(condition) !== null;
}
}
export class Tree {
constructor() {
this.rootNode = new TreeNode(undefined, {});
this.aciTreeApi = undefined;
this.draggableTypes = {};
addNewNode(id, data, item, parentPath) {
let parent;
parent = this.findNode(parentPath);
return this.createOrUpdateNode(id, data, parent, item);
}
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 && parent.path !== undefined && parent.path != '/browser') {
oldNodePath = parent.path + '/' + id;
}
const oldNode = this.findNode(oldNodePath);
if (oldNode !== null) {
oldNode.data = data;
oldNode.domNode = domNode;
return oldNode;
}
const node = new TreeNode(id, data, domNode, parent);
if (parent === this.rootNode) {
node.parentNode = null;
}
if (parent !== null && parent !== undefined)
parent.children.push(node);
return node;
}
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;
}
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;
}
}
node_cnt += 1;
item = item.hasParent() ? item.parent() : null;
} while (item);
return result;
}
/*
@@ -164,7 +440,8 @@ export class Tree {
}
}
prepareDraggable(data, item) {
handleDraggable(e, item) {
let data = item.getMetadata('data');
let dropDetailsFunc = this.getDraggable(data._type);
if(dropDetailsFunc != null) {
@@ -173,265 +450,67 @@ export class Tree {
* 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);
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);
}
});
}
}
addNewNode(id, data, domNode, parentPath) {
const parent = this.findNode(parentPath);
return this.createOrUpdateNode(id, data, parent, domNode);
}
findNode(path) {
if (path === null || path === undefined || path.length === 0) {
return this.rootNode;
}
return findInTree(this.rootNode, path.join('.'));
}
findNodeWithToggle(path) {
let tree = this;
if(path == null || !Array.isArray(path)) {
return Promise.reject();
}
path = path.join('.');
let onCorrectPath = function(matchPath) {
return (matchPath !== undefined && path !== undefined
&& (path.startsWith(matchPath + '.') || path === matchPath));
};
return (function findInNode(currentNode) {
return new Promise((resolve, reject)=>{
if (path === null || path === undefined || path.length === 0) {
resolve(null);
}
/* No point in checking the children if
* the path for currentNode itself is not matching
*/
if (currentNode.path !== undefined && !onCorrectPath(currentNode.path)) {
reject(null);
} else if (currentNode.path === path) {
resolve(currentNode);
} else {
currentNode.open(tree, true)
.then(()=>{
for (let i = 0, length = currentNode.children.length; i < length; i++) {
let childNode = currentNode.children[i];
if(onCorrectPath(childNode.path)) {
resolve(findInNode(childNode));
return;
}
}
reject(null);
})
.catch(()=>{
reject(null);
});
}
});
})(this.rootNode);
}
findNodeByDomElement(domElement) {
const path = this.translateTreeNodeIdFromACITree(domElement);
if(!path || !path[0]) {
return undefined;
}
return this.findNode(path);
}
selected() {
return this.aciTreeApi.selected();
}
/* 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]);
}
}
createOrUpdateNode(id, data, parent, domNode) {
let oldNodePath = [id];
if(parent !== null && parent !== undefined) {
oldNodePath = [parent.path, id];
}
const oldNode = this.findNode(oldNodePath);
if (oldNode !== null) {
oldNode.data = data;
oldNode.domNode = domNode;
return oldNode;
}
const node = new TreeNode(id, data, domNode, parent);
if (parent === this.rootNode) {
node.parentNode = null;
}
if (parent !== null && parent !== undefined)
parent.children.push(node);
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 = [];
}
}
/**
* 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);
}
}
}
}.bind(this));
this.aciTreeApi = $treeJQuery.aciTree('api');
/* 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);
}
/**
* 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
*/
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);
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

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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';

View File

@@ -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,8 +391,7 @@ define([
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'];
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
return _.isUndefined(s) ? false : s.version >= 110000;
},
@@ -466,8 +465,7 @@ define([
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'];
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
return _.isUndefined(s) ? false : s.version >= 110000;
},
@@ -518,8 +516,7 @@ define([
disabled: function(m) {
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'];
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
if (!_.isUndefined(s) && s.version >= 120000)
return true;
@@ -632,7 +629,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 +647,7 @@ define([
label: gettext('Backup...'),
icon: 'fa fa-save',
enable: supportedNodes.enabled.bind(
null, pgBrowser.treeMenu, menuUtils.backupSupportedNodes
null, pgBrowser.tree, menuUtils.backupSupportedNodes
),
});
}

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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') {

View File

@@ -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,

View File

@@ -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(

View File

@@ -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;

View File

@@ -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() {
@@ -505,9 +505,8 @@ define([
callback: function(e) {
if (e.button['data-btn-name'] === 'ok') {
var n = this.settings['pg_node'],
itemArr = this.settings['pg_item'],
treeData = n.getTreeNodeHierarchy.apply(n, [itemArr]);
var itemArr = this.settings['pg_item'],
treeData = pgBrowser.tree.getTreeNodeHierarchy(itemArr);
this.view.model.set({
'database': treeData.database._label,
@@ -589,9 +588,8 @@ define([
this.__internal.buttons[1].element.disabled = true;
var $container = $('<div class=\'import_dlg\'></div>'),
n = this.settings.pg_node,
itemArr = this.settings.pg_item,
treeData = n.getTreeNodeHierarchy.apply(n, [itemArr]),
treeData = pgBrowser.tree.getTreeNodeHierarchy(itemArr),
newModel = new ImportExportModel({}, {
node_info: treeData,
}),

View File

@@ -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(
@@ -304,7 +303,7 @@ define([
// Callback functions when click on the buttons of the Alertify dialogs
callback: function(e) {
var sel_item = pgBrowser.tree.selected(),
itemData = sel_item && sel_item.length == 1 ? pgBrowser.tree.itemData(sel_item) : undefined,
itemData = sel_item ? pgBrowser.tree.itemData(sel_item) : undefined,
sel_node = itemData && pgBrowser.Nodes[itemData._type];
if (e.button.element.name == 'dialog_help' || e.button.element.name == 'object_help') {
@@ -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(sel_item);
if (node_hierarchy.schema != undefined) {
schema = node_hierarchy.schema._label;
@@ -409,13 +408,13 @@ define([
var $container = $('<div class=\'maintenance_dlg\'></div>');
var tree = pgBrowser.tree,
sel_item = tree.selected(),
itemInfo = sel_item && sel_item.length == 1 ? tree.itemData(sel_item) : undefined,
itemInfo = sel_item ? tree.itemData(sel_item) : undefined,
nodeData = itemInfo && pgBrowser.Nodes[itemInfo._type];
if (!itemInfo)
return;
var treeData = nodeData.getTreeNodeHierarchy.apply(nodeData, [sel_item]);
var treeData = tree.getTreeNodeHierarchy(sel_item);
var newModel = new MaintenanceModel({}, {
node_info: treeData,

View File

@@ -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.getTreeNodeHierarchy(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.`;

View File

@@ -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
),
});
}

View File

@@ -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];

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;