[v11.1.x] Scenes: Fixes issue with panel repeat height calculation (#90232)

Scenes: Fixes issue with panel repeat height calculation (#90221)

* Scenes: Fixes issue with panel repeat height calculation

(cherry picked from commit 5cab595f45)

Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
This commit is contained in:
grafana-delivery-bot[bot]
2024-07-09 18:19:40 +03:00
committed by GitHub
co-authored by kay delaney
parent 0d3206db83
commit d4241ea163
4 changed files with 67 additions and 13 deletions
@@ -1,6 +1,7 @@
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { setPluginImportUtils } from '@grafana/runtime'; import { setPluginImportUtils } from '@grafana/runtime';
import { SceneGridLayout, VizPanel } from '@grafana/scenes'; import { SceneGridLayout, TestVariable, VizPanel } from '@grafana/scenes';
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants';
import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils'; import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils';
@@ -40,7 +41,7 @@ describe('PanelRepeaterGridItem', () => {
expect(repeater.state.repeatedPanels?.length).toBe(5); expect(repeater.state.repeatedPanels?.length).toBe(5);
}); });
it('Should adjust container height to fit panels direction is horizontal', async () => { it('Should adjust container height to fit panels if direction is horizontal', async () => {
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, maxPerRow: 2, itemHeight: 10 }); const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, maxPerRow: 2, itemHeight: 10 });
const layoutForceRender = jest.fn(); const layoutForceRender = jest.fn();
@@ -144,4 +145,56 @@ describe('PanelRepeaterGridItem', () => {
expect(gridItem.getClassName()).toBe(''); expect(gridItem.getClassName()).toBe('');
}); });
it('should have correct height after repeat is performed', () => {
const { scene, repeater } = buildPanelRepeaterScene({
variableQueryTime: 0,
height: 4,
maxPerRow: 4,
repeatDirection: 'h',
numberOfOptions: 5,
});
activateFullSceneTree(scene);
expect(repeater.state.height).toBe(4);
});
it('should have same item height if number of repititions changes', async () => {
const { scene, repeater } = buildPanelRepeaterScene({
variableQueryTime: 0,
height: 4,
maxPerRow: 4,
repeatDirection: 'h',
numberOfOptions: 5,
});
activateFullSceneTree(scene);
scene.state.$variables!.setState({
variables: [
new TestVariable({
name: 'server',
query: 'A.*',
value: ALL_VARIABLE_VALUE,
text: ALL_VARIABLE_TEXT,
isMulti: true,
includeAll: true,
delayMs: 0,
optionsToReturn: [
{ label: 'A', value: '1' },
{ label: 'B', value: '2' },
{ label: 'C', value: '3' },
{ label: 'D', value: '4' },
{ label: 'E', value: '5' },
{ label: 'F', value: '6' },
{ label: 'G', value: '7' },
{ label: 'H', value: '8' },
{ label: 'I', value: '9' },
{ label: 'J', value: '10' },
],
}),
],
});
expect(repeater.state.height).toBe(6);
});
}); });
@@ -163,6 +163,8 @@ export class DashboardGridItem extends SceneObjectBase<DashboardGridItemState> i
return; return;
} }
// Needed to calculate item height
const prevRepeatCount = this._prevRepeatValues?.length ?? values.length;
this._prevRepeatValues = values; this._prevRepeatValues = values;
const panelToRepeat = this.state.body instanceof LibraryVizPanel ? this.state.body.state.panel! : this.state.body; const panelToRepeat = this.state.body instanceof LibraryVizPanel ? this.state.body.state.panel! : this.state.body;
const repeatedPanels: VizPanel[] = []; const repeatedPanels: VizPanel[] = [];
@@ -188,16 +190,15 @@ export class DashboardGridItem extends SceneObjectBase<DashboardGridItemState> i
const direction = this.getRepeatDirection(); const direction = this.getRepeatDirection();
const stateChange: Partial<DashboardGridItemState> = { repeatedPanels: repeatedPanels }; const stateChange: Partial<DashboardGridItemState> = { repeatedPanels: repeatedPanels };
const itemHeight = this.state.itemHeight ?? 10; const prevHeight = this.state.height ?? 0;
const prevHeight = this.state.height; const maxPerRow = direction === 'h' ? this.getMaxPerRow() : 1;
const maxPerRow = this.getMaxPerRow(); const prevRowCount = Math.ceil(prevRepeatCount / maxPerRow);
const newRowCount = Math.ceil(repeatedPanels.length / maxPerRow);
if (direction === 'h') { // If item height is not defined, calculate based on total height and row count
const rowCount = Math.ceil(repeatedPanels.length / maxPerRow); const itemHeight = this.state.itemHeight ?? prevHeight / prevRowCount;
stateChange.height = rowCount * itemHeight; stateChange.itemHeight = itemHeight;
} else { stateChange.height = Math.ceil(newRowCount * itemHeight);
stateChange.height = repeatedPanels.length * itemHeight;
}
this.setState(stateChange); this.setState(stateChange);
@@ -437,7 +437,6 @@ export function buildGridItemForLibPanel(panel: PanelModel) {
x: panel.gridPos.x, x: panel.gridPos.x,
width: panel.gridPos.w, width: panel.gridPos.w,
height: panel.gridPos.h, height: panel.gridPos.h,
itemHeight: panel.gridPos.h,
body, body,
}); });
} }
@@ -502,7 +501,6 @@ export function buildGridItemForPanel(panel: PanelModel): DashboardGridItem {
y: panel.gridPos.y, y: panel.gridPos.y,
width: repeatOptions.repeatDirection === 'h' ? 24 : panel.gridPos.w, width: repeatOptions.repeatDirection === 'h' ? 24 : panel.gridPos.w,
height: panel.gridPos.h, height: panel.gridPos.h,
itemHeight: panel.gridPos.h,
body, body,
maxPerRow: panel.maxPerRow, maxPerRow: panel.maxPerRow,
...repeatOptions, ...repeatOptions,
@@ -96,6 +96,7 @@ interface SceneOptions {
variableQueryTime: number; variableQueryTime: number;
maxPerRow?: number; maxPerRow?: number;
itemHeight?: number; itemHeight?: number;
height?: number;
repeatDirection?: RepeatDirection; repeatDirection?: RepeatDirection;
x?: number; x?: number;
y?: number; y?: number;
@@ -113,6 +114,7 @@ export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel
repeatDirection: options.repeatDirection, repeatDirection: options.repeatDirection,
maxPerRow: options.maxPerRow, maxPerRow: options.maxPerRow,
itemHeight: options.itemHeight, itemHeight: options.itemHeight,
height: options.height,
body: body:
source ?? source ??
new VizPanel({ new VizPanel({