diff --git a/e2e/suite1/specs/bar-gauge.spec.ts b/e2e/suite1/specs/bar-gauge.spec.ts index 382e70d6908..cdc469cb2b9 100644 --- a/e2e/suite1/specs/bar-gauge.spec.ts +++ b/e2e/suite1/specs/bar-gauge.spec.ts @@ -12,7 +12,7 @@ e2e.scenario({ e2e.flows.openDashboard({ uid: 'O6f11TZWk' }); e2e() - .get(`#panel-6 [aria-label^="${selectors.components.Panels.Visualization.BarGauge.value}"]`) + .get(`[data-panelid=6] [aria-label^="${selectors.components.Panels.Visualization.BarGauge.value}"]`) .should('have.css', 'color', 'rgb(242, 73, 92)') .contains('100'); }, diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts index 3767c115d35..00d19eae9f9 100644 --- a/public/app/core/services/keybindingSrv.ts +++ b/public/app/core/services/keybindingSrv.ts @@ -21,6 +21,7 @@ import { contextSrv } from '../core'; import { getDatasourceSrv } from '../../features/plugins/datasource_srv'; import { getTimeSrv } from '../../features/dashboard/services/TimeSrv'; import { toggleTheme } from './toggleTheme'; +import { withFocusedPanel } from './withFocusedPanelId'; export class KeybindingSrv { modalOpen = false; @@ -174,6 +175,10 @@ export class KeybindingSrv { Mousetrap.unbind(keyArg, keyType); } + bindWithPanelId(keyArg: string, fn: (panelId: number) => void) { + this.bind(keyArg, withFocusedPanel(fn)); + } + setupDashboardBindings(dashboard: DashboardModel) { this.bind('mod+o', () => { dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3; @@ -209,105 +214,82 @@ export class KeybindingSrv { }); // edit panel - this.bind('e', () => { - if (!dashboard.meta.focusPanelId) { - return; - } - - if (dashboard.canEditPanelById(dashboard.meta.focusPanelId)) { - locationService.partial({ - editPanel: dashboard.meta.focusPanelId, - }); + this.bindWithPanelId('e', (panelId) => { + if (dashboard.canEditPanelById(panelId)) { + const isEditing = locationService.getSearchObject().editPanel !== undefined; + locationService.partial({ editPanel: isEditing ? null : panelId }); } }); // view panel - this.bind('v', () => { - if (dashboard.meta.focusPanelId) { - locationService.partial({ - viewPanel: dashboard.meta.focusPanelId, - }); - } + this.bindWithPanelId('v', (panelId) => { + const isViewing = locationService.getSearchObject().viewPanel !== undefined; + locationService.partial({ viewPanel: isViewing ? null : panelId }); }); - this.bind('i', () => { - if (dashboard.meta.focusPanelId) { - locationService.partial({ - inspect: dashboard.meta.focusPanelId, - }); - } + this.bindWithPanelId('i', (panelId) => { + locationService.partial({ inspect: panelId }); }); // jump to explore if permissions allow if (contextSrv.hasAccessToExplore()) { - this.bind('x', async () => { - if (dashboard.meta.focusPanelId) { - const panel = dashboard.getPanelById(dashboard.meta.focusPanelId)!; - const datasource = await getDatasourceSrv().get(panel.datasource); - const url = await getExploreUrl({ - panel, - panelTargets: panel.targets, - panelDatasource: datasource, - datasourceSrv: getDatasourceSrv(), - timeSrv: getTimeSrv(), - }); + this.bindWithPanelId('x', async (panelId) => { + const panel = dashboard.getPanelById(panelId)!; + const datasource = await getDatasourceSrv().get(panel.datasource); + const url = await getExploreUrl({ + panel, + panelTargets: panel.targets, + panelDatasource: datasource, + datasourceSrv: getDatasourceSrv(), + timeSrv: getTimeSrv(), + }); - if (url) { - const urlWithoutBase = locationUtil.stripBaseFromUrl(url); - if (urlWithoutBase) { - locationService.push(urlWithoutBase); - } + if (url) { + const urlWithoutBase = locationUtil.stripBaseFromUrl(url); + if (urlWithoutBase) { + locationService.push(urlWithoutBase); } } }); } // delete panel - this.bind('p r', () => { - const panelId = dashboard.meta.focusPanelId; - - if (panelId && dashboard.canEditPanelById(panelId) && !(dashboard.panelInView || dashboard.panelInEdit)) { + this.bindWithPanelId('p r', (panelId) => { + if (dashboard.canEditPanelById(panelId) && !(dashboard.panelInView || dashboard.panelInEdit)) { appEvents.publish(new RemovePanelEvent(panelId)); - dashboard.meta.focusPanelId = 0; } }); // duplicate panel - this.bind('p d', () => { - const panelId = dashboard.meta.focusPanelId; - - if (panelId && dashboard.canEditPanelById(panelId)) { + this.bindWithPanelId('p d', (panelId) => { + if (dashboard.canEditPanelById(panelId)) { const panelIndex = dashboard.getPanelInfoById(panelId)!.index; dashboard.duplicatePanel(dashboard.panels[panelIndex]); } }); // share panel - this.bind('p s', () => { - if (dashboard.meta.focusPanelId) { - const panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + this.bindWithPanelId('p s', (panelId) => { + const panelInfo = dashboard.getPanelInfoById(panelId); - appEvents.publish( - new ShowModalReactEvent({ - component: ShareModal, - props: { - dashboard: dashboard, - panel: panelInfo?.panel, - }, - }) - ); - } + appEvents.publish( + new ShowModalReactEvent({ + component: ShareModal, + props: { + dashboard: dashboard, + panel: panelInfo?.panel, + }, + }) + ); }); // toggle panel legend - this.bind('p l', () => { - if (dashboard.meta.focusPanelId) { - const panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId)!; + this.bindWithPanelId('p l', (panelId) => { + const panelInfo = dashboard.getPanelInfoById(panelId)!; - if (panelInfo.panel.legend) { - panelInfo.panel.legend.show = !panelInfo.panel.legend.show; - panelInfo.panel.render(); - } + if (panelInfo.panel.legend) { + panelInfo.panel.legend.show = !panelInfo.panel.legend.show; + panelInfo.panel.render(); } }); diff --git a/public/app/core/services/withFocusedPanelId.ts b/public/app/core/services/withFocusedPanelId.ts new file mode 100644 index 00000000000..3a88ee142f7 --- /dev/null +++ b/public/app/core/services/withFocusedPanelId.ts @@ -0,0 +1,12 @@ +export function withFocusedPanel(fn: (panelId: number) => void) { + return () => { + const elements = document.querySelectorAll(':hover'); + + for (let i = elements.length - 1; i > 0; i--) { + const element = (elements[i] as unknown) as HTMLElement; + if (element.dataset?.panelid) { + fn(parseInt(element.dataset?.panelid, 10)); + } + } + }; +} diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 11caee332e1..2ac3ec15d8f 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -238,7 +238,7 @@ export class PanelEditorUnconnected extends PureComponent { } return (
-
+
{ panel.isInView = this.isInView(panel); panelElements.push( -
elem && (this.panelRef[id] = elem)}> +
elem && (this.panelRef[id] = elem)}> {this.renderPanel(panel)}
); diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index f475124a456..814044802cd 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -66,14 +66,6 @@ export class DashboardPanelUnconnected extends PureComponent { } } - onMouseEnter = () => { - this.props.dashboard.setPanelFocus(this.props.panel.id); - }; - - onMouseLeave = () => { - this.props.dashboard.setPanelFocus(0); - }; - renderPanel(plugin: PanelPlugin) { const { dashboard, panel, isViewing, isInView, isEditing } = this.props; @@ -135,11 +127,7 @@ export class DashboardPanelUnconnected extends PureComponent { 'panel-wrapper--view': isViewing, }); - return ( -
- {this.renderPanel(plugin)} -
- ); + return
{this.renderPanel(plugin)}
; } } diff --git a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap index 8ae6c30200a..65d7987b01f 100644 --- a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap +++ b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap @@ -45,7 +45,7 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` >
{ if (this.links.length > 0) { diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index 94b5012b1f6..d99bde26ff6 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -23,7 +23,6 @@ export interface DashboardMeta { submenuEnabled?: boolean; provisioned?: boolean; provisionedExternalId?: string; - focusPanelId?: number; isStarred?: boolean; showSettings?: boolean; expires?: string;