Workspace Layout Update - Enhanced Query Tool and PSQL Behaviour:

With these changes, the Query Tool and PSQL tabs will now open in the same active workspace where the action is initiated.
This commit is contained in:
Akshay Joshi
2025-02-11 15:36:03 +05:30
parent 2c37ff2893
commit eb7c3ef361
7 changed files with 61 additions and 7 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -286,6 +286,11 @@ Expand the *Miscellaneous* node to specify miscellaneous display preferences.
areas for the Query Tool, PSQL, and Schema Diff tools. 'Workspace' layout is areas for the Query Tool, PSQL, and Schema Diff tools. 'Workspace' layout is
the default layout, but user can change it to 'Classic'. the default layout, but user can change it to 'Classic'.
* When the *Open the Query Tool/PSQL in their respective workspaces* switch is set to *True*
then all Query Tool/PSQL tabs will open in their respective workspaces. By default,
this setting is False, meaning that Query Tool/PSQL tabs will open in the currently
active workspace (either the default or the workspace selected at the time of opening).
* Use the *Themes* drop-down listbox to select the theme for pgAdmin. You'll also get a preview just below the * Use the *Themes* drop-down listbox to select the theme for pgAdmin. You'll also get a preview just below the
drop down. You can also submit your own themes, drop down. You can also submit your own themes,
check `here <https://github.com/pgadmin-org/pgadmin4/blob/master/README.md>`_ how. check `here <https://github.com/pgadmin-org/pgadmin4/blob/master/README.md>`_ how.

View File

@@ -105,6 +105,20 @@ class MiscModule(PgAdminModule):
'Diff tools.' 'Diff tools.'
) )
) )
self.preference.register(
'user_interface', 'open_in_res_workspace',
gettext("Open the Query Tool/PSQL in their respective workspaces"),
'boolean', False,
category_label=PREF_LABEL_USER_INTERFACE,
help_str=gettext(
'This setting applies only when the layout is set to '
'Workspace Layout. When set to True, all Query Tool/PSQL '
'tabs will open in their respective workspaces. By default, '
'this setting is False, meaning that Query Tool/PSQL tabs '
'will open in the currently active workspace (either the '
'default or the workspace selected at the time of opening)'
)
)
def get_exposed_url_endpoints(self): def get_exposed_url_endpoints(self):
""" """

View File

