|
| 1 | +# Server Color Refactoring Summary |
| 2 | + |
| 3 | +## Overview |
| 4 | +This refactoring addresses code duplication and a bug related to server color indicators in panel/tab headers. The changes implement a DRY approach and add dynamic color updates when server properties change. |
| 5 | + |
| 6 | +## Problems Solved |
| 7 | + |
| 8 | +### 1. Code Duplication ("The Hack") |
| 9 | +**Problem**: The same logic to extract bgcolor/fgcolor from server icon strings was duplicated across 6+ files: |
| 10 | +```javascript |
| 11 | +// Repeated everywhere: |
| 12 | +const iconParts = serverIcon.split(' '); |
| 13 | +bgcolor = iconParts[1] || null; |
| 14 | +fgcolor = iconParts[2] || null; |
| 15 | +``` |
| 16 | + |
| 17 | +**Root Cause**: The backend encodes structured data (icon CSS class, bgcolor, fgcolor) into a single space-separated string via `server_icon_and_background()` in Python. The format is: `"icon-class bgcolor fgcolor"` (e.g., `"icon-pg #FF5733 #FFFFFF"`). |
| 18 | + |
| 19 | +While the Server model in the database has separate `bgcolor` and `fgcolor` fields, the backend concatenates them with the icon class for tree node representation, requiring frontend parsing. |
| 20 | + |
| 21 | +**Solution**: Created a centralized utility function `getServerColors()` with comprehensive documentation explaining this design decision. |
| 22 | + |
| 23 | +### 2. Server Color Update Bug |
| 24 | +**Problem**: When a user changes a server's bgcolor/fgcolor in server properties while tabs are open, those tabs don't update their color indicators until closed and reopened. |
| 25 | + |
| 26 | +**Root Cause**: The TabTitle component only reads colors from cached `internal` data when `REFRESH_TITLE` event fires, never fetching fresh colors from the tree when server properties are updated. |
| 27 | + |
| 28 | +**Solution**: Added an event listener for `pgadmin:browser:node:updated` in TabTitle component to dynamically update colors when server properties change. |
| 29 | + |
| 30 | +## Changes Made |
| 31 | + |
| 32 | +### 1. New Utility Function |
| 33 | +**File**: `web/pgadmin/static/js/utils.js` |
| 34 | + |
| 35 | +Added `getServerColors(serverIcon)` function with: |
| 36 | +- Detailed JSDoc explaining the historical context |
| 37 | +- Clear example usage |
| 38 | +- Reference to the backend function responsible for this format |
| 39 | +- Safe handling of null/undefined inputs |
| 40 | + |
| 41 | +### 2. Refactored Modules (6 files) |
| 42 | +All tool modules now use the centralized utility: |
| 43 | + |
| 44 | +1. **SQLEditorModule.js** |
| 45 | + - Added `getServerColors` import |
| 46 | + - Replaced parsing logic with utility call |
| 47 | + - Added `server_id` to tab params |
| 48 | + |
| 49 | +2. **DebuggerModule.js** (2 locations) |
| 50 | + - Direct debugger launch |
| 51 | + - Indirect debugger launch |
| 52 | + - Both now use utility and include `server_id` |
| 53 | + |
| 54 | +3. **ERDModule.js** |
| 55 | + - Replaced parsing logic |
| 56 | + - Added `server_id` to tab params |
| 57 | + |
| 58 | +4. **PsqlModule.js** |
| 59 | + - Replaced parsing logic |
| 60 | + - Added `server_id` to tab params |
| 61 | + |
| 62 | +5. **SchemaDiffModule.js** |
| 63 | + - Replaced parsing logic |
| 64 | + - Added `server_id` to tab params |
| 65 | + |
| 66 | +6. **node.js** (browser tree callbacks) |
| 67 | + - Replaced parsing logic in `change_server_background` callback |
| 68 | + |
| 69 | +### 3. Dynamic Color Updates |
| 70 | +**File**: `web/pgadmin/static/js/helpers/Layout/index.jsx` |
| 71 | + |
| 72 | +**Changes**: |
| 73 | +- Added imports for `pgAdmin` and `getServerColors` |
| 74 | +- Enhanced `TabTitle` component's useEffect to: |
| 75 | + - Listen for `pgadmin:browser:node:updated` event |
| 76 | + - Check if the updated node is a server matching this tab's server_id |
| 77 | + - Extract fresh colors from the updated server icon |
| 78 | + - Update both internal data and visual state |
| 79 | + - Properly clean up event listener on unmount |
| 80 | + |
| 81 | +**How it works**: |
| 82 | +1. When user saves server properties, `pgadmin:browser:node:updated` event fires |
| 83 | +2. All open TabTitle components receive the event |
| 84 | +3. Each tab checks if `newNodeData._id` matches its stored `server_id` |
| 85 | +4. Matching tabs extract fresh colors and update their display |
| 86 | +5. Color indicators update immediately without tab refresh |
| 87 | + |
| 88 | +### 4. Server ID Tracking |
| 89 | +All tool modules now pass `server_id` in their tab parameters: |
| 90 | +```javascript |
| 91 | +{ |
| 92 | + title: panelTitle, |
| 93 | + icon: icon, |
| 94 | + bgcolor: bgcolor, |
| 95 | + fgcolor: fgcolor, |
| 96 | + server_id: serverId // NEW: enables color update matching |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +This enables the TabTitle component to identify which tabs belong to which server when properties change. |
| 101 | + |
| 102 | +## Benefits |
| 103 | + |
| 104 | +1. **DRY Principle**: Eliminated 6+ instances of duplicated parsing logic |
| 105 | +2. **Maintainability**: Single source of truth for color extraction |
| 106 | +3. **Documentation**: Clear explanation of the historical design decision |
| 107 | +4. **Bug Fix**: Server color changes now reflect immediately in all open tabs |
| 108 | +5. **Type Safety**: Consistent return type `{bgcolor: string|null, fgcolor: string|null}` |
| 109 | +6. **Future-Proof**: Easier to refactor if backend changes color encoding |
| 110 | + |
| 111 | +## Testing Recommendations |
| 112 | + |
| 113 | +1. **Color Extraction**: |
| 114 | + - Verify color indicators appear correctly when opening tools |
| 115 | + - Test with servers having no colors set (should handle gracefully) |
| 116 | + - Test with servers having only bgcolor (no fgcolor) |
| 117 | + |
| 118 | +2. **Dynamic Updates**: |
| 119 | + - Open multiple tabs from same server |
| 120 | + - Change server's bgcolor/fgcolor in properties |
| 121 | + - Verify all tabs from that server update colors immediately |
| 122 | + - Verify tabs from other servers are unaffected |
| 123 | + |
| 124 | +3. **Edge Cases**: |
| 125 | + - Open tabs, disconnect server, reconnect with different colors |
| 126 | + - Multiple tools open simultaneously (Query Tool, Debugger, ERD, etc.) |
| 127 | + - Tabs from different servers in same layout |
| 128 | + |
| 129 | +## Future Improvements |
| 130 | + |
| 131 | +1. **Backend Refactor**: Consider sending bgcolor/fgcolor as separate JSON fields instead of space-separated string |
| 132 | +2. **Performance**: Could debounce color updates if many tabs exist |
| 133 | +3. **Memory**: Consider weak references if tab count grows very large |
| 134 | + |
| 135 | +## Files Modified |
| 136 | + |
| 137 | +1. `web/pgadmin/static/js/utils.js` - New utility function |
| 138 | +2. `web/pgadmin/static/js/helpers/Layout/index.jsx` - Dynamic color updates |
| 139 | +3. `web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js` |
| 140 | +4. `web/pgadmin/tools/debugger/static/js/DebuggerModule.js` |
| 141 | +5. `web/pgadmin/tools/erd/static/js/ERDModule.js` |
| 142 | +6. `web/pgadmin/tools/psql/static/js/PsqlModule.js` |
| 143 | +7. `web/pgadmin/tools/schema_diff/static/js/SchemaDiffModule.js` |
| 144 | +8. `web/pgadmin/browser/static/js/node.js` |
| 145 | + |
| 146 | +## Related Backend Code |
| 147 | + |
| 148 | +- `web/pgadmin/browser/server_groups/servers/__init__.py` - `server_icon_and_background()` function |
| 149 | +- Database migration: `web/migrations/versions/02b9dccdcfcb_.py` - Added bgcolor/fgcolor columns |
0 commit comments