diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx index 47c5ec2146a..bf0e1df1825 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx @@ -107,6 +107,11 @@ function getStyles(theme: GrafanaTheme2) { flexDirection: 'column', maxWidth: '890px', gap: theme.spacing.gridSize * 4, + paddingTop: theme.spacing(2), + + [theme.breakpoints.up('sm')]: { + paddingTop: theme.spacing(12), + }, }), containerBox: css({ label: 'container-box', diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index 532f1e3b824..90e2a3e33d4 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -24,12 +24,7 @@ export interface Props { viewPanel: PanelModel | null; hidePanelMenus?: boolean; } - -export interface State { - isLayoutInitialized: boolean; -} - -export class DashboardGrid extends PureComponent { +export class DashboardGrid extends PureComponent { private panelMap: { [key: string]: PanelModel } = {}; private eventSubs = new Subscription(); private windowHeight = 1200; @@ -37,13 +32,10 @@ export class DashboardGrid extends PureComponent { private gridWidth = 0; /** Used to keep track of mobile panel layout position */ private lastPanelBottom = 0; + private isLayoutInitialized = false; constructor(props: Props) { super(props); - - this.state = { - isLayoutInitialized: false, - }; } componentDidMount() { @@ -93,15 +85,14 @@ export class DashboardGrid extends PureComponent { onLayoutChange = (newLayout: ReactGridLayout.Layout[]) => { for (const newPos of newLayout) { - this.panelMap[newPos.i!].updateGridPos(newPos, this.state.isLayoutInitialized); + this.panelMap[newPos.i!].updateGridPos(newPos, this.isLayoutInitialized); + } + + if (this.isLayoutInitialized) { + this.isLayoutInitialized = true; } this.props.dashboard.sortPanelsByGridPos(); - - // This is called on grid mount as it can correct invalid initial grid positions - if (!this.state.isLayoutInitialized) { - this.setState({ isLayoutInitialized: true }); - } }; triggerForceUpdate = () => { @@ -210,9 +201,24 @@ export class DashboardGrid extends PureComponent { ); } + /** + * Without this hack the move animations are triggered on initial load and all panels fly into position. + * This can be quite distracting and make the dashboard appear to less snappy. + */ + onGetWrapperDivRef = (ref: HTMLDivElement | null) => { + if (ref) { + setTimeout(() => { + ref.classList.add('react-grid-layout--enable-move-animations'); + }, 50); + } + }; + render() { - const { dashboard, isEditable } = this.props; - const hasPanels = dashboard.panels && dashboard.panels.length > 0; + const { isEditable, dashboard } = this.props; + + if (config.featureToggles.emptyDashboardPage && dashboard.panels.length === 0) { + return ; + } /** * We have a parent with "flex: 1 1 0" we need to reset it to "flex: 1 1 auto" to have the AutoSizer @@ -227,59 +233,23 @@ export class DashboardGrid extends PureComponent { return null; } - const draggable = width <= 769 ? false : isEditable; + // 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; - /* - Disable draggable if mobile device, solving an issue with unintentionally - moving panels. https://github.com/grafana/grafana/issues/18497 - theme.breakpoints.md = 769 - */ - return config.featureToggles.emptyDashboardPage ? ( - hasPanels ? ( - /** - * 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. - */ -
- - {this.renderPanels(width, draggable)} - -
- ) : ( -
- -
- ) - ) : ( + 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. */ -
+