diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
index d4c1ce592..2f5b4b739 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js
@@ -109,6 +109,13 @@ define('pgadmin.node.database', [
enable : 'is_connected',data: {
data_disabled: gettext('Selected database is already disconnected.'),
},
+ },{
+ name: 'disconnect_all_databases', node: 'coll-database', module: this,
+ applies: ['object', 'context'], callback: 'disconnect_all_databases',
+ category: 'disconnect', priority: 5, label: gettext('Disconnect from all databases'),
+ enable: 'can_disconnect',data: {
+ data_disabled: gettext('All the databases are already disconnected.'),
+ },
},{
name: 'generate_erd', node: 'database', module: this,
applies: ['object', 'context'], callback: 'generate_erd',
@@ -207,6 +214,14 @@ define('pgadmin.node.database', [
}
}
},
+ can_disconnect: function(node, item) {
+ return _.some(item.children, (child) => {
+ let data = pgAdmin.Browser.tree.getData(child),
+ {connected, canDisconn} = data;
+ return connected && canDisconn;
+ }
+ );
+ },
callbacks: {
/* Connect the database */
connect_database: function(args){
@@ -230,45 +245,31 @@ define('pgadmin.node.database', [
d = i ? t.itemData(i) : undefined;
if (d) {
+ disconnect_from_database(obj, d, t, i, true);
+ }
+
+ return false;
+ },
+
+ disconnect_all_databases: function(args, item) {
+ let children = item.children ?? [],
+ obj = this,
+ t = pgBrowser.tree;
+
+ if (children) {
pgAdmin.Browser.notifier.confirm(
- gettext('Disconnect from database'),
- gettext('Are you sure you want to disconnect from database - %s?', d.label),
+ gettext('Disconnect from all databases'),
+ gettext('Are you sure you want to disconnect from all databases?'),
function() {
- let data = d;
- getApiInstance().delete(
- obj.generate_url(i, 'connect', d, true),
- ).then(({data: res})=> {
- if (res.success == 1) {
- let prv_i = t.parent(i);
- if(res.data.info_prefix) {
- res.info = `${_.escape(res.data.info_prefix)} - ${res.info}`;
- }
- pgAdmin.Browser.notifier.success(res.info);
- t.removeIcon(i);
- data.connected = false;
- data.icon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected';
-
- t.addIcon(i, {icon: data.icon});
- t.unload(i);
- pgBrowser.Events.trigger('pgadmin:browser:tree:update-tree-state', i);
- setTimeout(function() {
- t.select(prv_i);
- }, 10);
-
- } else {
- try {
- pgAdmin.Browser.notifier.error(res.errormsg);
- } catch (e) {
- console.warn(e.stack || e);
- }
- t.unload(i);
+ _.forEach(children, function(child) {
+ let data = pgAdmin.Browser.tree.getData(child);
+ if (data.connected && data.canDisconn) {
+ disconnect_from_database(obj, data, t, child, false);
}
- }).catch(function(error) {
- pgAdmin.Browser.notifier.pgRespErrorNotify(error);
- t.unload(i);
});
+ t.deselect(item);
},
- function() { return true; }
+ function() { return true;},
);
}
@@ -502,6 +503,63 @@ define('pgadmin.node.database', [
error, obj, data, tree, item, wasConnected
);
});
+ },
+ disconnect_from_database = function(obj, data, tree, item, notify=false) {
+ let d = data,
+ t = tree,
+ i = item,
+ label = data.label;
+ let disconnect = function() {
+ d.label = `[Disconnecting...] ${label}`;
+ t.setLabel(i,{label:d.label});
+ t.close(i);
+ let data = d;
+ getApiInstance().delete(
+ obj.generate_url(i, 'connect', d, true),
+ ).then(({data: res})=> {
+ if (res.success == 1) {
+ let prv_i = t.parent(i);
+ if(res.data.info_prefix) {
+ res.info = `${_.escape(res.data.info_prefix)} - ${res.info}`;
+ }
+ pgAdmin.Browser.notifier.success(res.info);
+ t.removeIcon(i);
+ data.connected = false;
+ data.icon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected';
+ d.label = label;
+ t.setLabel(i, {label});
+ t.addIcon(i, {icon: data.icon});
+ t.unload(i);
+ pgBrowser.Events.trigger('pgadmin:browser:tree:update-tree-state', i);
+ setTimeout(function() {
+ t.select(prv_i);
+ }, 10);
+
+ } else {
+ try {
+ pgAdmin.Browser.notifier.error(res.errormsg);
+ } catch (e) {
+ console.warn(e.stack || e);
+ }
+ t.unload(i);
+ }
+ }).catch(function(error) {
+ pgAdmin.Browser.notifier.pgRespErrorNotify(error);
+ t.unload(i);
+ });
+ };
+ if (notify) {
+ pgAdmin.Browser.notifier.confirm(
+ gettext('Disconnect from database'),
+ gettext('Are you sure you want to disconnect from database - %s?', d.label),
+ function() {
+ disconnect();
+ },
+ function() { return true; }
+ );
+ } else {
+ disconnect();
+ }
};
}
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js
index 0c7f5748a..b100965cf 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/server.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js
@@ -78,6 +78,11 @@ define('pgadmin.node.server', [
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'register', priority: 1, label: gettext('Server...'),
data: {action: 'create'}, enable: 'canCreate',
+ },{
+ name: 'disconnect_all_servers', node: 'server_group', module: this,
+ applies: ['object','context'], callback: 'disconnect_all_servers',
+ priority: 5, label: gettext('Disconnect from all servers'),
+ data:{action: 'disconnect_all'}, enable: 'can_disconnect_all'
},{
name: 'create_server', node: 'server', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
@@ -200,6 +205,9 @@ define('pgadmin.node.server', [
node?.connected && node?.user?.is_superuser
&& node?.in_recovery && node?.wal_pause);
},
+ can_disconnect_all: function(node, item) {
+ return _.some(item.children, (child) => pgAdmin.Browser.tree.getData(child).connected);
+ },
callbacks: {
/* Connect the server */
connect_server: function(args){
@@ -215,73 +223,40 @@ define('pgadmin.node.server', [
return false;
},
/* Disconnect the server */
- disconnect_server: function(args, notify) {
+ disconnect_server: function(args) {
let input = args || {},
obj = this,
t = pgBrowser.tree,
i = 'item' in input ? input.item : t.selected(),
d = i ? t.itemData(i) : undefined;
-
if (d) {
- notify = notify || _.isUndefined(notify) || _.isNull(notify);
-
- let disconnect = function() {
- getApiInstance().delete(
- obj.generate_url(i, 'connect', d, true),
- ).then(({data: res})=> {
- if (res.success == 1) {
- pgAdmin.Browser.notifier.success(res.info);
- d = t.itemData(i);
- t.removeIcon(i);
- d.connected = false;
- // Update server tree node data after server diconnected.
- t.update(i,d);
-
- // Generate the event that server is disconnected
- pgBrowser.Events.trigger(
- 'pgadmin:server:disconnect',
- {item: i, data: d}, false
- );
- if (d.shared && pgAdmin.server_mode == 'True'){
- d.icon = 'icon-shared-server-not-connected';
- }else{
- d.icon = 'icon-server-not-connected';
- }
- t.addIcon(i, {icon: d.icon});
- obj.callbacks.refresh.apply(obj, [null, i]);
- setTimeout(() => {
- t.close(i);
- }, 10);
- if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
- delete pgBrowser.serverInfo[d._id];
- }
- else {
- try {
- pgAdmin.Browser.notifier.error(res.errormsg);
- } catch (e) {
- console.warn(e.stack || e);
- }
- t.unload(i);
- }
- }
- }).catch(function(error) {
- pgAdmin.Browser.notifier.pgRespErrorNotify(error);
- t.unload(i);
- });
- };
-
- if (notify) {
- pgAdmin.Browser.notifier.confirm(
- gettext('Disconnect from server'),
- gettext('Are you sure you want to disconnect from the server %s?', d.label),
- function() { disconnect(); },
- function() { return true;},
- );
- } else {
- disconnect();
- }
+ disconnect_from_server(obj, d, t, i, true);
+ }
+ return false;
+ },
+ disconnect_all_servers: function(args, item) {
+ let children = item.children ?? [],
+ obj = this,
+ t = pgBrowser.tree;
+ if (children) {
+ pgAdmin.Browser.notifier.confirm(
+ gettext('Disconnect from all servers'),
+ gettext('Are you sure you want to disconnect from all servers?'),
+ function() {
+ _.forEach(children, function(child) {
+ let data = pgAdmin.Browser.tree.getData(child);
+ if (data.connected) {
+ disconnect_from_server(obj, data, t, child, false);
+ }
+ });
+ t.deselect(item);
+ setTimeout(() => {
+ t.select(item);
+ }, 100);
+ },
+ function() { return true;},
+ );
}
-
return false;
},
/* Connect the server (if not connected), before opening this node */
@@ -819,6 +794,78 @@ define('pgadmin.node.server', [
pgAdmin.Browser.notifier.pgRespErrorNotify(error);
});
};
+ let disconnect_from_server = async function(obj, data, tree, item, notify=false) {
+ let d = data,
+ i = item,
+ t = tree,
+ label = data.label;
+
+ let disconnect = function() {
+ d.label = `[Disconnecting...] ${label}`;
+ t.setLabel(i,{label:d.label});
+ t.close(i);
+ getApiInstance().delete(
+ obj.generate_url(i, 'connect', d, true),
+ ).then(({data: res})=> {
+ if (res.success == 1) {
+ if (notify) {
+ pgAdmin.Browser.notifier.success(res.info);
+ } else {
+ pgAdmin.Browser.notifier.success(`${label} - ${res.info}`);
+ }
+ d = t.itemData(i);
+ t.removeIcon(i);
+ d.connected = false;
+ d.label = label;
+ t.setLabel(i, {label});
+ // Update server tree node data after server diconnected.
+ t.update(i,d);
+ // Generate the event that server is disconnected
+ pgBrowser.Events.trigger(
+ 'pgadmin:server:disconnect',
+ {item: i, data: d}, false
+ );
+ if (d.shared && pgAdmin.server_mode == 'True'){
+ d.icon = 'icon-shared-server-not-connected';
+ }else{
+ d.icon = 'icon-server-not-connected';
+ }
+ t.addIcon(i, {icon: d.icon});
+ obj.callbacks.refresh.apply(obj, [null, i]);
+ setTimeout(() => {
+ t.close(i);
+ }, 10);
+ if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
+ delete pgBrowser.serverInfo[d._id];
+ }
+ else {
+ try {
+ pgAdmin.Browser.notifier.error(res.errormsg);
+ } catch (e) {
+ console.warn(e.stack || e);
+ }
+ t.setLabel(i, {label});
+ t.unload(i);
+ }
+ }
+ }).catch(function(error) {
+ pgAdmin.Browser.notifier.pgRespErrorNotify(error);
+ t.setLabel(i, {label});
+ t.unload(i);
+ });
+ };
+
+ if (notify) {
+ pgAdmin.Browser.notifier.confirm(
+ gettext('Disconnect from server'),
+ gettext('Are you sure you want to disconnect from the server %s?', label),
+ function() { disconnect(); },
+ function() { return true;},
+ );
+ } else {
+ disconnect();
+ }
+ };
}
return pgBrowser.Nodes['server'];
diff --git a/web/pgadmin/static/js/Theme/overrides/pgadmin.classes.override.js b/web/pgadmin/static/js/Theme/overrides/pgadmin.classes.override.js
index 8e8278525..52980017d 100644
--- a/web/pgadmin/static/js/Theme/overrides/pgadmin.classes.override.js
+++ b/web/pgadmin/static/js/Theme/overrides/pgadmin.classes.override.js
@@ -24,5 +24,8 @@ export default function pgadminOverride(theme) {
'&.icon-terminal': {
fontSize: '1.3rem !important',
}
+ },
+ '.text-muted': {
+ color: theme.otherVars.textMuted
}
};}
diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js
index bb13b7450..82dee8f0c 100644
--- a/web/pgadmin/static/js/tree/tree.js
+++ b/web/pgadmin/static/js/tree/tree.js
@@ -475,7 +475,7 @@ export class Tree {
let idx = 0;
let node_cnt = 0;
let result = {};
- if (identifier === undefined) return;
+ if (!identifier) return;
let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path);
if (!item) return;
do {