///////////////////////////////////////////////////////////// // // 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( { params.error ? : } ); } }