Add an object menu option to disconnect all server and database connections. #1984

This commit is contained in:
Pravesh Sharma 2024-11-06 15:52:31 +05:30 committed by GitHub
parent 6cb71c9ae4
commit b51eef12b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 203 additions and 95 deletions

View File

@ -109,6 +109,13 @@ define('pgadmin.node.database', [
enable : 'is_connected',data: { enable : 'is_connected',data: {
data_disabled: gettext('Selected database is already disconnected.'), 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, name: 'generate_erd', node: 'database', module: this,
applies: ['object', 'context'], callback: 'generate_erd', 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: { callbacks: {
/* Connect the database */ /* Connect the database */
connect_database: function(args){ connect_database: function(args){
@ -230,45 +245,31 @@ define('pgadmin.node.database', [
d = i ? t.itemData(i) : undefined; d = i ? t.itemData(i) : undefined;
if (d) { if (d) {
pgAdmin.Browser.notifier.confirm( disconnect_from_database(obj, d, t, i, true);
gettext('Disconnect from database'),
gettext('Are you sure you want to disconnect from database - %s?', d.label),
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}); return false;
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);
});
}, },
function() { return true; }
disconnect_all_databases: function(args, item) {
let children = item.children ?? [],
obj = this,
t = pgBrowser.tree;
if (children) {
pgAdmin.Browser.notifier.confirm(
gettext('Disconnect from all databases'),
gettext('Are you sure you want to disconnect from all databases?'),
function() {
_.forEach(children, function(child) {
let data = pgAdmin.Browser.tree.getData(child);
if (data.connected && data.canDisconn) {
disconnect_from_database(obj, data, t, child, false);
}
});
t.deselect(item);
},
function() { return true;},
); );
} }
@ -502,6 +503,63 @@ define('pgadmin.node.database', [
error, obj, data, tree, item, wasConnected 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 = `<span class='text-muted'>[Disconnecting...]</span> ${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();
}
}; };
} }

View File

@ -78,6 +78,11 @@ define('pgadmin.node.server', [
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'register', priority: 1, label: gettext('Server...'), category: 'register', priority: 1, label: gettext('Server...'),
data: {action: 'create'}, enable: 'canCreate', 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, name: 'create_server', node: 'server', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
@ -200,6 +205,9 @@ define('pgadmin.node.server', [
node?.connected && node?.user?.is_superuser node?.connected && node?.user?.is_superuser
&& node?.in_recovery && node?.wal_pause); && node?.in_recovery && node?.wal_pause);
}, },
can_disconnect_all: function(node, item) {
return _.some(item.children, (child) => pgAdmin.Browser.tree.getData(child).connected);
},
callbacks: { callbacks: {
/* Connect the server */ /* Connect the server */
connect_server: function(args){ connect_server: function(args){
@ -215,73 +223,40 @@ define('pgadmin.node.server', [
return false; return false;
}, },
/* Disconnect the server */ /* Disconnect the server */
disconnect_server: function(args, notify) { disconnect_server: function(args) {
let input = args || {}, let input = args || {},
obj = this, obj = this,
t = pgBrowser.tree, t = pgBrowser.tree,
i = 'item' in input ? input.item : t.selected(), i = 'item' in input ? input.item : t.selected(),
d = i ? t.itemData(i) : undefined; d = i ? t.itemData(i) : undefined;
if (d) { if (d) {
notify = notify || _.isUndefined(notify) || _.isNull(notify); disconnect_from_server(obj, d, t, i, true);
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}); return false;
obj.callbacks.refresh.apply(obj, [null, i]); },
setTimeout(() => { disconnect_all_servers: function(args, item) {
t.close(i); let children = item.children ?? [],
}, 10); obj = this,
if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) { t = pgBrowser.tree;
delete pgBrowser.serverInfo[d._id]; if (children) {
}
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( pgAdmin.Browser.notifier.confirm(
gettext('Disconnect from server'), gettext('Disconnect from all servers'),
gettext('Are you sure you want to disconnect from the server %s?', d.label), gettext('Are you sure you want to disconnect from all servers?'),
function() { disconnect(); }, 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;}, function() { return true;},
); );
} else {
disconnect();
} }
}
return false; return false;
}, },
/* Connect the server (if not connected), before opening this node */ /* Connect the server (if not connected), before opening this node */
@ -819,6 +794,78 @@ define('pgadmin.node.server', [
pgAdmin.Browser.notifier.pgRespErrorNotify(error); 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 = `<span class='text-muted'>[Disconnecting...]</span> ${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']; return pgBrowser.Nodes['server'];

View File

@ -24,5 +24,8 @@ export default function pgadminOverride(theme) {
'&.icon-terminal': { '&.icon-terminal': {
fontSize: '1.3rem !important', fontSize: '1.3rem !important',
} }
},
'.text-muted': {
color: theme.otherVars.textMuted
} }
};} };}

View File

@ -475,7 +475,7 @@ export class Tree {
let idx = 0; let idx = 0;
let node_cnt = 0; let node_cnt = 0;
let result = {}; let result = {};
if (identifier === undefined) return; if (!identifier) return;
let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path); let item = TreeNode.prototype.isPrototypeOf(identifier) ? identifier : this.findNode(identifier.path);
if (!item) return; if (!item) return;
do { do {