mirror of
https://github.com/mathuo/dockview
synced 2025-03-12 08:52:05 +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(tabDragEvents.length).toBe(0);
|
||||||
expect(groupDragEvents.length).toBe(1);
|
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 createGroupFromSerializedState = (data: GroupPanelViewState) => {
|
||||||
const { id, locked, hideHeader, views, activeView } = data;
|
const { id, locked, hideHeader, views, activeView } = data;
|
||||||
|
|
||||||
const group = this.createGroup({
|
if (typeof id !== 'string') {
|
||||||
id,
|
throw new Error('group id must be of type string');
|
||||||
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) {
|
let group: DockviewGroupPanel | undefined;
|
||||||
group.model.openPanel(group.panels[group.panels.length - 1], {
|
|
||||||
skipSetGroupActive: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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, {
|
this.gridview.deserialize(grid, {
|
||||||
|
Loading…
Reference in New Issue
Block a user