From 321e60e69c19c78a5e40169d1ec20c67c6ac89f7 Mon Sep 17 00:00:00 2001 From: Kristina Demeshchik Date: Tue, 16 Dec 2025 09:34:10 -0500 Subject: [PATCH] Dashboards: Add missing keyboard shortcuts for new layouts (#115377) * missing key bindings * Collapse repeted panels --- .../dashboard-keybindings.spec.ts | 59 +++++++++++++++++++ .../scene/keyboardShortcuts.ts | 5 ++ .../scene/layout-rows/RowsLayoutManager.tsx | 26 ++++++++ 3 files changed, 90 insertions(+) create mode 100644 e2e-playwright/dashboard-new-layouts/dashboard-keybindings.spec.ts diff --git a/e2e-playwright/dashboard-new-layouts/dashboard-keybindings.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboard-keybindings.spec.ts new file mode 100644 index 00000000000..19ad38f16d5 --- /dev/null +++ b/e2e-playwright/dashboard-new-layouts/dashboard-keybindings.spec.ts @@ -0,0 +1,59 @@ +import { test, expect } from '@grafana/plugin-e2e'; + +test.use({ + featureToggles: { + kubernetesDashboards: true, + dashboardNewLayouts: true, + }, +}); + +test.describe('Dashboard keybindings with new layouts', { tag: ['@dashboards'] }, () => { + test.use({ + viewport: { width: 1280, height: 1080 }, + }); + + test('should collapse and expand all rows', async ({ gotoDashboardPage, page, selectors }) => { + const dashboardPage = await gotoDashboardPage({ uid: 'Repeating-rows-uid/repeating-rows' }); + + const panelContents = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.content); + await expect(panelContents).toHaveCount(5); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('server = A, pod = Bob')) + ).toBeVisible(); + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('server = B, pod = Bob')) + ).toBeVisible(); + + // Collapse all rows using keyboard shortcut: d + Shift+C + await page.keyboard.press('d'); + await page.keyboard.press('Shift+C'); + + await expect(panelContents).toHaveCount(0); + await expect(page.getByText('server = A, pod = Bob')).toBeHidden(); + await expect(page.getByText('server = B, pod = Bob')).toBeHidden(); + + // Expand all rows using keyboard shortcut: d + Shift+E + await page.keyboard.press('d'); + await page.keyboard.press('Shift+E'); + + await expect(panelContents).toHaveCount(6); + await expect(page.getByText('server = A, pod = Bob')).toBeVisible(); + await expect(page.getByText('server = B, pod = Bob')).toBeVisible(); + }); + + test('should open panel inspect', async ({ gotoDashboardPage, page, selectors }) => { + const dashboardPage = await gotoDashboardPage({ uid: 'edediimbjhdz4b/a-tall-dashboard' }); + + // Find Panel #1 and press 'i' to open inspector + const panel1 = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel #1')); + await expect(panel1).toBeVisible(); + await panel1.press('i'); + + await expect(dashboardPage.getByGrafanaSelector(selectors.components.PanelInspector.Json.content)).toBeVisible(); + + // Press Escape to close inspector + await page.keyboard.press('Escape'); + + await expect(page.getByTestId(selectors.components.PanelInspector.Json.content)).toBeHidden(); + }); +}); diff --git a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts index f1878aeb466..cb5172a0e7e 100644 --- a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts +++ b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts @@ -18,6 +18,7 @@ import { getPanelIdForVizPanel } from '../utils/utils'; import { DashboardScene } from './DashboardScene'; import { onRemovePanel, toggleVizPanelLegend } from './PanelMenuBehavior'; import { DefaultGridLayoutManager } from './layout-default/DefaultGridLayoutManager'; +import { RowsLayoutManager } from './layout-rows/RowsLayoutManager'; export function setupKeyboardShortcuts(scene: DashboardScene) { const keybindings = new KeybindingSet(); @@ -265,6 +266,8 @@ export function setupKeyboardShortcuts(scene: DashboardScene) { onTrigger: () => { if (scene.state.body instanceof DefaultGridLayoutManager) { scene.state.body.collapseAllRows(); + } else if (scene.state.body instanceof RowsLayoutManager) { + scene.state.body.collapseAllRows(); } }, }); @@ -275,6 +278,8 @@ export function setupKeyboardShortcuts(scene: DashboardScene) { onTrigger: () => { if (scene.state.body instanceof DefaultGridLayoutManager) { scene.state.body.expandAllRows(); + } else if (scene.state.body instanceof RowsLayoutManager) { + scene.state.body.expandAllRows(); } }, }); diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx index 778aad91757..48f11357e24 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx @@ -390,4 +390,30 @@ export class RowsLayoutManager extends SceneObjectBase i return duplicateTitles; } + + public collapseAllRows() { + this.state.rows.forEach((row) => { + if (!row.getCollapsedState()) { + row.setCollapsedState(true); + } + row.state.repeatedRows?.forEach((repeatedRow) => { + if (!repeatedRow.getCollapsedState()) { + repeatedRow.setCollapsedState(true); + } + }); + }); + } + + public expandAllRows() { + this.state.rows.forEach((row) => { + if (row.getCollapsedState()) { + row.setCollapsedState(false); + } + row.state.repeatedRows?.forEach((repeatedRow) => { + if (repeatedRow.getCollapsedState()) { + repeatedRow.setCollapsedState(false); + } + }); + }); + } }