@@ -9,7 +9,7 @@
import React, { useContext, useMemo, useRef, useState } from 'react'; import React, { useContext, useMemo, useRef, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { WORKSPACES } from '../../../../browser/static/js/constants'; import { BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/constants';
import { usePgAdmin } from '../../../../static/js/PgAdminProvider'; import { usePgAdmin } from '../../../../static/js/PgAdminProvider';
import usePreferences from '../../../../preferences/static/js/store'; import usePreferences from '../../../../preferences/static/js/store';
import { config } from './config'; import { config } from './config';
@@ -23,8 +23,11 @@ export function WorkspaceProvider({children}) {
const [currentWorkspace, setCurrentWorkspace] = useState(WORKSPACES.DEFAULT); const [currentWorkspace, setCurrentWorkspace] = useState(WORKSPACES.DEFAULT);
const lastSelectedTreeItem = useRef(); const lastSelectedTreeItem = useRef();
const isClassic = (usePreferences()?.getPreferencesForModule('misc')?.layout ?? 'classic') == 'classic'; const isClassic = (usePreferences()?.getPreferencesForModule('misc')?.layout ?? 'classic') == 'classic';
const openInResWorkspace = usePreferences()?.getPreferencesForModule('misc')?.open_in_res_workspace && !isClassic;
pgAdmin.Browser.docker.currentWorkspace = WORKSPACES.DEFAULT; if (_.isUndefined(pgAdmin.Browser.docker.currentWorkspace)) {
pgAdmin.Browser.docker.currentWorkspace = WORKSPACES.DEFAULT;
}
/* In case of classic UI all workspace objects should point to the /* In case of classic UI all workspace objects should point to the
* the instance of the default layout. * the instance of the default layout.
*/ */
@@ -50,6 +53,14 @@ export function WorkspaceProvider({children}) {
workspace = WORKSPACES.DEFAULT; workspace = WORKSPACES.DEFAULT;
} }
// If the layout is Workspace layout and 'Open the Query Tool/PSQL in their respective workspaces'
// is False then check the current workspace and set the workspace and docker accordingly.
if (!openInResWorkspace && pgAdmin.Browser.docker.currentWorkspace == WORKSPACES.DEFAULT &&
(panelId.indexOf(BROWSER_PANELS.QUERY_TOOL) >= 0 || panelId.indexOf(BROWSER_PANELS.PSQL_TOOL) >= 0)) {
docker = pgAdmin.Browser.docker.default_workspace;
workspace = WORKSPACES.DEFAULT;
}
// Call onWorkspaceChange to enable or disable the menu based on the selected workspace. // Call onWorkspaceChange to enable or disable the menu based on the selected workspace.
changeWorkspace(workspace); changeWorkspace(workspace);
return {docker: docker, focus: ()=>changeWorkspace(workspace)}; return {docker: docker, focus: ()=>changeWorkspace(workspace)};

View File

@@ -299,6 +299,8 @@ export default function PreferencesComponent({ ...props }) {
preferencesValues[element.id] = { 'warning': _val[0], 'alert': _val[1] }; preferencesValues[element.id] = { 'warning': _val[0], 'alert': _val[1] };
} else if (subNode.label == gettext('Results grid') && node.label == gettext('Query Tool')) { } else if (subNode.label == gettext('Results grid') && node.label == gettext('Query Tool')) {
setResultsOptions(element, subNode, preferencesValues, type); setResultsOptions(element, subNode, preferencesValues, type);
} else if (subNode.label == gettext('User Interface') && node.label == gettext('Miscellaneous')) {
setWorkspaceOptions(element, subNode, preferencesValues, type);
} else { } else {
element.type = type; element.type = type;
preferencesValues[element.id] = element.value; preferencesValues[element.id] = element.value;
@@ -329,6 +331,23 @@ export default function PreferencesComponent({ ...props }) {
preferencesValues[element.id] = element.value; preferencesValues[element.id] = element.value;
} }
function setWorkspaceOptions(element, subNode, preferencesValues, type) {
if (element.name== 'open_in_res_workspace') {
let layout_control_id = null;
subNode.preferences.forEach((_el) => {
if(_el.name == 'layout') {
layout_control_id = _el.id;
}
});
element.disabled = (state) => {
return state[layout_control_id] != 'workspace';
};
}
element.type = type;
preferencesValues[element.id] = element.value;
}
function setThemesOptions(element) { function setThemesOptions(element) {
if (element.name == 'theme') { if (element.name == 'theme') {
element.type = 'theme'; element.type = 'theme';

View File

@@ -80,16 +80,16 @@ let defaultLayout = {
mode: 'horizontal', mode: 'horizontal',
children: [ children: [
{ {
size: 20, size: 10,
tabs: [ tabs: [
LayoutDocker.getPanel({ LayoutDocker.getPanel({
id: BROWSER_PANELS.OBJECT_EXPLORER, title: gettext('Object Explorer'), id: BROWSER_PANELS.OBJECT_EXPLORER, title: gettext(''),
content: <ObjectExplorer />, group: 'object-explorer' content: <ObjectExplorer />, group: 'object-explorer'
}), }),
], ],
}, },
{ {
size: 80, size: 90,
id: BROWSER_PANELS.MAIN, id: BROWSER_PANELS.MAIN,
group: 'playground', group: 'playground',
tabs: defaultTabsData.map((t)=>LayoutDocker.getPanel(t)), tabs: defaultTabsData.map((t)=>LayoutDocker.getPanel(t)),

View File

@@ -23,7 +23,7 @@ import ReactDOM from 'react-dom/client';
import QueryToolComponent from './components/QueryToolComponent'; import QueryToolComponent from './components/QueryToolComponent';
import ModalProvider from '../../../../static/js/helpers/ModalProvider'; import ModalProvider from '../../../../static/js/helpers/ModalProvider';
import Theme from '../../../../static/js/Theme'; import Theme from '../../../../static/js/Theme';
import { BROWSER_PANELS } from '../../../../browser/static/js/constants'; import { BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/constants';
import { NotifierProvider } from '../../../../static/js/helpers/Notifier'; import { NotifierProvider } from '../../../../static/js/helpers/Notifier';
import usePreferences, { listenPreferenceBroadcast } from '../../../../preferences/static/js/store'; import usePreferences, { listenPreferenceBroadcast } from '../../../../preferences/static/js/store';
import { PgAdminProvider } from '../../../../static/js/PgAdminProvider'; import { PgAdminProvider } from '../../../../static/js/PgAdminProvider';
@@ -229,6 +229,11 @@ export default class SQLEditor {
} }
async loadComponent(container, params) { async loadComponent(container, params) {
let panelDocker = pgWindow.pgAdmin.Browser.docker.query_tool_workspace;
if (pgWindow.pgAdmin.Browser.docker.currentWorkspace == WORKSPACES.DEFAULT) {
panelDocker = pgWindow.pgAdmin.Browser.docker.default_workspace;
}
const selectedNodeInfo = params.selectedNodeInfo ? JSON.parse(_.unescape(params.selectedNodeInfo)) : params.selectedNodeInfo; const selectedNodeInfo = params.selectedNodeInfo ? JSON.parse(_.unescape(params.selectedNodeInfo)) : params.selectedNodeInfo;
pgAdmin.Browser.keyboardNavigation.init(); pgAdmin.Browser.keyboardNavigation.init();
await listenPreferenceBroadcast(); await listenPreferenceBroadcast();
@@ -238,7 +243,7 @@ export default class SQLEditor {
<PgAdminProvider value={pgAdmin}> <PgAdminProvider value={pgAdmin}>
<ModalProvider> <ModalProvider>
<NotifierProvider pgAdmin={pgAdmin} pgWindow={pgWindow} /> <NotifierProvider pgAdmin={pgAdmin} pgWindow={pgWindow} />
<QueryToolComponent params={params} pgWindow={pgWindow} pgAdmin={pgAdmin} qtPanelDocker={pgWindow.pgAdmin.Browser.docker.query_tool_workspace} <QueryToolComponent params={params} pgWindow={pgWindow} pgAdmin={pgAdmin} qtPanelDocker={panelDocker}
qtPanelId={`${BROWSER_PANELS.QUERY_TOOL}_${params.trans_id}`} selectedNodeInfo={selectedNodeInfo}/> qtPanelId={`${BROWSER_PANELS.QUERY_TOOL}_${params.trans_id}`} selectedNodeInfo={selectedNodeInfo}/>
</ModalProvider> </ModalProvider>
</PgAdminProvider> </PgAdminProvider>