diff --git a/packages/perspective-workspace/src/ts/workspace/commands.ts b/packages/perspective-workspace/src/ts/workspace/commands.ts index 3154fe12e5..09cc6ea761 100644 --- a/packages/perspective-workspace/src/ts/workspace/commands.ts +++ b/packages/perspective-workspace/src/ts/workspace/commands.ts @@ -110,7 +110,7 @@ export const createCommands = ( commands.addCommand("workspace:new", { execute: (args) => { const widget = workspace._createWidgetAndNode({ - config: { table: args.table as string, master: false }, + config: { table: args.table as string }, slot: undefined, }); @@ -255,7 +255,7 @@ export const createCommands = ( commands.addCommand("workspace:help", { // iconClass: "menu-close", - execute: () => undefined, + execute: () => {}, label: "Shift+Click for Browser Menu", isEnabled: () => false, // mnemonic: 0, diff --git a/packages/perspective-workspace/src/ts/workspace/tabbar.ts b/packages/perspective-workspace/src/ts/workspace/tabbar.ts index a97d578fbb..363b78c962 100644 --- a/packages/perspective-workspace/src/ts/workspace/tabbar.ts +++ b/packages/perspective-workspace/src/ts/workspace/tabbar.ts @@ -172,7 +172,10 @@ export class PerspectiveTabBar extends TabBar { event ); - event.preventDefault(); + if (!event.shiftKey) { + event.preventDefault(); + } + break; case "mousedown": if ((event.target as HTMLElement).id === TabBarItems.Label) { diff --git a/packages/perspective-workspace/src/ts/workspace/widget.ts b/packages/perspective-workspace/src/ts/workspace/widget.ts index c5dc905733..0f9e12e3ae 100644 --- a/packages/perspective-workspace/src/ts/workspace/widget.ts +++ b/packages/perspective-workspace/src/ts/workspace/widget.ts @@ -23,7 +23,6 @@ interface IPerspectiveViewerWidgetOptions { export class PerspectiveViewerWidget extends Widget { viewer: psp_viewer.HTMLPerspectiveViewerElement; - _master: boolean; _title: string; _is_table_loaded: boolean; _restore_config?: () => Promise; @@ -32,29 +31,10 @@ export class PerspectiveViewerWidget extends Widget { constructor({ viewer, node }: IPerspectiveViewerWidgetOptions) { super({ node }); this.viewer = viewer; - this._master = false; this._title = ""; this._is_table_loaded = false; } - set master(value: boolean) { - if (this._master !== value) { - if (value) { - this.viewer.classList.add("workspace-master-widget"); - this.viewer.toggleAttribute?.("selectable", true); - } else { - this.viewer.classList.remove("workspace-master-widget"); - this.viewer.removeAttribute("selectable"); - } - - this._master = value; - } - } - - get master(): boolean { - return this._master; - } - get name(): string { return this._title; } @@ -75,12 +55,10 @@ export class PerspectiveViewerWidget extends Widget { restore( config: psp_viewer.ViewerConfigUpdate & { - master: boolean; table: string; } ) { - const { master, table, ...viewerConfig } = config; - this.master = master; + const { table, ...viewerConfig } = config; this._title = config.title as string; this.title.label = config.title as string; if (table) { @@ -107,7 +85,6 @@ export class PerspectiveViewerWidget extends Widget { async save() { let config = { ...(await this.viewer.save()), - master: this.master, table: this.viewer.getAttribute("table"), }; diff --git a/packages/perspective-workspace/src/ts/workspace/workspace.ts b/packages/perspective-workspace/src/ts/workspace/workspace.ts index 8ebe309f3e..e2d256d01d 100644 --- a/packages/perspective-workspace/src/ts/workspace/workspace.ts +++ b/packages/perspective-workspace/src/ts/workspace/workspace.ts @@ -49,7 +49,6 @@ export interface PerspectiveLayout { export interface ViewerConfigUpdateExt extends ViewerConfigUpdate { table: string; - master: boolean; } export interface PerspectiveWorkspaceConfig { @@ -326,16 +325,16 @@ export class PerspectiveWorkspace extends SplitPanel { widget = starting_widgets.find((x) => x.viewer === viewer); if (widget) { widget.load(this.tables.get(viewer_config.table)); - widget.restore({ ...viewer_config, master }); + widget.restore({ ...viewer_config }); } else { widget = this._createWidget({ - config: { ...viewer_config, master }, + config: { ...viewer_config }, viewer, }); } } else if (viewer_config) { widget = this._createWidgetAndNode({ - config: { ...viewer_config, master }, + config: { ...viewer_config }, slot: widgetName, }); } else { @@ -345,10 +344,13 @@ export class PerspectiveWorkspace extends SplitPanel { } if (master) { + widget.viewer.classList.add("workspace-master-widget"); + widget.viewer.toggleAttribute("selectable", true); widget.viewer.addEventListener( "perspective-select", this.onPerspectiveSelect.bind(this) ); + widget.viewer.addEventListener( "perspective-click", this.onPerspectiveSelect.bind(this) @@ -419,7 +421,6 @@ export class PerspectiveWorkspace extends SplitPanel { const widget = this._createWidget({ config: { - master: false, table: viewer.getAttribute("table")!, }, viewer, @@ -473,15 +474,10 @@ export class PerspectiveWorkspace extends SplitPanel { slot: undefined, }); - if (widget.master) { - const index = this.masterPanel.widgets.indexOf(widget) + 1; - this.masterPanel.insertWidget(index, duplicate); - } else { - this.dockpanel.addWidget(duplicate, { - mode: "split-right", - ref: widget, - }); - } + this.dockpanel.addWidget(duplicate, { + mode: "split-right", + ref: widget, + }); await duplicate.task; } @@ -587,11 +583,12 @@ export class PerspectiveWorkspace extends SplitPanel { } async makeMaster(widget: PerspectiveViewerWidget) { - widget.master = true; if (widget.viewer.hasAttribute("settings")) { await widget.toggleConfig(); } + widget.viewer.classList.add("workspace-master-widget"); + widget.viewer.toggleAttribute("selectable", true); if (!this.masterPanel.isAttached) { this.detailPanel.close(); this.setupMasterPanel(DEFAULT_WORKSPACE_SIZE); @@ -612,7 +609,8 @@ export class PerspectiveWorkspace extends SplitPanel { } makeDetail(widget: PerspectiveViewerWidget) { - widget.master = false; + widget.viewer.classList.remove("workspace-master-widget"); + widget.viewer.toggleAttribute("selectable", false); this.dockpanel.addWidget(widget, { mode: `split-left` }); if (this.masterPanel.widgets.length === 0) { this.detailPanel.close(); @@ -824,16 +822,17 @@ export class PerspectiveWorkspace extends SplitPanel { this.setRelativeSizes(sizes); } - addViewer(config: ViewerConfigUpdateExt) { + addViewer(config: ViewerConfigUpdateExt, is_global_filter?: boolean) { const widget = this._createWidgetAndNode({ config }); if (this.dockpanel.mode === "single-document") { this._unmaximize(); } - if (config.master) { + if (is_global_filter) { if (!this.masterPanel.isAttached) { this.setupMasterPanel(DEFAULT_WORKSPACE_SIZE); } + this.masterPanel.addWidget(widget); } else { if (!this.detailPanel.isAttached) { diff --git a/packages/perspective-workspace/test/js/restore.spec.js b/packages/perspective-workspace/test/js/restore.spec.js index d9aa27d676..125abe83eb 100644 --- a/packages/perspective-workspace/test/js/restore.spec.js +++ b/packages/perspective-workspace/test/js/restore.spec.js @@ -92,6 +92,29 @@ function tests(context, compare) { `${context}-restore-workspace-with-master-and-detail.txt` ); }); + + test("restore workspace is symmetric with addViewer", async ({ page }) => { + const initial = await page.evaluate(async (config) => { + const workspace = document.getElementById("workspace"); + await workspace.addViewer({ table: "superstore" }); + await workspace.flush(); + return await workspace.save(); + }); + + const second = await page.evaluate(async (initial) => { + const workspace = document.getElementById("workspace"); + await workspace.restore(initial); + await workspace.flush(); + return await workspace.save(); + }, initial); + + expect(initial).toEqual(second); + + return compare( + page, + `${context}-restore-workspace-is-symmetric-with-addviewer.txt` + ); + }); } test.describe("Workspace restore", () => { diff --git a/tools/perspective-test/results.tar.gz b/tools/perspective-test/results.tar.gz index 87fb577107..14ea0c92f2 100644 Binary files a/tools/perspective-test/results.tar.gz and b/tools/perspective-test/results.tar.gz differ