mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardScene: Transform scene repeats to snapshot (#76428)
* WIP : Transform scene panel repeats to snapshot * Set scoped vars correctly on repeated panel snapshot * Row repeats snapshots * Fix scoped vars for repeated rows * Tests * Fix merge
This commit is contained in:
parent
2a7b6a533e
commit
120247667b
@ -3018,7 +3018,10 @@ exports[`better eslint`] = {
|
||||
"public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "3"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "4"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "5"]
|
||||
],
|
||||
"public/app/features/dashboard-scene/utils/test-utils.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
|
@ -1,19 +1,8 @@
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import {
|
||||
EmbeddedScene,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneTimeRange,
|
||||
SceneVariableSet,
|
||||
TestVariable,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants';
|
||||
import { SceneGridLayout } from '@grafana/scenes';
|
||||
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
import { PanelRepeaterGridItem, RepeatDirection } from './PanelRepeaterGridItem';
|
||||
import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils';
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
@ -22,7 +11,7 @@ setPluginImportUtils({
|
||||
|
||||
describe('PanelRepeaterGridItem', () => {
|
||||
it('Given scene with variable with 2 values', async () => {
|
||||
const { scene, repeater } = buildScene({ variableQueryTime: 0 });
|
||||
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0 });
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
@ -38,7 +27,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('Should wait for variable to load', async () => {
|
||||
const { scene, repeater } = buildScene({ variableQueryTime: 1 });
|
||||
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 1 });
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
@ -50,7 +39,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('Should adjust container height to fit panels direction is horizontal', async () => {
|
||||
const { scene, repeater } = buildScene({ variableQueryTime: 0, maxPerRow: 2, itemHeight: 10 });
|
||||
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, maxPerRow: 2, itemHeight: 10 });
|
||||
|
||||
const layoutForceRender = jest.fn();
|
||||
(scene.state.body as SceneGridLayout).forceRender = layoutForceRender;
|
||||
@ -64,7 +53,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('Should adjust container height to fit panels when direction is vertical', async () => {
|
||||
const { scene, repeater } = buildScene({ variableQueryTime: 0, itemHeight: 10, repeatDirection: 'v' });
|
||||
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, itemHeight: 10, repeatDirection: 'v' });
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
@ -73,7 +62,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('Should adjust itemHeight when container is resized, direction horizontal', async () => {
|
||||
const { scene, repeater } = buildScene({
|
||||
const { scene, repeater } = buildPanelRepeaterScene({
|
||||
variableQueryTime: 0,
|
||||
itemHeight: 10,
|
||||
repeatDirection: 'h',
|
||||
@ -92,7 +81,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('Should adjust itemHeight when container is resized, direction vertical', async () => {
|
||||
const { scene, repeater } = buildScene({
|
||||
const { scene, repeater } = buildPanelRepeaterScene({
|
||||
variableQueryTime: 0,
|
||||
itemHeight: 10,
|
||||
repeatDirection: 'v',
|
||||
@ -110,7 +99,7 @@ describe('PanelRepeaterGridItem', () => {
|
||||
});
|
||||
|
||||
it('When updating variable should update repeats', async () => {
|
||||
const { scene, repeater, variable } = buildScene({ variableQueryTime: 0 });
|
||||
const { scene, repeater, variable } = buildPanelRepeaterScene({ variableQueryTime: 0 });
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
@ -119,57 +108,3 @@ describe('PanelRepeaterGridItem', () => {
|
||||
expect(repeater.state.repeatedPanels?.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
interface SceneOptions {
|
||||
variableQueryTime: number;
|
||||
maxPerRow?: number;
|
||||
itemHeight?: number;
|
||||
repeatDirection?: RepeatDirection;
|
||||
}
|
||||
|
||||
function buildScene(options: SceneOptions) {
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
variableName: 'server',
|
||||
repeatedPanels: [],
|
||||
repeatDirection: options.repeatDirection,
|
||||
maxPerRow: options.maxPerRow,
|
||||
itemHeight: options.itemHeight,
|
||||
source: new VizPanel({
|
||||
title: 'Panel $server',
|
||||
pluginId: 'timeseries',
|
||||
}),
|
||||
});
|
||||
|
||||
const variable = new TestVariable({
|
||||
name: 'server',
|
||||
query: 'A.*',
|
||||
value: ALL_VARIABLE_VALUE,
|
||||
text: ALL_VARIABLE_TEXT,
|
||||
isMulti: true,
|
||||
includeAll: true,
|
||||
delayMs: options.variableQueryTime,
|
||||
optionsToReturn: [
|
||||
{ label: 'A', value: '1' },
|
||||
{ label: 'B', value: '2' },
|
||||
{ label: 'C', value: '3' },
|
||||
{ label: 'D', value: '4' },
|
||||
{ label: 'E', value: '5' },
|
||||
],
|
||||
});
|
||||
|
||||
const scene = new EmbeddedScene({
|
||||
$timeRange: new SceneTimeRange({ from: 'now-6h', to: 'now' }),
|
||||
$variables: new SceneVariableSet({
|
||||
variables: [variable],
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridRow({
|
||||
children: [repeater],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
return { scene, repeater, variable };
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItem
|
||||
this.publishEvent(new DashboardRepeatsProcessedEvent({ source: this }), true);
|
||||
}
|
||||
|
||||
private getMaxPerRow(): number {
|
||||
public getMaxPerRow(): number {
|
||||
return this.state.maxPerRow ?? 4;
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,6 @@ export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike {
|
||||
|
||||
if (panel.repeat) {
|
||||
const repeatDirection = panel.repeatDirection ?? 'h';
|
||||
|
||||
return new PanelRepeaterGridItem({
|
||||
key: `grid-item-${panel.id}`,
|
||||
x: panel.gridPos.x,
|
||||
|
@ -31,7 +31,7 @@ import { reduceTransformRegistryItem } from 'app/features/transformers/editors/R
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils';
|
||||
import { getVizPanelKeyForPanelId } from '../utils/utils';
|
||||
|
||||
import { GRAFANA_DATASOURCE_REF } from './const';
|
||||
@ -44,7 +44,13 @@ import {
|
||||
buildGridItemForPanel,
|
||||
transformSaveModelToScene,
|
||||
} from './transformSaveModelToScene';
|
||||
import { gridItemToPanel, transformSceneToSaveModel, trimDashboardForSnapshot } from './transformSceneToSaveModel';
|
||||
import {
|
||||
gridItemToPanel,
|
||||
gridRowToSaveModel,
|
||||
panelRepeaterToPanels,
|
||||
transformSceneToSaveModel,
|
||||
trimDashboardForSnapshot,
|
||||
} from './transformSceneToSaveModel';
|
||||
|
||||
standardTransformersRegistry.setInit(() => [reduceTransformRegistryItem]);
|
||||
setPluginImportUtils({
|
||||
@ -597,6 +603,107 @@ describe('transformSceneToSaveModel', () => {
|
||||
expect(snapshot.panels?.[4].collapsed).toEqual(true);
|
||||
});
|
||||
|
||||
describe('repeats', () => {
|
||||
it('handles repeated panels', async () => {
|
||||
const { scene, repeater } = buildPanelRepeaterScene({ variableQueryTime: 0, numberOfOptions: 2 });
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
expect(repeater.state.repeatedPanels?.length).toBe(2);
|
||||
const result = panelRepeaterToPanels(repeater, true);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
|
||||
// @ts-expect-error
|
||||
expect(result[0].scopedVars).toEqual({
|
||||
server: {
|
||||
text: 'A',
|
||||
value: '1',
|
||||
},
|
||||
});
|
||||
// @ts-expect-error
|
||||
expect(result[1].scopedVars).toEqual({
|
||||
server: {
|
||||
text: 'B',
|
||||
value: '2',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result[0].title).toEqual('Panel $server');
|
||||
expect(result[1].title).toEqual('Panel $server');
|
||||
});
|
||||
|
||||
it('handles row repeats ', () => {
|
||||
const { scene, row } = buildPanelRepeaterScene({
|
||||
variableQueryTime: 0,
|
||||
numberOfOptions: 2,
|
||||
useRowRepeater: true,
|
||||
usePanelRepeater: false,
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
let panels: Panel[] = [];
|
||||
gridRowToSaveModel(row, panels, true);
|
||||
|
||||
expect(panels).toHaveLength(2);
|
||||
expect(panels[0].repeat).toBe('handler');
|
||||
|
||||
// @ts-expect-error
|
||||
expect(panels[0].scopedVars).toEqual({
|
||||
handler: {
|
||||
text: 'AA',
|
||||
value: '11',
|
||||
},
|
||||
});
|
||||
|
||||
expect(panels[1].title).toEqual('Panel $server');
|
||||
expect(panels[1].gridPos).toEqual({ x: 0, y: 0, w: 10, h: 10 });
|
||||
});
|
||||
|
||||
it('handles row repeats with panel repeater', () => {
|
||||
const { scene, row } = buildPanelRepeaterScene({
|
||||
variableQueryTime: 0,
|
||||
numberOfOptions: 2,
|
||||
useRowRepeater: true,
|
||||
usePanelRepeater: true,
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
let panels: Panel[] = [];
|
||||
gridRowToSaveModel(row, panels, true);
|
||||
|
||||
expect(panels[0].repeat).toBe('handler');
|
||||
|
||||
// @ts-expect-error
|
||||
expect(panels[0].scopedVars).toEqual({
|
||||
handler: {
|
||||
text: 'AA',
|
||||
value: '11',
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
expect(panels[1].scopedVars).toEqual({
|
||||
server: {
|
||||
text: 'A',
|
||||
value: '1',
|
||||
},
|
||||
});
|
||||
// @ts-expect-error
|
||||
expect(panels[2].scopedVars).toEqual({
|
||||
server: {
|
||||
text: 'B',
|
||||
value: '2',
|
||||
},
|
||||
});
|
||||
|
||||
expect(panels[1].title).toEqual('Panel $server');
|
||||
expect(panels[2].title).toEqual('Panel $server');
|
||||
});
|
||||
});
|
||||
|
||||
describe('trimDashboardForSnapshot', () => {
|
||||
let snapshot: Dashboard = {} as Dashboard;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { isEmptyObject, TimeRange } from '@grafana/data';
|
||||
import { isEmptyObject, ScopedVars, TimeRange } from '@grafana/data';
|
||||
import {
|
||||
SceneDataLayers,
|
||||
SceneGridItem,
|
||||
@ -10,6 +10,7 @@ import {
|
||||
SceneDataTransformer,
|
||||
SceneVariableSet,
|
||||
AdHocFilterSet,
|
||||
LocalValueVariable,
|
||||
} from '@grafana/scenes';
|
||||
import {
|
||||
AnnotationQuery,
|
||||
@ -45,7 +46,7 @@ export function transformSceneToSaveModel(scene: DashboardScene, isSnapshot = fa
|
||||
const data = state.$data;
|
||||
const variablesSet = state.$variables;
|
||||
const body = state.body;
|
||||
const panels: Panel[] = [];
|
||||
let panels: Panel[] = [];
|
||||
|
||||
let variables: VariableModel[] = [];
|
||||
|
||||
@ -55,9 +56,13 @@ export function transformSceneToSaveModel(scene: DashboardScene, isSnapshot = fa
|
||||
panels.push(gridItemToPanel(child, isSnapshot));
|
||||
}
|
||||
|
||||
if (child instanceof PanelRepeaterGridItem) {
|
||||
panels = panels.concat(panelRepeaterToPanels(child, isSnapshot));
|
||||
}
|
||||
|
||||
if (child instanceof SceneGridRow) {
|
||||
// Skip repeat clones
|
||||
if (child.state.key!.indexOf('-clone-') > 0) {
|
||||
// Skip repeat clones or when generating a snapshot
|
||||
if (child.state.key!.indexOf('-clone-') > 0 && !isSnapshot) {
|
||||
continue;
|
||||
}
|
||||
gridRowToSaveModel(child, panels, isSnapshot);
|
||||
@ -151,7 +156,6 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
|
||||
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
vizPanel = gridItem.state.source;
|
||||
|
||||
x = gridItem.state.x ?? 0;
|
||||
y = gridItem.state.y ?? 0;
|
||||
w = gridItem.state.width ?? 0;
|
||||
@ -171,6 +175,7 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
|
||||
fieldConfig: (vizPanel.state.fieldConfig as FieldConfigSource) ?? { defaults: {}, overrides: [] },
|
||||
transformations: [],
|
||||
transparent: vizPanel.state.displayMode === 'transparent',
|
||||
...vizPanelDataToPanel(vizPanel, isSnapshot),
|
||||
};
|
||||
|
||||
const panelTime = vizPanel.state.$timeRange;
|
||||
@ -181,8 +186,22 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
|
||||
panel.hideTimeOverride = panelTime.state.hideTimeOverride;
|
||||
}
|
||||
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
panel.repeat = gridItem.state.variableName;
|
||||
panel.maxPerRow = gridItem.state.maxPerRow;
|
||||
panel.repeatDirection = gridItem.getRepeatDirection();
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
function vizPanelDataToPanel(
|
||||
vizPanel: VizPanel,
|
||||
isSnapshot = false
|
||||
): Pick<Panel, 'datasource' | 'targets' | 'maxDataPoints' | 'transformations'> {
|
||||
const dataProvider = vizPanel.state.$data;
|
||||
|
||||
const panel: Pick<Panel, 'datasource' | 'targets' | 'maxDataPoints' | 'transformations'> = {};
|
||||
// Dashboard datasource handling
|
||||
if (dataProvider instanceof ShareQueryDataProvider) {
|
||||
panel.datasource = {
|
||||
@ -252,16 +271,64 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
|
||||
];
|
||||
}
|
||||
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
panel.repeat = gridItem.state.variableName;
|
||||
panel.maxPerRow = gridItem.state.maxPerRow;
|
||||
panel.repeatDirection = gridItem.getRepeatDirection();
|
||||
}
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
export function panelRepeaterToPanels(repeater: PanelRepeaterGridItem, isSnapshot = false): Panel[] {
|
||||
if (!isSnapshot) {
|
||||
return [gridItemToPanel(repeater)];
|
||||
} else {
|
||||
if (repeater.state.repeatedPanels) {
|
||||
const itemHeight = repeater.state.itemHeight ?? 10;
|
||||
const rowCount = Math.ceil(repeater.state.repeatedPanels!.length / repeater.getMaxPerRow());
|
||||
const columnCount = Math.ceil(repeater.state.repeatedPanels!.length / rowCount);
|
||||
const w = 24 / columnCount;
|
||||
const h = itemHeight;
|
||||
const panels = repeater.state.repeatedPanels!.map((panel, index) => {
|
||||
let x = 0,
|
||||
y = 0;
|
||||
if (repeater.state.repeatDirection === 'v') {
|
||||
x = repeater.state.x!;
|
||||
y = index * h;
|
||||
} else {
|
||||
x = (index % columnCount) * w;
|
||||
y = repeater.state.y! + Math.floor(index / columnCount) * h;
|
||||
}
|
||||
|
||||
const gridPos = { x, y, w, h };
|
||||
|
||||
const localVariable = panel.state.$variables!.getByName(repeater.state.variableName!) as LocalValueVariable;
|
||||
|
||||
const result: Panel = {
|
||||
id: getPanelIdForVizPanel(panel),
|
||||
type: panel.state.pluginId,
|
||||
title: panel.state.title,
|
||||
gridPos,
|
||||
options: panel.state.options,
|
||||
fieldConfig: (panel.state.fieldConfig as FieldConfigSource) ?? { defaults: {}, overrides: [] },
|
||||
transformations: [],
|
||||
transparent: panel.state.displayMode === 'transparent',
|
||||
// @ts-expect-error scopedVars are runtime only properties, not part of the persisted Dashboardmodel
|
||||
scopedVars: {
|
||||
[repeater.state.variableName!]: {
|
||||
text: localVariable?.state.text,
|
||||
value: localVariable?.state.value,
|
||||
},
|
||||
},
|
||||
...vizPanelDataToPanel(panel, isSnapshot),
|
||||
};
|
||||
return result;
|
||||
});
|
||||
|
||||
return panels;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function gridRowToSaveModel(gridRow: SceneGridRow, panelsArray: Array<Panel | RowPanel>, isSnapshot = false) {
|
||||
const collapsed = Boolean(gridRow.state.isCollapsed);
|
||||
const rowPanel: RowPanel = {
|
||||
type: 'row',
|
||||
id: getPanelIdForVizPanel(gridRow),
|
||||
@ -272,21 +339,52 @@ export function gridRowToSaveModel(gridRow: SceneGridRow, panelsArray: Array<Pan
|
||||
w: gridRow.state.width ?? 24,
|
||||
h: gridRow.state.height ?? 1,
|
||||
},
|
||||
collapsed: Boolean(gridRow.state.isCollapsed),
|
||||
collapsed,
|
||||
panels: [],
|
||||
};
|
||||
|
||||
if (gridRow.state.$behaviors?.length) {
|
||||
const behavior = gridRow.state.$behaviors[0];
|
||||
|
||||
if (behavior instanceof RowRepeaterBehavior) {
|
||||
rowPanel.repeat = behavior.state.variableName;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSnapshot) {
|
||||
// Rows that are repeated has SceneVariableSet attached to them.
|
||||
if (gridRow.state.$variables) {
|
||||
const localVariable = gridRow.state.$variables;
|
||||
const scopedVars: ScopedVars = (localVariable.state.variables as LocalValueVariable[]).reduce((acc, variable) => {
|
||||
return {
|
||||
...acc,
|
||||
[variable.state.name]: {
|
||||
text: variable.state.text,
|
||||
value: variable.state.value,
|
||||
},
|
||||
};
|
||||
}, {});
|
||||
// @ts-expect-error
|
||||
rowPanel.scopedVars = scopedVars;
|
||||
}
|
||||
}
|
||||
|
||||
panelsArray.push(rowPanel);
|
||||
|
||||
const panelsInsideRow = gridRow.state.children.map((c) => gridItemToPanel(c, isSnapshot));
|
||||
let panelsInsideRow: Panel[] = [];
|
||||
|
||||
if (isSnapshot) {
|
||||
gridRow.state.children.forEach((c) => {
|
||||
if (c instanceof PanelRepeaterGridItem) {
|
||||
// Perform snapshot only for uncollapsed rows
|
||||
panelsInsideRow = panelsInsideRow.concat(panelRepeaterToPanels(c, !collapsed));
|
||||
} else {
|
||||
// Perform snapshot only for uncollapsed panels
|
||||
panelsInsideRow.push(gridItemToPanel(c, !collapsed));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
panelsInsideRow = gridRow.state.children.map((c) => gridItemToPanel(c));
|
||||
}
|
||||
|
||||
if (gridRow.state.isCollapsed) {
|
||||
rowPanel.panels = panelsInsideRow;
|
||||
|
@ -1,7 +1,23 @@
|
||||
import { DeepPartial, SceneDeactivationHandler, SceneObject } from '@grafana/scenes';
|
||||
import {
|
||||
DeepPartial,
|
||||
EmbeddedScene,
|
||||
SceneDeactivationHandler,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObject,
|
||||
SceneTimeRange,
|
||||
SceneVariableSet,
|
||||
TestVariable,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
import { PanelRepeaterGridItem, RepeatDirection } from '../scene/PanelRepeaterGridItem';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
|
||||
export function setupLoadDashboardMock(rsp: DeepPartial<DashboardDTO>) {
|
||||
const loadDashboardMock = jest.fn().mockResolvedValue(rsp);
|
||||
setDashboardLoaderSrv({
|
||||
@ -69,3 +85,101 @@ export function activateFullSceneTree(scene: SceneObject): SceneDeactivationHand
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
interface SceneOptions {
|
||||
variableQueryTime: number;
|
||||
maxPerRow?: number;
|
||||
itemHeight?: number;
|
||||
repeatDirection?: RepeatDirection;
|
||||
x?: number;
|
||||
y?: number;
|
||||
numberOfOptions?: number;
|
||||
usePanelRepeater?: boolean;
|
||||
useRowRepeater?: boolean;
|
||||
}
|
||||
|
||||
export function buildPanelRepeaterScene(options: SceneOptions) {
|
||||
const defaults = { usePanelRepeater: true, ...options };
|
||||
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
variableName: 'server',
|
||||
repeatedPanels: [],
|
||||
repeatDirection: options.repeatDirection,
|
||||
maxPerRow: options.maxPerRow,
|
||||
itemHeight: options.itemHeight,
|
||||
source: new VizPanel({
|
||||
title: 'Panel $server',
|
||||
pluginId: 'timeseries',
|
||||
}),
|
||||
x: options.x || 0,
|
||||
y: options.y || 0,
|
||||
});
|
||||
|
||||
const gridItem = new SceneGridItem({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 10,
|
||||
body: new VizPanel({ title: 'Panel $server', pluginId: 'timeseries' }),
|
||||
});
|
||||
|
||||
const rowChildren = defaults.usePanelRepeater ? repeater : gridItem;
|
||||
|
||||
const row = new SceneGridRow({
|
||||
$behaviors: defaults.useRowRepeater
|
||||
? [
|
||||
new RowRepeaterBehavior({
|
||||
variableName: 'handler',
|
||||
sources: [rowChildren],
|
||||
}),
|
||||
]
|
||||
: [],
|
||||
children: defaults.useRowRepeater ? [] : [rowChildren],
|
||||
});
|
||||
|
||||
const panelRepeatVariable = new TestVariable({
|
||||
name: 'server',
|
||||
query: 'A.*',
|
||||
value: ALL_VARIABLE_VALUE,
|
||||
text: ALL_VARIABLE_TEXT,
|
||||
isMulti: true,
|
||||
includeAll: true,
|
||||
delayMs: options.variableQueryTime,
|
||||
optionsToReturn: [
|
||||
{ label: 'A', value: '1' },
|
||||
{ label: 'B', value: '2' },
|
||||
{ label: 'C', value: '3' },
|
||||
{ label: 'D', value: '4' },
|
||||
{ label: 'E', value: '5' },
|
||||
].slice(0, options.numberOfOptions),
|
||||
});
|
||||
|
||||
const rowRepeatVariable = new TestVariable({
|
||||
name: 'handler',
|
||||
query: 'A.*',
|
||||
value: ALL_VARIABLE_VALUE,
|
||||
text: ALL_VARIABLE_TEXT,
|
||||
isMulti: true,
|
||||
includeAll: true,
|
||||
delayMs: options.variableQueryTime,
|
||||
optionsToReturn: [
|
||||
{ label: 'AA', value: '11' },
|
||||
{ label: 'BB', value: '22' },
|
||||
{ label: 'CC', value: '33' },
|
||||
{ label: 'DD', value: '44' },
|
||||
{ label: 'EE', value: '55' },
|
||||
].slice(0, options.numberOfOptions),
|
||||
});
|
||||
|
||||
const scene = new EmbeddedScene({
|
||||
$timeRange: new SceneTimeRange({ from: 'now-6h', to: 'now' }),
|
||||
$variables: new SceneVariableSet({
|
||||
variables: [panelRepeatVariable, rowRepeatVariable],
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [row],
|
||||
}),
|
||||
});
|
||||
|
||||
return { scene, repeater, row, variable: panelRepeatVariable };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user