diff --git a/e2e/scenes/dashboards-suite/dashboard-keybindings.spec.ts b/e2e/scenes/dashboards-suite/dashboard-keybindings.spec.ts new file mode 100644 index 00000000000..a7ab42cf7e8 --- /dev/null +++ b/e2e/scenes/dashboards-suite/dashboard-keybindings.spec.ts @@ -0,0 +1,24 @@ +import { e2e } from '../utils'; + +describe('Dashboard keybindings', () => { + beforeEach(() => { + e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); + }); + + it('should collapse and expand all rows', () => { + e2e.flows.openDashboard({ uid: 'Repeating-rows-uid/repeating-rows' }); + e2e.components.Panels.Panel.content().should('have.length', 5); + e2e.components.Panels.Panel.title('server = A, pod = Bob').should('be.visible'); + e2e.components.Panels.Panel.title('server = B, pod = Bob').should('be.visible'); + + cy.get('body').type('d').type('{shift}c'); + e2e.components.Panels.Panel.content().should('have.length', 0); + e2e.components.Panels.Panel.title('server = A, pod = Bob').should('not.exist'); + e2e.components.Panels.Panel.title('server = B, pod = Bob').should('not.exist'); + + cy.get('body').type('d').type('{shift}e'); + e2e.components.Panels.Panel.content().should('have.length', 6); + e2e.components.Panels.Panel.title('server = A, pod = Bob').should('be.visible'); + e2e.components.Panels.Panel.title('server = B, pod = Bob').should('be.visible'); + }); +}); diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 8c66b347edd..4f39bb8b104 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -877,6 +877,40 @@ export class DashboardScene extends SceneObjectBase { this.setState({ isDirty: false }); locationService.replace('/'); } + + public collapseAllRows() { + if (!(this.state.body instanceof SceneGridLayout)) { + throw new Error('Dashboard scene layout is not SceneGridLayout'); + } + + const sceneGridLayout = this.state.body; + + sceneGridLayout.state.children.forEach((child) => { + if (!(child instanceof SceneGridRow)) { + return; + } + if (!child.state.isCollapsed) { + sceneGridLayout.toggleRow(child); + } + }); + } + + public expandAllRows() { + if (!(this.state.body instanceof SceneGridLayout)) { + throw new Error('Dashboard scene layout is not SceneGridLayout'); + } + + const sceneGridLayout = this.state.body; + + sceneGridLayout.state.children.forEach((child) => { + if (!(child instanceof SceneGridRow)) { + return; + } + if (child.state.isCollapsed) { + sceneGridLayout.toggleRow(child); + } + }); + } } export class DashboardVariableDependency implements SceneVariableDependencyConfigLike { diff --git a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts index b88bd57d422..45be3d96f33 100644 --- a/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts +++ b/public/app/features/dashboard-scene/scene/keyboardShortcuts.ts @@ -167,12 +167,26 @@ export function setupKeyboardShortcuts(scene: DashboardScene) { } }), }); + + // collapse all rows + keybindings.addBinding({ + key: 'd shift+c', + onTrigger: () => { + scene.collapseAllRows(); + }, + }); + + // expand all rows + keybindings.addBinding({ + key: 'd shift+e', + onTrigger: () => { + scene.expandAllRows(); + }, + }); } // toggle all panel legends (TODO) // toggle all exemplars (TODO) - // collapse all rows (TODO) - // expand all rows (TODO) return () => { keybindings.removeAll();