Skip to content

Feat: Added a option to colorize panel/tab header based on server color #2431#9799

Open
mzabuawala wants to merge 1 commit intopgadmin-org:masterfrom
mzabuawala:feat-query-tool-2431
Open

Feat: Added a option to colorize panel/tab header based on server color #2431#9799
mzabuawala wants to merge 1 commit intopgadmin-org:masterfrom
mzabuawala:feat-query-tool-2431

Conversation

@mzabuawala
Copy link
Copy Markdown
Contributor

@mzabuawala mzabuawala commented Mar 29, 2026

Summary by CodeRabbit

  • New Features
    • Added a browser preference (default: off) to show a small colored circle in panel tabs that matches a server’s configured color, helping identify which server a panel is connected to.
    • Server color indicators are shown for panels/tools (Query Tool, ERD, Debugger, PSQL, Schema Diff, SQL Editor) and update when a server’s color changes; visibility is optimized for active/hidden tabs.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

Walkthrough

Adds a browser preference to toggle a per-server color indicator in panel tabs and propagates server color metadata (bgcolor/fgcolor, server_id) from tree/tool modules through layout to TabTitle for conditional rendering.

Changes

Cohort / File(s) Summary
Browser Preference Registration
web/pgadmin/browser/register_browser_preferences.py
Register new boolean preference display.show_server_color_indicator (default False) with label and help text.
Layout System & Tab UI
web/pgadmin/static/js/helpers/Layout/index.jsx
LayoutDocker.getPanel accepts bgcolor, fgcolor, server_id and stores them on panel internal; TabTitle now tracks internal.bgcolor/fgcolor/server_id, listens for layout and server-color update events, and conditionally renders a circular color indicator when the preference is enabled and conditions match.
Utility: server color extraction
web/pgadmin/static/js/utils.js
Add exported getServerColors(serverIcon) returning { bgcolor, fgcolor } with guards for falsy/missing input.
Browser node updates & background change
web/pgadmin/browser/static/js/node.js
On server node update, compute {bgcolor, fgcolor} via commonUtils.getServerColors(...) and trigger pgadmin:server:colors:updated with server_id and colors; replace manual string-splitting in change_server_background with getServerColors.
Tool modules: include colors & server_id in tool show payloads
web/pgadmin/tools/debugger/static/js/DebuggerModule.js, web/pgadmin/tools/erd/static/js/ERDModule.js, web/pgadmin/tools/psql/static/js/PsqlModule.js, web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js, web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
Each module imports/uses getServerColors (or common util) to derive bgcolor/fgcolor and extracts server_id, then adds them to the pgadmin:tool:show event options payload alongside existing metadata (title, icon, manualClose, renamable).
Minor UI helper tweak
web/pgadmin/static/js/ToolView.jsx
Whitespace/trailing blank line added in getToolTabParams (no behavior change).

Sequence Diagram

sequenceDiagram
    actor User
    participant Tool as Tool Module
    participant Layout as LayoutDocker
    participant TabTitle as TabTitle Component
    participant Pref as Preference System

    User->>Tool: open tool (SQLEditor/Debugger/...)
    Tool->>Tool: getServerColors(server.icon)
    Tool->>Layout: trigger('pgadmin:tool:show', {..., bgcolor, fgcolor, server_id})
    Layout->>Layout: getPanel(..., bgcolor, fgcolor, server_id) -> store in internal
    Layout->>TabTitle: provide internal props (including colors)
    TabTitle->>Pref: read browser.show_server_color_indicator
    Pref-->>TabTitle: preference value
    alt pref enabled & bgcolor present & tab hidden
        TabTitle->>TabTitle: render circular color indicator
    else
        TabTitle->>TabTitle: do not render indicator
    end
    TabTitle-->>User: display tab title
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • yogeshmahajan-1903
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding a preference option to colorize panel/tab headers based on server colors, which is implemented across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mzabuawala mzabuawala force-pushed the feat-query-tool-2431 branch 2 times, most recently from 7e3e6df to 102aa02 Compare March 29, 2026 05:07
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
web/pgadmin/tools/debugger/static/js/DebuggerModule.js (1)

382-389: Refactor duplicated color parsing into a local helper.

