diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py index c7d962a03ef..aba07383462 100644 --- a/web/pgadmin/browser/register_browser_preferences.py +++ b/web/pgadmin/browser/register_browser_preferences.py @@ -101,6 +101,17 @@ def register_browser_preferences(self): ) ) + self.preference.register( + 'display', 'show_server_color_indicator', + gettext("Show server color indicator in panel tabs?"), 'boolean', False, + category_label=PREF_LABEL_DISPLAY, + help_str=gettext( + 'If enabled, a colored circle indicator will be shown in panel ' + 'tabs (Query Tool, ERD Tool, etc.) matching the server\'s custom ' + 'background color.' + ) + ) + self.table_row_count_threshold = self.preference.register( 'properties', 'table_row_count_threshold', gettext("Count rows if estimated less than"), 'integer', 2000, diff --git a/web/pgadmin/static/js/helpers/Layout/index.jsx b/web/pgadmin/static/js/helpers/Layout/index.jsx index 506bbe1325f..35eaecf8c13 100644 --- a/web/pgadmin/static/js/helpers/Layout/index.jsx +++ b/web/pgadmin/static/js/helpers/Layout/index.jsx @@ -32,10 +32,15 @@ import { BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/consta export function TabTitle({id, closable, defaultInternal}) { const layoutDocker = React.useContext(LayoutDockerContext); const internal = layoutDocker?.find(id)?.internal ?? defaultInternal; + const showServerColorIndicator = usePreferences( + React.useCallback((state) => state.getPreferencesForModule('browser')?.show_server_color_indicator ?? false, []) + ); const [attrs, setAttrs] = useState({ icon: internal.icon, title: internal.title, tooltip: internal.tooltip ?? internal.title, + bgcolor: internal.bgcolor, + fgcolor: internal.fgcolor, }); const onContextMenu = useCallback((e)=>{ const g = layoutDocker.find(id)?.group??''; @@ -53,6 +58,8 @@ export function TabTitle({id, closable, defaultInternal}) { icon: internal.icon, title: internal.title, tooltip: internal.tooltip ?? internal.title, + bgcolor: internal.bgcolor, + fgcolor: internal.fgcolor, }); layoutDocker.saveLayout(); } @@ -64,6 +71,21 @@ export function TabTitle({id, closable, defaultInternal}) { return ( {attrs.icon && } + {showServerColorIndicator && attrs.bgcolor && !layoutDocker.isTabVisible(id) && ( + + )} {attrs.title} {closable && } size="xs" noBorder onClick={()=>{ layoutDocker.close(id); @@ -368,7 +390,7 @@ export class LayoutDocker { this.saveLayout(); } - static getPanel({icon, title, closable, tooltip, renamable, manualClose, ...attrs}) { + static getPanel({icon, title, closable, tooltip, renamable, manualClose, bgcolor, fgcolor, ...attrs}) { const internal = { icon: icon, title: title, @@ -376,6 +398,8 @@ export class LayoutDocker { closable: _.isUndefined(closable) ? manualClose : closable, renamable: renamable, manualClose: manualClose, + bgcolor: bgcolor, + fgcolor: fgcolor, }; return { cached: true, diff --git a/web/pgadmin/tools/debugger/static/js/DebuggerModule.js b/web/pgadmin/tools/debugger/static/js/DebuggerModule.js index 1aee8e981c2..0a93ac1a2bf 100644 --- a/web/pgadmin/tools/debugger/static/js/DebuggerModule.js +++ b/web/pgadmin/tools/debugger/static/js/DebuggerModule.js @@ -378,13 +378,23 @@ export default class DebuggerModule { let open_new_tab = browser_preferences.new_browser_tab_open; const db_label = self.checkDbNameChange(data, dbNode, newTreeInfo); let label = getAppropriateLabel(newTreeInfo); + + // Extract bgcolor and fgcolor from server icon if available + let bgcolor = null; + let fgcolor = null; + if (newTreeInfo?.server?.icon) { + const iconParts = newTreeInfo.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + pgAdmin.Browser.Events.trigger( 'pgadmin:tool:show', `${BROWSER_PANELS.DEBUGGER_TOOL}_${trans_id}`, url, null, {title: getDebuggerTitle(browser_preferences, label, newTreeInfo.schema.label, db_label, null, self.pgBrowser), - icon: 'fa fa-bug', manualClose: false, renamable: true}, + icon: 'fa fa-bug', manualClose: false, renamable: true, bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(open_new_tab?.includes('debugger')) ); }) @@ -527,13 +537,22 @@ export default class DebuggerModule { let label = getAppropriateLabel(treeInfo); + // Extract bgcolor and fgcolor from server icon if available + let bgcolor = null; + let fgcolor = null; + if (treeInfo?.server?.icon) { + const iconParts = treeInfo.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + pgAdmin.Browser.Events.trigger( 'pgadmin:tool:show', `${BROWSER_PANELS.DEBUGGER_TOOL}_${res.data.data.debuggerTransId}`, url, null, {title: getDebuggerTitle(browser_preferences, label, db_label, db_label, null, self.pgBrowser), - icon: 'fa fa-bug', manualClose: false, renamable: true}, + icon: 'fa fa-bug', manualClose: false, renamable: true, bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(open_new_tab?.includes('debugger')) ); }) diff --git a/web/pgadmin/tools/erd/static/js/ERDModule.js b/web/pgadmin/tools/erd/static/js/ERDModule.js index 2d051f5386b..5bdcb1c4f52 100644 --- a/web/pgadmin/tools/erd/static/js/ERDModule.js +++ b/web/pgadmin/tools/erd/static/js/ERDModule.js @@ -142,12 +142,21 @@ export default class ERDModule { const panelUrl = this.getPanelUrl(transId, parentData, gen); const open_new_tab = usePreferences.getState().getPreferencesForModule('browser').new_browser_tab_open; + // Extract bgcolor and fgcolor from server icon if available + let bgcolor = null; + let fgcolor = null; + if (parentData?.server?.icon) { + const iconParts = parentData.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + pgAdmin.Browser.Events.trigger( 'pgadmin:tool:show', `${BROWSER_PANELS.ERD_TOOL}_${transId}`, panelUrl, {sql_id: toolDataId, connectionTitle: _.escape(panelTitle), db_name:parentData.database.label, server_name: parentData.server.label, user: parentData.server.user.name, server_type: parentData.server.server_type}, - {title: 'Untitled', icon: 'fa fa-sitemap'}, + {title: 'Untitled', icon: 'fa fa-sitemap', bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(open_new_tab?.includes('erd_tool')) ); diff --git a/web/pgadmin/tools/psql/static/js/PsqlModule.js b/web/pgadmin/tools/psql/static/js/PsqlModule.js index 39bac7c9891..c369589edda 100644 --- a/web/pgadmin/tools/psql/static/js/PsqlModule.js +++ b/web/pgadmin/tools/psql/static/js/PsqlModule.js @@ -173,12 +173,21 @@ export default class Psql { const open_new_tab = usePreferences.getState().getPreferencesForModule('browser').new_browser_tab_open; + // Extract bgcolor and fgcolor from server icon if available + let bgcolor = null; + let fgcolor = null; + if (parentData?.server?.icon) { + const iconParts = parentData.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + 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}, + {title: panelTitle, icon: 'pg-font-icon icon-terminal', manualClose: false, renamable: true, bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(open_new_tab?.includes('psql_tool')) ); diff --git a/web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js b/web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js index 1df100b0dc0..d474b82fce1 100644 --- a/web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js +++ b/web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js @@ -75,12 +75,25 @@ export default class SchemaDiff { let browserPreferences = usePreferences.getState().getPreferencesForModule('browser'); let openInNewTab = browserPreferences.new_browser_tab_open; + // Extract bgcolor and fgcolor from selected server if available + let bgcolor = null; + let fgcolor = null; + const selectedItem = pgAdmin.Browser.tree?.selected(); + if (selectedItem) { + const selectedNodeInfo = pgAdmin.Browser.tree?.getTreeNodeHierarchy(selectedItem); + if (selectedNodeInfo?.server?.icon) { + const iconParts = selectedNodeInfo.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + } + pgAdmin.Browser.Events.trigger( 'pgadmin:tool:show', `${BROWSER_PANELS.SCHEMA_DIFF_TOOL}_${trans_id}`, baseUrl, {...params}, - {title: panelTitle, icon: 'pg-font-icon icon-compare', manualClose: false, renamable: true}, + {title: panelTitle, icon: 'pg-font-icon icon-compare', manualClose: false, renamable: true, bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(openInNewTab?.includes('schema_diff')) ); return true; diff --git a/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js b/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js index 6da0f425b80..12a730c6449 100644 --- a/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js +++ b/web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js @@ -223,12 +223,21 @@ export default class SQLEditor { const [icon, tooltip] = panelTitleFunc.getQueryToolIcon(panel_title, is_query_tool); let selectedNodeInfo = pgAdmin.Browser.tree?.selected() ? pgAdmin.Browser.tree?.getTreeNodeHierarchy(pgAdmin.Browser.tree.selected()) : null; + // Extract bgcolor and fgcolor from selectedNodeInfo if available + let bgcolor = null; + let fgcolor = null; + if (selectedNodeInfo?.server?.icon) { + const iconParts = selectedNodeInfo.server.icon.split(' '); + bgcolor = iconParts[1] || null; + fgcolor = iconParts[2] || null; + } + pgAdmin.Browser.Events.trigger( 'pgadmin:tool:show', `${BROWSER_PANELS.QUERY_TOOL}_${trans_id}`, panel_url, {...params, title: panel_title, selectedNodeInfo: JSON.stringify(selectedNodeInfo)}, - {title: panel_title, icon: icon, tooltip: tooltip, renamable: true}, + {title: panel_title, icon: icon, tooltip: tooltip, renamable: true, bgcolor: bgcolor, fgcolor: fgcolor}, Boolean(open_new_tab?.includes('qt')) ); return true;