Skip to content

Commit b3feb15

Browse files
committed
Ensure new tabs are loaded correctly.
1 parent ad92886 commit b3feb15

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

  • web/pgadmin/static/js/helpers/Layout

web/pgadmin/static/js/helpers/Layout/index.jsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,79 @@ export class LayoutDocker {
222222
loadLayout(savedLayout) {
223223
try {
224224
this.layoutObj.loadLayout(JSON.parse(savedLayout));
225+
this.addMissingDefaultPanels();
225226
} catch {
226227
/* Fallback to default */
227228
this.layoutObj.loadLayout(this.defaultLayout);
228229
}
229230
}
230231

232+
addMissingDefaultPanels() {
233+
// Flatten both layouts to get all tabs
234+
const flattenLayout = (box, arr) => {
235+
box.children.forEach((child) => {
236+
if (child.children) {
237+
flattenLayout(child, arr);
238+
} else {
239+
arr.push(...(child.tabs ?? []));
240+
}
241+
});
242+
};
243+
244+
const flatDefault = [];
245+
const flatCurrent = [];
246+
flattenLayout(this.defaultLayout.dockbox, flatDefault);
247+
flattenLayout(this.layoutObj.getLayout().dockbox, flatCurrent);
248+
249+
// Find tabs in default but not in saved layout
250+
const missingTabs = _.differenceBy(flatDefault, flatCurrent, 'id');
251+
252+
// Only add non-closable tabs (closable tabs may have been intentionally removed)
253+
const missingNonClosableTabs = missingTabs.filter(tab => !tab.internal?.closable);
254+
255+
// Add each missing tab next to a sibling from its original panel group
256+
missingNonClosableTabs.forEach((tab) => {
257+
const siblingId = this.findSiblingTab(tab.id, flatDefault, flatCurrent);
258+
if (siblingId) {
259+
this.openTab({
260+
id: tab.id,
261+
content: tab.content,
262+
...tab.internal
263+
}, siblingId, 'middle');
264+
} else if (this.resetToTabPanel) {
265+
// Fallback: add to the reset panel location
266+
this.openTab({
267+
id: tab.id,
268+
content: tab.content,
269+
...tab.internal
270+
}, this.resetToTabPanel, 'middle');
271+
}
272+
});
273+
}
274+
275+
findSiblingTab(tabId, flatDefault, flatCurrent) {
276+
// Find which panel group this tab belongs to in the default layout
277+
const findPanelTabs = (box, targetId) => {
278+
for (const child of box.children) {
279+
if (child.children) {
280+
const result = findPanelTabs(child, targetId);
281+
if (result) return result;
282+
} else if (child.tabs) {
283+
const hasTarget = child.tabs.some(t => t.id === targetId);
284+
if (hasTarget) return child.tabs.map(t => t.id);
285+
}
286+
}
287+
return null;
288+
};
289+
290+
const siblingIds = findPanelTabs(this.defaultLayout.dockbox, tabId);
291+
if (!siblingIds) return null;
292+
293+
// Find a sibling that exists in current layout
294+
const currentIds = flatCurrent.map(t => t.id);
295+
return siblingIds.find(id => id !== tabId && currentIds.includes(id));
296+
}
297+
231298
saveLayout(l) {
232299
let api = getApiInstance();
233300
if(!this.layoutId || !this.layoutObj) {

0 commit comments

Comments
 (0)