mirror of
https://github.com/mathuo/dockview
synced 2025-03-12 00:42:04 +00:00
Merge pull request #342 from mathuo/341-dockview-stuck-in-broken-state-after-apifromjson-fails-due-to-invalid-component-name
bug: unable to recover from loading a corrupted layout
This commit is contained in:
commit
9006fb9917
@ -4063,4 +4063,81 @@ describe('dockviewComponent', () => {
|
||||
expect(tabDragEvents.length).toBe(0);
|
||||
expect(groupDragEvents.length).toBe(1);
|
||||
});
|
||||
|
||||
test('that loading a corrupt layout throws an error and leaves a clean dockview behind', () => {
|
||||
const container = document.createElement('div');
|
||||
|
||||
const dockview = new DockviewComponent({
|
||||
parentElement: container,
|
||||
components: {
|
||||
default: PanelContentPartTest,
|
||||
},
|
||||
tabComponents: {
|
||||
test_tab_id: PanelTabPartTest,
|
||||
},
|
||||
orientation: Orientation.HORIZONTAL,
|
||||
});
|
||||
|
||||
dockview.layout(1000, 500);
|
||||
|
||||
dockview.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
expect(dockview.groups.length).toBe(1);
|
||||
expect(dockview.panels.length).toBe(1);
|
||||
|
||||
expect(() => {
|
||||
dockview.fromJSON({
|
||||
grid: {
|
||||
root: {
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panelA'],
|
||||
activeView: 'panelA',
|
||||
id: '1',
|
||||
},
|
||||
size: 841,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panelB'],
|
||||
activeView: 'panelB',
|
||||
id: '2',
|
||||
},
|
||||
size: 842,
|
||||
},
|
||||
],
|
||||
size: 530,
|
||||
},
|
||||
width: 1683,
|
||||
height: 530,
|
||||
orientation: Orientation.HORIZONTAL,
|
||||
},
|
||||
panels: {
|
||||
panelA: {
|
||||
id: 'panelA',
|
||||
contentComponent: 'somethingBad',
|
||||
title: 'Panel A',
|
||||
},
|
||||
panelB: {
|
||||
id: 'panelB',
|
||||
contentComponent: 'panelB',
|
||||
title: 'Panel B',
|
||||
},
|
||||
},
|
||||
activeGroup: '1',
|
||||
});
|
||||
}).toThrow(
|
||||
"Cannot create 'panelA', no component 'somethingBad' provided"
|
||||
);
|
||||
|
||||
expect(dockview.groups.length).toBe(0);
|
||||
expect(dockview.panels.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -649,33 +649,65 @@ export class DockviewComponent
|
||||
const createGroupFromSerializedState = (data: GroupPanelViewState) => {
|
||||
const { id, locked, hideHeader, views, activeView } = data;
|
||||
|
||||
const group = this.createGroup({
|
||||
id,
|
||||
locked: !!locked,
|
||||
hideHeader: !!hideHeader,
|
||||
});
|
||||
|
||||
this._onDidAddGroup.fire(group);
|
||||
|
||||
for (const child of views) {
|
||||
const panel = this._deserializer.fromJSON(panels[child], group);
|
||||
|
||||
const isActive =
|
||||
typeof activeView === 'string' && activeView === panel.id;
|
||||
|
||||
group.model.openPanel(panel, {
|
||||
skipSetPanelActive: !isActive,
|
||||
skipSetGroupActive: true,
|
||||
});
|
||||
if (typeof id !== 'string') {
|
||||
throw new Error('group id must be of type string');
|
||||
}
|
||||
|
||||
if (!group.activePanel && group.panels.length > 0) {
|
||||
group.model.openPanel(group.panels[group.panels.length - 1], {
|
||||
skipSetGroupActive: true,
|
||||
});
|
||||
}
|
||||
let group: DockviewGroupPanel | undefined;
|
||||
|
||||
return group;
|
||||
try {
|
||||
group = this.createGroup({
|
||||
id,
|
||||
locked: !!locked,
|
||||
hideHeader: !!hideHeader,
|
||||
});
|
||||
|
||||
this._onDidAddGroup.fire(group);
|
||||
|
||||
for (const child of views) {
|
||||
const panel = this._deserializer.fromJSON(
|
||||
panels[child],
|
||||
group
|
||||
);
|
||||
|
||||
const isActive =
|
||||
typeof activeView === 'string' &&
|
||||
activeView === panel.id;
|
||||
|
||||
group.model.openPanel(panel, {
|
||||
skipSetPanelActive: !isActive,
|
||||
skipSetGroupActive: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (!group.activePanel && group.panels.length > 0) {
|
||||
group.model.openPanel(
|
||||
group.panels[group.panels.length - 1],
|
||||
{
|
||||
skipSetGroupActive: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return group;
|
||||
} catch (err) {
|
||||
/**
|
||||
* This is an odd case... we have failed to deserialize a view but we have already created a group,
|
||||
* but we havn't registered that group with the gridview.
|
||||
* We cannot use the removeGroup method because the group has only been partially added, we must
|
||||
* manually dipose() of the view and remove it from being stored in the map.
|
||||
*/
|
||||
if (group) {
|
||||
group.dispose();
|
||||
this._groups.delete(group.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* re-throw the error becasue we don't actually want to catch it, we just
|
||||
* needed to do some clean-up before continuing.
|
||||
*/
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
this.gridview.deserialize(grid, {
|
||||
|
Loading…
Reference in New Issue
Block a user