The same server.icon split/extract logic appears in both debugger launch paths; a shared helper in this module would reduce maintenance overhead.

Also applies to: 540-547

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/pgadmin/tools/debugger/static/js/DebuggerModule.js` around lines 382 -
389, Extract the duplicated server.icon parsing into a small local helper (e.g.,
parseServerIcon(icon)) that accepts newTreeInfo.server.icon, splits it, and
returns {bgcolor, fgcolor} (null when not present); replace the inline logic
that sets bgcolor/fgcolor in both debugger launch paths (the snippet using
newTreeInfo?.server?.icon around where bgcolor and fgcolor are assigned and the
similar block at lines 540-547) to call this helper instead, leaving callers to
destructure or assign the returned values.
web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js (1)

226-233: Consider centralizing server-color parsing into a shared helper.

icon.split(' ')[1/2] is now repeated across multiple tool modules; extracting a shared utility would reduce drift and simplify future changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js` around lines 226 -
233, The repeated parsing of server icon colors
(selectedNodeInfo.server.icon.split(' ')[1/2]) should be extracted into a shared
helper to avoid duplication: create a utility function (e.g.,
parseServerIconColors(icon) -> {bgcolor, fgcolor}) in a common utilities module
and export it, replace the inline code in SQLEditorModule.js (where
bgcolor/fgcolor are set from selectedNodeInfo.server.icon) with a call to
parseServerIconColors(selectedNodeInfo?.server?.icon) and update other tool
modules to import and use the same helper so all modules derive bgcolor and
fgcolor consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/pgadmin/browser/register_browser_preferences.py`:
- Line 106: The preference declaration gettext("Show server color indicator in
panel tabs?"), 'boolean', False exceeds the 79-character line length; fix by
wrapping the tuple across multiple lines or breaking the long string into
concatenated parts so the gettext(...) call or the tuple elements fit within the
79-char limit (e.g., place each tuple element on its own line inside the
surrounding list/tuple using parentheses) while keeping the symbol gettext("Show
server color indicator in panel tabs?"), 'boolean', False intact.

---

Nitpick comments:
In `@web/pgadmin/tools/debugger/static/js/DebuggerModule.js`:
- Around line 382-389: Extract the duplicated server.icon parsing into a small
local helper (e.g., parseServerIcon(icon)) that accepts newTreeInfo.server.icon,
splits it, and returns {bgcolor, fgcolor} (null when not present); replace the
inline logic that sets bgcolor/fgcolor in both debugger launch paths (the
snippet using newTreeInfo?.server?.icon around where bgcolor and fgcolor are
assigned and the similar block at lines 540-547) to call this helper instead,
leaving callers to destructure or assign the returned values.

In `@web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js`:
- Around line 226-233: The repeated parsing of server icon colors
(selectedNodeInfo.server.icon.split(' ')[1/2]) should be extracted into a shared
helper to avoid duplication: create a utility function (e.g.,
parseServerIconColors(icon) -> {bgcolor, fgcolor}) in a common utilities module
and export it, replace the inline code in SQLEditorModule.js (where
bgcolor/fgcolor are set from selectedNodeInfo.server.icon) with a call to
parseServerIconColors(selectedNodeInfo?.server?.icon) and update other tool
modules to import and use the same helper so all modules derive bgcolor and
fgcolor consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 16c6121d-db9d-447c-9fe6-f6ae8f1935bd

📥 Commits

Reviewing files that changed from the base of the PR and between aa3dc38 and 102aa02.

📒 Files selected for processing (7)
  • web/pgadmin/browser/register_browser_preferences.py
  • web/pgadmin/static/js/helpers/Layout/index.jsx
  • web/pgadmin/tools/debugger/static/js/DebuggerModule.js
  • web/pgadmin/tools/erd/static/js/ERDModule.js
  • web/pgadmin/tools/psql/static/js/PsqlModule.js
  • web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js
  • web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js

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, [])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can safely remove React.useCallback to simplify code.

if (newTreeInfo?.server?.icon) {
const iconParts = newTreeInfo.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this hack for?

if (treeInfo?.server?.icon) {
const iconParts = treeInfo.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeated.

if (parentData?.server?.icon) {
const iconParts = parentData.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeated

if (parentData?.server?.icon) {
const iconParts = parentData.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeated

if (selectedNodeInfo?.server?.icon) {
const iconParts = selectedNodeInfo.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm skeptical for this logic. kind of a hack,

if (selectedNodeInfo?.server?.icon) {
const iconParts = selectedNodeInfo.server.icon.split(' ');
bgcolor = iconParts[1] || null;
fgcolor = iconParts[2] || null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeated.

return (
<Box display="flex" alignItems="center" title={attrs.tooltip} onContextMenu={onContextMenu} width="100%">
{attrs.icon && <span className={`dock-tab-icon ${attrs.icon}`}></span>}
{showServerColorIndicator && attrs.bgcolor && !layoutDocker.isTabVisible(id) && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this work, if a tab is open and server color is changed?

@mzabuawala mzabuawala force-pushed the feat-query-tool-2431 branch 2 times, most recently from 3cfa44b to 8121fd0 Compare March 31, 2026 17:51
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/pgadmin/static/js/utils.js`:
- Around line 250-253: The current parsing of serverIcon is brittle because it
assumes single spaces and single-token icon classes; instead, split serverIcon
using whitespace (e.g., serverIcon.trim().split(/\s+/)) and extract the last one
or two tokens as bgcolor/fgcolor so multi-token icon classes don't shift indices
— update the logic around serverIcon splitting and the return that sets bgcolor
and fgcolor to use the last tokens (falling back to null if missing).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b963a62e-4e0f-4ebf-9625-5cc13e2b77f3

