mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 00:47:38 -06:00
Dashboards: Fix scroll position not being restored when leaving panel edit (#83787)
* Dashboards: Fix scroll position not being restored when leaving panel edit view * remove mock from tests * remove console log * Remove my debugging stuff, and don't render grid if width is 0 * remove old comment (but retain old, probably unneeded css) * rename ref * fix it not actually working anymore!!! * add e2e tests * jsonnet, i guess
This commit is contained in:
parent
6db7eafd7e
commit
183aa09eeb
1791
devenv/dev-dashboards/scenarios/tall_dashboard.json
Normal file
1791
devenv/dev-dashboards/scenarios/tall_dashboard.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -91,6 +91,7 @@
|
||||
"table_sparkline_cell": (import '../dev-dashboards/panel-table/table_sparkline_cell.json'),
|
||||
"table_tests": (import '../dev-dashboards/panel-table/table_tests.json'),
|
||||
"table_tests_new": (import '../dev-dashboards/panel-table/table_tests_new.json'),
|
||||
"tall_dashboard": (import '../dev-dashboards/scenarios/tall_dashboard.json'),
|
||||
"templating-dashboard-links-and-variables": (import '../dev-dashboards/feature-templating/templating-dashboard-links-and-variables.json'),
|
||||
"templating-repeating-panels": (import '../dev-dashboards/feature-templating/templating-repeating-panels.json'),
|
||||
"templating-repeating-rows": (import '../dev-dashboards/feature-templating/templating-repeating-rows.json'),
|
||||
|
33
e2e/dashboards-suite/general-dashboards.spec.ts
Normal file
33
e2e/dashboards-suite/general-dashboards.spec.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const PAGE_UNDER_TEST = 'edediimbjhdz4b/a-tall-dashboard';
|
||||
|
||||
describe('Dashboards', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('should restore scroll position', () => {
|
||||
e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST });
|
||||
e2e.components.Panels.Panel.title('Panel #1').should('be.visible');
|
||||
|
||||
// scroll to the bottom
|
||||
e2e.pages.Dashboard.DashNav.navV2()
|
||||
.parent()
|
||||
.parent() // Note, this will probably fail when we change the custom scrollbars
|
||||
.scrollTo('bottom', {
|
||||
timeout: 5 * 1000,
|
||||
});
|
||||
|
||||
// The last panel should be visible...
|
||||
e2e.components.Panels.Panel.title('Panel #50').should('be.visible');
|
||||
|
||||
// Then we open and close the panel editor
|
||||
e2e.components.Panels.Panel.menu('Panel #50').click({ force: true }); // it only shows on hover
|
||||
e2e.components.Panels.Panel.menuItems('Edit').click();
|
||||
e2e.components.PanelEditor.applyButton().click();
|
||||
|
||||
// And the last panel should still be visible!
|
||||
e2e.components.Panels.Panel.title('Panel #50').should('be.visible');
|
||||
});
|
||||
});
|
@ -4,7 +4,6 @@ import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { match, Router } from 'react-router-dom';
|
||||
import { useEffectOnce } from 'react-use';
|
||||
import { Props as AutoSizerProps } from 'react-virtualized-auto-sizer';
|
||||
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
|
||||
@ -71,18 +70,6 @@ jest.mock('@grafana/runtime', () => ({
|
||||
getPluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }),
|
||||
}));
|
||||
|
||||
jest.mock('react-virtualized-auto-sizer', () => {
|
||||
// The size of the children need to be small enough to be outside the view.
|
||||
// So it does not trigger the query to be run by the PanelQueryRunner.
|
||||
return ({ children }: AutoSizerProps) =>
|
||||
children({
|
||||
height: 1,
|
||||
scaledHeight: 1,
|
||||
scaledWidth: 1,
|
||||
width: 1,
|
||||
});
|
||||
});
|
||||
|
||||
function getTestDashboard(overrides?: Partial<Dashboard>, metaOverrides?: Partial<DashboardMeta>): DashboardModel {
|
||||
const data = Object.assign(
|
||||
{
|
||||
|
@ -3,7 +3,6 @@ import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { useEffectOnce } from 'react-use';
|
||||
import { Props as AutoSizerProps } from 'react-virtualized-auto-sizer';
|
||||
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
|
||||
|
||||
import { TextBoxVariableModel } from '@grafana/data';
|
||||
@ -42,18 +41,6 @@ jest.mock('app/features/dashboard/dashgrid/LazyLoader', () => {
|
||||
return { LazyLoader };
|
||||
});
|
||||
|
||||
jest.mock('react-virtualized-auto-sizer', () => {
|
||||
// The size of the children need to be small enough to be outside the view.
|
||||
// So it does not trigger the query to be run by the PanelQueryRunner.
|
||||
return ({ children }: AutoSizerProps) =>
|
||||
children({
|
||||
scaledHeight: 1,
|
||||
height: 1,
|
||||
scaledWidth: 1,
|
||||
width: 1,
|
||||
});
|
||||
});
|
||||
|
||||
function setup(props: Props) {
|
||||
const context = getGrafanaContextMock();
|
||||
const store = configureStore({});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import React, { PureComponent, CSSProperties } from 'react';
|
||||
import ReactGridLayout, { ItemCallback } from 'react-grid-layout';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { config } from '@grafana/runtime';
|
||||
@ -31,6 +30,7 @@ export interface Props {
|
||||
|
||||
interface State {
|
||||
panelFilter?: RegExp;
|
||||
width: number;
|
||||
}
|
||||
|
||||
export class DashboardGrid extends PureComponent<Props, State> {
|
||||
@ -47,6 +47,7 @@ export class DashboardGrid extends PureComponent<Props, State> {
|
||||
super(props);
|
||||
this.state = {
|
||||
panelFilter: undefined,
|
||||
width: document.body.clientWidth, // initial very rough estimate
|
||||
};
|
||||
}
|
||||
|
||||
@ -291,22 +292,41 @@ export class DashboardGrid extends PureComponent<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
private resizeObserver?: ResizeObserver;
|
||||
private rootEl: HTMLDivElement | null = null;
|
||||
onMeasureRef = (rootEl: HTMLDivElement | null) => {
|
||||
if (!rootEl) {
|
||||
if (this.rootEl && this.resizeObserver) {
|
||||
this.resizeObserver.unobserve(this.rootEl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.rootEl = rootEl;
|
||||
this.resizeObserver = new ResizeObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
this.setState({ width: entry.contentRect.width });
|
||||
});
|
||||
});
|
||||
|
||||
this.resizeObserver.observe(rootEl);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isEditable, dashboard } = this.props;
|
||||
const { width } = this.state;
|
||||
|
||||
if (dashboard.panels.length === 0) {
|
||||
return <DashboardEmpty dashboard={dashboard} canCreate={isEditable} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have a parent with "flex: 1 1 0" we need to reset it to "flex: 1 1 auto" to have the AutoSizer
|
||||
* properly working. For more information go here:
|
||||
* https://github.com/bvaughn/react-virtualized/blob/master/docs/usingAutoSizer.md#can-i-use-autosizer-within-a-flex-container
|
||||
*
|
||||
* pos: rel + z-index is required to create a new stacking context to contain the escalating z-indexes of the panels
|
||||
*/
|
||||
const draggable = width <= config.theme2.breakpoints.values.md ? false : isEditable;
|
||||
|
||||
// pos: rel + z-index is required to create a new stacking context to contain
|
||||
// the escalating z-indexes of the panels
|
||||
return (
|
||||
<div
|
||||
ref={this.onMeasureRef}
|
||||
style={{
|
||||
flex: '1 1 auto',
|
||||
position: 'relative',
|
||||
@ -314,46 +334,27 @@ export class DashboardGrid extends PureComponent<Props, State> {
|
||||
display: this.props.editPanel ? 'none' : undefined,
|
||||
}}
|
||||
>
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => {
|
||||
if (width === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Disable draggable if mobile device, solving an issue with unintentionally
|
||||
// moving panels. https://github.com/grafana/grafana/issues/18497
|
||||
const draggable = width <= config.theme2.breakpoints.values.md ? false : isEditable;
|
||||
|
||||
return (
|
||||
/**
|
||||
* The children is using a width of 100% so we need to guarantee that it is wrapped
|
||||
* in an element that has the calculated size given by the AutoSizer. The AutoSizer
|
||||
* has a width of 0 and will let its content overflow its div.
|
||||
*/
|
||||
<div style={{ width: width, height: '100%' }} ref={this.onGetWrapperDivRef}>
|
||||
<ReactGridLayout
|
||||
width={width}
|
||||
isDraggable={draggable}
|
||||
isResizable={isEditable}
|
||||
containerPadding={[0, 0]}
|
||||
useCSSTransforms={true}
|
||||
margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
|
||||
cols={GRID_COLUMN_COUNT}
|
||||
rowHeight={GRID_CELL_HEIGHT}
|
||||
draggableHandle=".grid-drag-handle"
|
||||
draggableCancel=".grid-drag-cancel"
|
||||
layout={this.buildLayout()}
|
||||
onDragStop={this.onDragStop}
|
||||
onResize={this.onResize}
|
||||
onResizeStop={this.onResizeStop}
|
||||
onLayoutChange={this.onLayoutChange}
|
||||
>
|
||||
{this.renderPanels(width, draggable)}
|
||||
</ReactGridLayout>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</AutoSizer>
|
||||
<div style={{ width: width, height: '100%' }} ref={this.onGetWrapperDivRef}>
|
||||
<ReactGridLayout
|
||||
width={width}
|
||||
isDraggable={draggable}
|
||||
isResizable={isEditable}
|
||||
containerPadding={[0, 0]}
|
||||
useCSSTransforms={true}
|
||||
margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
|
||||
cols={GRID_COLUMN_COUNT}
|
||||
rowHeight={GRID_CELL_HEIGHT}
|
||||
draggableHandle=".grid-drag-handle"
|
||||
draggableCancel=".grid-drag-cancel"
|
||||
layout={this.buildLayout()}
|
||||
onDragStop={this.onDragStop}
|
||||
onResize={this.onResize}
|
||||
onResizeStop={this.onResizeStop}
|
||||
onLayoutChange={this.onLayoutChange}
|
||||
>
|
||||
{this.renderPanels(width, draggable)}
|
||||
</ReactGridLayout>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user