pgadmin4/web/pgadmin/tools/psql/static/js/PsqlModule.js

246 lines
7.8 KiB
JavaScript

/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import { getRandomInt, hasBinariesConfiguration } from 'sources/utils';
import { retrieveAncestorOfTypeServer } from 'sources/tree/tree_utils';
import { generateTitle } from 'tools/sqleditor/static/js/sqleditor_title';
import { AllPermissionTypes, BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/constants';
import usePreferences,{ listenPreferenceBroadcast } from '../../../../preferences/static/js/store';
import 'pgadmin.browser.keyboard';
import pgWindow from 'sources/window';
import pgAdmin from 'sources/pgadmin';
import pgBrowser from 'pgadmin.browser';
import PsqlComponent from './components/PsqlComponent';
import { PgAdminProvider } from '../../../../static/js/PgAdminProvider';
import getApiInstance from '../../../../static/js/api_instance';
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';
import Theme from '../../../../static/js/Theme';
import { NotifierProvider } from '../../../../static/js/helpers/Notifier';
import ModalProvider from '../../../../static/js/helpers/ModalProvider';
import * as csrfToken from 'sources/csrf';
import { ApplicationStateProvider } from '../../../../settings/static/ApplicationStateProvider';
import ToolErrorView from '../../../../static/js/ToolErrorView';
import React from 'react';
import ReactDOM from 'react-dom/client';
export default class Psql {
static instance;
static getInstance(...args) {
if (!Psql.instance) {
Psql.instance = new Psql(...args);
}
return Psql.instance;
}
constructor(pgAdmin, pgBrowser) {
this.pgAdmin = pgAdmin;
this.pgBrowser = pgBrowser;
this.api = getApiInstance();
}
/* Enable/disable PSQL tool menu in tools based
* on node selected. if selected node is present
* in unsupported_nodes, menu will be disabled
* otherwise enabled.
*/
psqlToolEnabled(obj) {
let isEnabled = (() => {
if (!_.isUndefined(obj) && !_.isNull(obj) && pgAdmin['enable_psql']) {
if (_.indexOf(pgAdmin.unsupported_nodes, obj._type) == -1) {
if (obj._type == 'database' && obj.allowConn) {
return true;
} else if (obj._type != 'database') {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
})();
return isEnabled;
}
init() {
if (this.initialized)
return;
this.initialized = true;
csrfToken.setPGCSRFToken(pgAdmin.csrf_token_header, pgAdmin.csrf_token);
// Define the nodes on which the menus to be appear
let menus = [{
name: 'psql',
module: this,
applies: ['tools'],
callback: 'openPsqlTool',
enable: this.psqlToolEnabled,
priority: 1,
label: gettext('PSQL Tool'),
data:{
applies: 'tools',
data_disabled: gettext('Please select a database from the object explorer to access Pql Tool.'),
},
permission: AllPermissionTypes.TOOLS_PSQL_TOOL,
}];
this.enable_psql_tool = pgAdmin['enable_psql'];
if(pgAdmin['enable_psql']) {
pgBrowser.add_menus(menus);
}
}
openPsqlTool(_data, treeIdentifier, connectionInfo=null) {
let parentData = null;
let panelTitle = '';
if (connectionInfo){
parentData = {
server_group: {
_id: connectionInfo.sgid || 0
},
server: {
_id: connectionInfo.sid,
server_type: connectionInfo.server_type,
label: connectionInfo.server_name,
user: {
name: connectionInfo.user
}
},
database: {
_id: connectionInfo.did,
_label: connectionInfo.db
},
schema: {
_id: connectionInfo.scid || null,
},
table: {
_id: connectionInfo.tid || null,
}
};
}else{
const serverInformation = retrieveAncestorOfTypeServer(pgBrowser, treeIdentifier, gettext('PSQL Error'));
if (!hasBinariesConfiguration(pgBrowser, serverInformation)) {
return;
}
const node = pgBrowser.tree.findNodeByDomElement(treeIdentifier);
if (node === undefined || !node.getData()) {
pgAdmin.Browser.notifier.alert(
gettext('PSQL Error'),
gettext('No object selected.')
);
return;
}
parentData = pgBrowser.tree.getTreeNodeHierarchy(treeIdentifier);
if(_.isUndefined(parentData.server)) {
pgAdmin.Browser.notifier.alert(
gettext('PSQL Error'),
gettext('Please select a server/database object.')
);
return;
}
}
const transId = getRandomInt(1, 9999999);
// Set psql tab title as per prefrences setting.
let title_data = {
'database': parentData.database ? _.unescape(parentData.database._label) : 'postgres' ,
'username': parentData.server.user.name,
'server': parentData.server.label,
'type': 'psql_tool',
};
let tab_title_placeholder = usePreferences.getState().getPreferencesForModule('browser').psql_tab_title_placeholder;
panelTitle = generateTitle(tab_title_placeholder, title_data);
const [panelUrl, db_label] = this.getPanelUrls(transId, parentData);
const open_new_tab = usePreferences.getState().getPreferencesForModule('browser').new_browser_tab_open;
pgAdmin.Browser.Events.trigger(
'pgadmin:tool:show',
`${BROWSER_PANELS.PSQL_TOOL}_${transId}`,
panelUrl,
{title: panelTitle, db: db_label, server_name: parentData.server.label, 'user': parentData.server.user.name },
{title: panelTitle, icon: 'pg-font-icon icon-terminal', manualClose: false, renamable: true},
Boolean(open_new_tab?.includes('psql_tool'))
);
return true;
}
getPanelUrls(transId, pData) {
let openUrl = url_for('psql.panel', {
trans_id: transId,
});
const misc_preferences = usePreferences.getState().getPreferencesForModule('misc');
let theme = misc_preferences.theme;
openUrl += `?sgid=${pData.server_group._id}`
+`&sid=${pData.server._id}`
+`&did=${pData.database._id}`
+`&server_type=${pData.server.server_type}`
+ `&theme=${theme}`;
if(pData.database?._id) {
openUrl += `&db=${encodeURIComponent(pData.database._label)}`;
} else {
openUrl += `&db=${''}`;
}
return [openUrl, pData.database._label];
}
async loadComponent(container, params) {
let panelDocker = pgWindow.pgAdmin.Browser.docker.psql_workspace;
if (pgWindow.pgAdmin.Browser.docker.currentWorkspace == WORKSPACES.DEFAULT) {
panelDocker = pgWindow.pgAdmin.Browser.docker.default_workspace;
}
pgAdmin.Browser.keyboardNavigation.init();
await listenPreferenceBroadcast();
const root = ReactDOM.createRoot(container);
root.render(
<Theme>
<PgAdminProvider value={pgAdmin}>
<ApplicationStateProvider>
<ModalProvider>
<NotifierProvider pgAdmin={pgAdmin} pgWindow={pgWindow} />
{ params.error ?
<ToolErrorView
error={params.error}
panelId={`${BROWSER_PANELS.PSQL_TOOL}_${params.trans_id}`}
panelDocker={panelDocker}
/> :
<PsqlComponent
params={params}
pgAdmin={pgAdmin}
panelId={`${BROWSER_PANELS.PSQL_TOOL}_${params.trans_id}`}
panelDocker={panelDocker}
/>
}
</ModalProvider>
</ApplicationStateProvider>
</PgAdminProvider>
</Theme>
);
}
}