📥 Commits

Reviewing files that changed from the base of the PR and between 102aa02 and 8121fd0.

📒 Files selected for processing (9)
  • web/pgadmin/browser/register_browser_preferences.py
  • web/pgadmin/browser/static/js/node.js
  • web/pgadmin/static/js/helpers/Layout/index.jsx
  • web/pgadmin/static/js/utils.js
  • web/pgadmin/tools/debugger/static/js/DebuggerModule.js
  • web/pgadmin/tools/erd/static/js/ERDModule.js
  • web/pgadmin/tools/psql/static/js/PsqlModule.js
  • web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js
  • web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
✅ Files skipped from review due to trivial changes (2)
  • web/pgadmin/tools/erd/static/js/ERDModule.js
  • web/pgadmin/tools/debugger/static/js/DebuggerModule.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • web/pgadmin/browser/register_browser_preferences.py
  • web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
  • web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js
  • web/pgadmin/tools/psql/static/js/PsqlModule.js
  • web/pgadmin/static/js/helpers/Layout/index.jsx

Comment on lines +250 to +253
const parts = serverIcon.split(' ');
return {
bgcolor: parts[1] || null,
fgcolor: parts[2] || null,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make server icon parsing resilient to spacing/class-token variations.

Line 250 assumes a strict single-space, single-class format. If spacing varies (or icon class contains multiple tokens), parts[1]/parts[2] can map to wrong values and break color rendering.

Proposed fix
 export function getServerColors(serverIcon) {
-  if (!serverIcon) {
+  if (!serverIcon || typeof serverIcon !== 'string') {
     return { bgcolor: null, fgcolor: null };
   }
 
-  const parts = serverIcon.split(' ');
+  const parts = serverIcon.trim().split(/\s+/);
+  if (parts.length < 3) {
+    return { bgcolor: null, fgcolor: null };
+  }
   return {
-    bgcolor: parts[1] || null,
-    fgcolor: parts[2] || null,
+    // Keep icon token(s) flexible; colors are the trailing 2 tokens.
+    bgcolor: parts[parts.length - 2] || null,
+    fgcolor: parts[parts.length - 1] || null,
   };
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const parts = serverIcon.split(' ');
return {
bgcolor: parts[1] || null,
fgcolor: parts[2] || null,
export function getServerColors(serverIcon) {
if (!serverIcon || typeof serverIcon !== 'string') {
return { bgcolor: null, fgcolor: null };
}
const parts = serverIcon.trim().split(/\s+/);
if (parts.length < 3) {
return { bgcolor: null, fgcolor: null };
}
return {
// Keep icon token(s) flexible; colors are the trailing 2 tokens.
bgcolor: parts[parts.length - 2] || null,
fgcolor: parts[parts.length - 1] || null,
};
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/pgadmin/static/js/utils.js` around lines 250 - 253, The current parsing
of serverIcon is brittle because it assumes single spaces and single-token icon
classes; instead, split serverIcon using whitespace (e.g.,
serverIcon.trim().split(/\s+/)) and extract the last one or two tokens as
bgcolor/fgcolor so multi-token icon classes don't shift indices — update the
logic around serverIcon splitting and the return that sets bgcolor and fgcolor
to use the last tokens (falling back to null if missing).

@mzabuawala mzabuawala force-pushed the feat-query-tool-2431 branch from 8121fd0 to 6cb541c Compare April 1, 2026 05:11
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/pgadmin/static/js/helpers/Layout/index.jsx`:
- Line 31: Remove the unused import getServerColors from the top of
Layout/index.jsx; delete the line "import { getServerColors } from
'../../utils';" (and any leftover references if present) because bgcolor/fgcolor
are provided via event payloads and the module does not need to compute colors
itself, preventing the pipeline failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54a14f6c-230a-4956-92a6-d3c21306475d

📥 Commits

Reviewing files that changed from the base of the PR and between 8121fd0 and 6cb541c.

📒 Files selected for processing (10)
  • web/pgadmin/browser/register_browser_preferences.py
  • web/pgadmin/browser/static/js/node.js
  • web/pgadmin/static/js/ToolView.jsx
  • web/pgadmin/static/js/helpers/Layout/index.jsx
  • web/pgadmin/static/js/utils.js
  • web/pgadmin/tools/debugger/static/js/DebuggerModule.js
  • web/pgadmin/tools/erd/static/js/ERDModule.js
  • web/pgadmin/tools/psql/static/js/PsqlModule.js
  • web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js
  • web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
✅ Files skipped from review due to trivial changes (3)
  • web/pgadmin/static/js/ToolView.jsx
  • web/pgadmin/tools/debugger/static/js/DebuggerModule.js
  • web/pgadmin/tools/erd/static/js/ERDModule.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js
  • web/pgadmin/browser/register_browser_preferences.py
  • web/pgadmin/static/js/utils.js
  • web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js
  • web/pgadmin/browser/static/js/node.js

import ToolView, { getToolTabParams } from '../../ToolView';
import { ApplicationStateProvider, useApplicationState } from '../../../../settings/static/ApplicationStateProvider';
import { BROWSER_PANELS, WORKSPACES } from '../../../../browser/static/js/constants';
import { getServerColors } from '../../utils';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove unused import getServerColors.

The import is causing pipeline failures. This file receives bgcolor/fgcolor from tool modules via the event payload—it doesn't need to compute colors itself.

🐛 Proposed fix
-import { getServerColors } from '../../utils';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { getServerColors } from '../../utils';
🧰 Tools
🪛 GitHub Actions: Check Javascript style

[error] 31-31: ESLint (unused-imports/no-unused-imports): 'getServerColors' is defined but never used.

🪛 GitHub Actions: Run feature tests on PostgreSQL

[error] 31-31: ESLint error: 'getServerColors' is defined but never used (unused-imports/no-unused-imports).

🪛 GitHub Actions: Run Javascript tests

[error] 31-10: ESLint error (unused-imports/no-unused-imports): 'getServerColors' is defined but never used.

🪛 GitHub Check: run-javascript-tests (macos-latest)

[failure] 31-31:
'getServerColors' is defined but never used

🪛 GitHub Check: run-javascript-tests (ubuntu-22.04)

[failure] 31-31:
'getServerColors' is defined but never used

🪛 GitHub Check: run-javascript-tests (windows-latest)

[failure] 31-31:
'getServerColors' is defined but never used

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/pgadmin/static/js/helpers/Layout/index.jsx` at line 31, Remove the unused
import getServerColors from the top of Layout/index.jsx; delete the line "import
{ getServerColors } from '../../utils';" (and any leftover references if
present) because bgcolor/fgcolor are provided via event payloads and the module
does not need to compute colors itself, preventing the pipeline failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants