Dashboard: Scroll to panel for custom grid (#103270)

This commit is contained in:
Torkel Ödegaard
2025-04-03 10:35:34 +02:00
committed by GitHub
parent 7165bc553a
commit 5bc053730b
5 changed files with 27 additions and 6 deletions
@@ -24,6 +24,7 @@ ButtonGroup.displayName = 'ButtonGroup';
const getStyles = (theme: GrafanaTheme2) => ({
wrapper: css({
display: 'flex',
gap: 1,
'> .button-group:not(:first-child) > button, > button:not(:first-child)': {
borderTopLeftRadius: 0,
@@ -12,6 +12,7 @@ import {
PanelDescriptionTextArea,
PanelFrameTitleInput,
} from '../panel-edit/getPanelFrameOptions';
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
import { AutoGridItem } from '../scene/layout-responsive-grid/ResponsiveGridItem';
import { BulkActionElement } from '../scene/types/BulkActionElement';
import { isDashboardLayoutItem } from '../scene/types/DashboardLayoutItem';
@@ -101,6 +102,9 @@ export class VizPanelEditableElement implements EditableDashboardElement, BulkAc
if (this.panel.parent instanceof AutoGridItem) {
this.panel.parent.scrollIntoView();
}
if (this.panel.parent instanceof DashboardGridItem) {
this.panel.parent.scrollIntoView();
}
}
}
@@ -1,4 +1,5 @@
import { isEqual } from 'lodash';
import React from 'react';
import { Unsubscribable } from 'rxjs';
import {
@@ -20,6 +21,7 @@ import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components
import { getCloneKey } from '../../utils/clone';
import { getMultiVariableValues } from '../../utils/utils';
import { scrollCanvasElementIntoView } from '../layouts-shared/scrollCanvasElementIntoView';
import { DashboardLayoutItem } from '../types/DashboardLayoutItem';
import { DashboardRepeatsProcessedEvent } from '../types/DashboardRepeatsProcessedEvent';
@@ -47,9 +49,9 @@ export class DashboardGridItem
protected _variableDependency = new DashboardGridItemVariableDependencyHandler(this);
public readonly isDashboardLayoutItem = true;
public containerRef = React.createRef<HTMLDivElement>();
private _prevRepeatValues?: VariableValueSingle[];
private _gridSizeSub: Unsubscribable | undefined;
public constructor(state: DashboardGridItemState) {
@@ -249,4 +251,8 @@ export class DashboardGridItem
public isRepeated(): boolean {
return this.state.variableName !== undefined;
}
public scrollIntoView() {
scrollCanvasElementIntoView(this, this.containerRef);
}
}
@@ -14,7 +14,11 @@ export function DashboardGridItemRenderer({ model }: SceneComponentProps<Dashboa
if (!variableName) {
if (body instanceof VizPanel) {
return <body.Component model={body} key={body.state.key} />;
return (
<div className={panelWrapper} ref={model.containerRef}>
<body.Component model={body} key={body.state.key} />
</div>
);
}
}
@@ -23,9 +27,9 @@ export function DashboardGridItemRenderer({ model }: SceneComponentProps<Dashboa
}
return (
<div className={layoutStyle}>
<div className={layoutStyle} ref={model.containerRef}>
{repeatedPanels.map((panel) => (
<div className={itemStyle} key={panel.state.key}>
<div className={panelWrapper} key={panel.state.key}>
<panel.Component model={panel} key={panel.state.key} />
</div>
))}
@@ -75,8 +79,10 @@ function useLayoutStyle(direction: RepeatDirection, itemCount: number, maxPerRow
}, [direction, itemCount, maxPerRow, itemHeight]);
}
const itemStyle = css({
const panelWrapper = css({
display: 'flex',
flexGrow: 1,
position: 'relative',
width: '100%',
height: '100%',
});
@@ -1,4 +1,4 @@
import { SceneObject } from '@grafana/scenes';
import { SceneGridRow, SceneObject } from '@grafana/scenes';
import { RowItem } from '../layout-rows/RowItem';
import { TabItem } from '../layout-tabs/TabItem';
@@ -21,6 +21,10 @@ export function scrollCanvasElementIntoView(sceneObject: SceneObject, ref: React
parent.onCollapseToggle();
}
if (parent instanceof SceneGridRow && parent.state.isCollapsed) {
parent.onCollapseToggle();
}
if (parent instanceof TabItem) {
const tabsManager = parent.parent;
if (tabsManager instanceof TabsLayoutManager && tabsManager.getCurrentTab() !== parent) {