2023-09-29 13:19:03 +02:00
|
|
|
import { CoreApp } from '@grafana/data';
|
2023-11-08 14:08:59 +01:00
|
|
|
import {
|
|
|
|
|
sceneGraph,
|
|
|
|
|
SceneGridItem,
|
|
|
|
|
SceneGridLayout,
|
2023-12-01 16:04:56 +01:00
|
|
|
SceneTimeRange,
|
2023-11-08 14:08:59 +01:00
|
|
|
SceneQueryRunner,
|
|
|
|
|
SceneVariableSet,
|
|
|
|
|
TestVariable,
|
|
|
|
|
VizPanel,
|
2024-02-26 14:48:27 +02:00
|
|
|
SceneGridRow,
|
2023-11-08 14:08:59 +01:00
|
|
|
} from '@grafana/scenes';
|
2024-01-19 10:58:20 +02:00
|
|
|
import { Dashboard } from '@grafana/schema';
|
2023-11-08 14:08:59 +01:00
|
|
|
import appEvents from 'app/core/app_events';
|
2023-10-13 16:24:04 +02:00
|
|
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
2023-11-08 14:08:59 +01:00
|
|
|
import { VariablesChanged } from 'app/features/variables/types';
|
2023-07-12 13:37:26 +02:00
|
|
|
|
2024-02-28 11:13:01 +02:00
|
|
|
import { buildGridItemForPanel, transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
|
2024-01-19 10:58:20 +02:00
|
|
|
import { DecoratedRevisionModel } from '../settings/VersionsEditView';
|
|
|
|
|
import { historySrv } from '../settings/version-history/HistorySrv';
|
2023-12-01 16:04:56 +01:00
|
|
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
2023-12-01 10:07:55 +01:00
|
|
|
import { djb2Hash } from '../utils/djb2Hash';
|
|
|
|
|
|
2023-12-01 16:04:56 +01:00
|
|
|
import { DashboardControls } from './DashboardControls';
|
2023-11-08 14:08:59 +01:00
|
|
|
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
2023-07-12 13:37:26 +02:00
|
|
|
|
2024-01-19 10:58:20 +02:00
|
|
|
jest.mock('../settings/version-history/HistorySrv');
|
|
|
|
|
jest.mock('../serialization/transformSaveModelToScene');
|
2024-02-28 11:13:01 +02:00
|
|
|
jest.mock('../serialization/transformSceneToSaveModel');
|
2024-02-26 14:48:27 +02:00
|
|
|
jest.mock('@grafana/runtime', () => ({
|
|
|
|
|
...jest.requireActual('@grafana/runtime'),
|
|
|
|
|
getDataSourceSrv: () => {
|
|
|
|
|
return {
|
|
|
|
|
getInstanceSettings: jest.fn().mockResolvedValue({ uid: 'ds1' }),
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
}));
|
2024-01-19 10:58:20 +02:00
|
|
|
|
2023-07-12 13:37:26 +02:00
|
|
|
describe('DashboardScene', () => {
|
2023-10-13 16:24:04 +02:00
|
|
|
describe('DashboardSrv.getCurrent compatibility', () => {
|
|
|
|
|
it('Should set to compatibility wrapper', () => {
|
|
|
|
|
const scene = buildTestScene();
|
|
|
|
|
scene.activate();
|
|
|
|
|
|
|
|
|
|
expect(getDashboardSrv().getCurrent()?.uid).toBe('dash-1');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-08-29 14:17:55 +02:00
|
|
|
describe('Editing and discarding', () => {
|
|
|
|
|
describe('Given scene in edit mode', () => {
|
|
|
|
|
let scene: DashboardScene;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
scene = buildTestScene();
|
|
|
|
|
scene.onEnterEditMode();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should set isEditing to true', () => {
|
|
|
|
|
expect(scene.state.isEditing).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('A change to griditem pos should set isDirty true', () => {
|
|
|
|
|
const gridItem = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as SceneGridItem;
|
|
|
|
|
gridItem.setState({ x: 10, y: 0, width: 10, height: 10 });
|
|
|
|
|
|
|
|
|
|
expect(scene.state.isDirty).toBe(true);
|
|
|
|
|
|
2024-02-05 16:08:12 +01:00
|
|
|
scene.exitEditMode({ skipConfirm: true });
|
2023-08-29 14:17:55 +02:00
|
|
|
const gridItem2 = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as SceneGridItem;
|
|
|
|
|
expect(gridItem2.state.x).toBe(0);
|
|
|
|
|
});
|
2023-12-01 16:04:56 +01:00
|
|
|
|
|
|
|
|
it.each`
|
2023-12-15 11:52:34 +01:00
|
|
|
prop | value
|
|
|
|
|
${'title'} | ${'new title'}
|
|
|
|
|
${'description'} | ${'new description'}
|
|
|
|
|
${'tags'} | ${['tag3', 'tag4']}
|
|
|
|
|
${'editable'} | ${false}
|
2024-01-16 12:24:54 +01:00
|
|
|
${'links'} | ${[]}
|
2023-12-01 16:04:56 +01:00
|
|
|
`(
|
|
|
|
|
'A change to $prop should set isDirty true',
|
2024-02-16 14:35:26 +00:00
|
|
|
({ prop, value }: { prop: keyof DashboardSceneState; value: unknown }) => {
|
2023-12-15 11:52:34 +01:00
|
|
|
const prevState = scene.state[prop];
|
2023-12-01 16:04:56 +01:00
|
|
|
scene.setState({ [prop]: value });
|
|
|
|
|
|
|
|
|
|
expect(scene.state.isDirty).toBe(true);
|
|
|
|
|
|
2024-02-05 16:08:12 +01:00
|
|
|
scene.exitEditMode({ skipConfirm: true });
|
2023-12-15 11:52:34 +01:00
|
|
|
expect(scene.state[prop]).toEqual(prevState);
|
2023-12-01 16:04:56 +01:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2023-12-15 11:52:34 +01:00
|
|
|
it('A change to refresh picker interval settings should set isDirty true', () => {
|
2023-12-01 16:04:56 +01:00
|
|
|
const refreshPicker = dashboardSceneGraph.getRefreshPicker(scene)!;
|
2023-12-15 11:52:34 +01:00
|
|
|
const prevState = [...refreshPicker.state.intervals!];
|
2023-12-01 16:04:56 +01:00
|
|
|
refreshPicker.setState({ intervals: ['10s'] });
|
|
|
|
|
|
|
|
|
|
expect(scene.state.isDirty).toBe(true);
|
|
|
|
|
|
2024-02-05 16:08:12 +01:00
|
|
|
scene.exitEditMode({ skipConfirm: true });
|
2023-12-15 11:52:34 +01:00
|
|
|
expect(dashboardSceneGraph.getRefreshPicker(scene)!.state.intervals).toEqual(prevState);
|
2023-12-01 16:04:56 +01:00
|
|
|
});
|
|
|
|
|
|
2023-12-15 11:52:34 +01:00
|
|
|
it('A change to time picker visibility settings should set isDirty true', () => {
|
2024-02-20 08:43:02 +01:00
|
|
|
const dashboardControls = scene.state.controls!;
|
2023-12-15 11:52:34 +01:00
|
|
|
const prevState = dashboardControls.state.hideTimeControls;
|
|
|
|
|
dashboardControls.setState({ hideTimeControls: true });
|
|
|
|
|
|
|
|
|
|
expect(scene.state.isDirty).toBe(true);
|
|
|
|
|
|
2024-02-05 16:08:12 +01:00
|
|
|
scene.exitEditMode({ skipConfirm: true });
|
2024-02-20 08:43:02 +01:00
|
|
|
expect(scene.state.controls!.state.hideTimeControls).toEqual(prevState);
|
2023-12-15 11:52:34 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('A change to time zone should set isDirty true', () => {
|
|
|
|
|
const timeRange = sceneGraph.getTimeRange(scene)!;
|
2023-12-01 16:04:56 +01:00
|
|
|
const prevState = timeRange.state.timeZone;
|
|
|
|
|
timeRange.setState({ timeZone: 'UTC' });
|
|
|
|
|
|
|
|
|
|
expect(scene.state.isDirty).toBe(true);
|
|
|
|
|
|
2024-02-05 16:08:12 +01:00
|
|
|
scene.exitEditMode({ skipConfirm: true });
|
2023-12-15 11:52:34 +01:00
|
|
|
expect(sceneGraph.getTimeRange(scene)!.state.timeZone).toBe(prevState);
|
2023-12-01 16:04:56 +01:00
|
|
|
});
|
2024-02-26 14:48:27 +02:00
|
|
|
|
|
|
|
|
it('Should throw an error when adding a panel to a layout that is not SceneGridLayout', () => {
|
|
|
|
|
const scene = buildTestScene({ body: undefined });
|
|
|
|
|
|
|
|
|
|
expect(() => {
|
|
|
|
|
scene.addPanel(new VizPanel({ title: 'Panel Title', key: 'panel-4', pluginId: 'timeseries' }));
|
|
|
|
|
}).toThrow('Trying to add a panel in a layout that is not SceneGridLayout');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should add a new panel to the dashboard', () => {
|
|
|
|
|
const vizPanel = new VizPanel({
|
|
|
|
|
title: 'Panel Title',
|
2024-02-28 11:13:01 +02:00
|
|
|
key: 'panel-5',
|
2024-02-26 14:48:27 +02:00
|
|
|
pluginId: 'timeseries',
|
|
|
|
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scene.addPanel(vizPanel);
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridItem = body.state.children[0] as SceneGridItem;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(5);
|
2024-02-28 11:13:01 +02:00
|
|
|
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
|
|
|
|
expect(gridItem.state.y).toBe(0);
|
2024-02-26 14:48:27 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should create and add a new panel to the dashboard', () => {
|
|
|
|
|
scene.onCreateNewPanel();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridItem = body.state.children[0] as SceneGridItem;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(5);
|
2024-02-28 11:13:01 +02:00
|
|
|
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should create and add a new row to the dashboard', () => {
|
|
|
|
|
scene.onCreateNewRow();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridRow = body.state.children[0] as SceneGridRow;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(3);
|
|
|
|
|
expect(gridRow.state.key).toBe('panel-5');
|
|
|
|
|
expect(gridRow.state.children[0].state.key).toBe('griditem-1');
|
|
|
|
|
expect(gridRow.state.children[1].state.key).toBe('griditem-2');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should create a row and add all panels in the dashboard under it', () => {
|
|
|
|
|
const scene = buildTestScene({
|
|
|
|
|
body: new SceneGridLayout({
|
|
|
|
|
children: [
|
|
|
|
|
new SceneGridItem({
|
|
|
|
|
key: 'griditem-1',
|
|
|
|
|
x: 0,
|
|
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel A',
|
|
|
|
|
key: 'panel-1',
|
|
|
|
|
pluginId: 'table',
|
|
|
|
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
new SceneGridItem({
|
|
|
|
|
key: 'griditem-2',
|
|
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel B',
|
|
|
|
|
key: 'panel-2',
|
|
|
|
|
pluginId: 'table',
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
],
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scene.onCreateNewRow();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridRow = body.state.children[0] as SceneGridRow;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(1);
|
|
|
|
|
expect(gridRow.state.children.length).toBe(2);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should create and add two new rows, but the second has no children', () => {
|
|
|
|
|
scene.onCreateNewRow();
|
|
|
|
|
scene.onCreateNewRow();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridRow = body.state.children[0] as SceneGridRow;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(4);
|
|
|
|
|
expect(gridRow.state.children.length).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should create an empty row when nothing else in dashboard', () => {
|
|
|
|
|
const scene = buildTestScene({
|
|
|
|
|
body: new SceneGridLayout({
|
|
|
|
|
children: [],
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scene.onCreateNewRow();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridRow = body.state.children[0] as SceneGridRow;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(1);
|
|
|
|
|
expect(gridRow.state.children.length).toBe(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should copy a panel', () => {
|
|
|
|
|
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body;
|
|
|
|
|
scene.copyPanel(vizPanel as VizPanel);
|
|
|
|
|
|
|
|
|
|
expect(scene.state.hasCopiedPanel).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('Should paste a panel', () => {
|
|
|
|
|
scene.setState({ hasCopiedPanel: true });
|
|
|
|
|
jest.spyOn(JSON, 'parse').mockReturnThis();
|
|
|
|
|
jest.mocked(buildGridItemForPanel).mockReturnValue(
|
|
|
|
|
new SceneGridItem({
|
|
|
|
|
key: 'griditem-9',
|
|
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel A',
|
|
|
|
|
key: 'panel-9',
|
|
|
|
|
pluginId: 'table',
|
|
|
|
|
}),
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
scene.pastePanel();
|
|
|
|
|
|
|
|
|
|
const body = scene.state.body as SceneGridLayout;
|
|
|
|
|
const gridItem = body.state.children[0] as SceneGridItem;
|
|
|
|
|
|
|
|
|
|
expect(body.state.children.length).toBe(5);
|
|
|
|
|
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
|
|
|
|
expect(gridItem.state.y).toBe(0);
|
|
|
|
|
expect(scene.state.hasCopiedPanel).toBe(false);
|
2024-02-26 14:48:27 +02:00
|
|
|
});
|
2023-08-29 14:17:55 +02:00
|
|
|
});
|
|
|
|
|
});
|
2023-09-29 13:19:03 +02:00
|
|
|
|
|
|
|
|
describe('Enriching data requests', () => {
|
|
|
|
|
let scene: DashboardScene;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
scene = buildTestScene();
|
|
|
|
|
scene.onEnterEditMode();
|
|
|
|
|
});
|
|
|
|
|
|
2024-02-21 09:38:42 +01:00
|
|
|
it('Should add app, uid, panelId and panelPluginId', () => {
|
2023-09-29 13:19:03 +02:00
|
|
|
const queryRunner = sceneGraph.findObject(scene, (o) => o.state.key === 'data-query-runner')!;
|
|
|
|
|
expect(scene.enrichDataRequest(queryRunner)).toEqual({
|
|
|
|
|
app: CoreApp.Dashboard,
|
|
|
|
|
dashboardUID: 'dash-1',
|
|
|
|
|
panelId: 1,
|
2024-02-21 09:38:42 +01:00
|
|
|
panelPluginId: 'table',
|
2023-09-29 13:19:03 +02:00
|
|
|
});
|
|
|
|
|
});
|
2023-12-01 10:07:55 +01:00
|
|
|
|
|
|
|
|
it('Should hash the key of the cloned panels and set it as panelId', () => {
|
|
|
|
|
const queryRunner = sceneGraph.findObject(scene, (o) => o.state.key === 'data-query-runner2')!;
|
|
|
|
|
const expectedPanelId = djb2Hash('panel-2-clone-1');
|
|
|
|
|
expect(scene.enrichDataRequest(queryRunner).panelId).toEqual(expectedPanelId);
|
|
|
|
|
});
|
2023-09-29 13:19:03 +02:00
|
|
|
});
|
2023-11-08 14:08:59 +01:00
|
|
|
|
|
|
|
|
describe('When variables change', () => {
|
|
|
|
|
it('A change to griditem pos should set isDirty true', () => {
|
|
|
|
|
const varA = new TestVariable({ name: 'A', query: 'A.*', value: 'A.AA', text: '', options: [], delayMs: 0 });
|
|
|
|
|
const scene = buildTestScene({
|
|
|
|
|
$variables: new SceneVariableSet({ variables: [varA] }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
scene.activate();
|
|
|
|
|
|
|
|
|
|
const eventHandler = jest.fn();
|
|
|
|
|
appEvents.subscribe(VariablesChanged, eventHandler);
|
|
|
|
|
|
|
|
|
|
varA.changeValueTo('A.AB');
|
|
|
|
|
|
|
|
|
|
expect(eventHandler).toHaveBeenCalledTimes(1);
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-01-19 10:58:20 +02:00
|
|
|
|
|
|
|
|
describe('When a dashboard is restored', () => {
|
|
|
|
|
let scene: DashboardScene;
|
|
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
scene = buildTestScene();
|
|
|
|
|
scene.onEnterEditMode();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should restore the dashboard to the selected version and exit edit mode', () => {
|
|
|
|
|
const newVersion = 3;
|
|
|
|
|
|
|
|
|
|
const mockScene = new DashboardScene({
|
|
|
|
|
title: 'new name',
|
|
|
|
|
uid: 'dash-1',
|
|
|
|
|
version: 4,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
jest.mocked(historySrv.restoreDashboard).mockResolvedValue({ version: newVersion });
|
|
|
|
|
jest.mocked(transformSaveModelToScene).mockReturnValue(mockScene);
|
|
|
|
|
|
|
|
|
|
return scene.onRestore(getVersionMock()).then((res) => {
|
|
|
|
|
expect(res).toBe(true);
|
|
|
|
|
|
|
|
|
|
expect(scene.state.version).toBe(newVersion);
|
|
|
|
|
expect(scene.state.title).toBe('new name');
|
|
|
|
|
expect(scene.state.isEditing).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return early if historySrv does not return a valid version number', () => {
|
|
|
|
|
jest
|
|
|
|
|
.mocked(historySrv.restoreDashboard)
|
|
|
|
|
.mockResolvedValueOnce({ version: null })
|
|
|
|
|
.mockResolvedValueOnce({ version: undefined })
|
|
|
|
|
.mockResolvedValueOnce({ version: Infinity })
|
|
|
|
|
.mockResolvedValueOnce({ version: NaN })
|
|
|
|
|
.mockResolvedValue({ version: '10' });
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
|
|
|
scene.onRestore(getVersionMock()).then((res) => {
|
|
|
|
|
expect(res).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
2023-07-12 13:37:26 +02:00
|
|
|
});
|
|
|
|
|
|
2023-11-08 14:08:59 +01:00
|
|
|
function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
2023-07-12 13:37:26 +02:00
|
|
|
const scene = new DashboardScene({
|
|
|
|
|
title: 'hello',
|
2023-09-11 13:51:05 +02:00
|
|
|
uid: 'dash-1',
|
2023-12-15 11:52:34 +01:00
|
|
|
description: 'hello description',
|
|
|
|
|
tags: ['tag1', 'tag2'],
|
|
|
|
|
editable: true,
|
|
|
|
|
$timeRange: new SceneTimeRange({
|
|
|
|
|
timeZone: 'browser',
|
|
|
|
|
}),
|
2024-02-20 08:43:02 +01:00
|
|
|
controls: new DashboardControls({}),
|
2023-07-12 13:37:26 +02:00
|
|
|
body: new SceneGridLayout({
|
|
|
|
|
children: [
|
|
|
|
|
new SceneGridItem({
|
2023-08-29 14:17:55 +02:00
|
|
|
key: 'griditem-1',
|
|
|
|
|
x: 0,
|
2023-07-12 13:37:26 +02:00
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel A',
|
|
|
|
|
key: 'panel-1',
|
|
|
|
|
pluginId: 'table',
|
2023-09-29 13:19:03 +02:00
|
|
|
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
2023-07-12 13:37:26 +02:00
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
new SceneGridItem({
|
2024-02-28 11:13:01 +02:00
|
|
|
key: 'griditem-2',
|
2023-07-12 13:37:26 +02:00
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel B',
|
|
|
|
|
key: 'panel-2',
|
|
|
|
|
pluginId: 'table',
|
|
|
|
|
}),
|
|
|
|
|
}),
|
2024-02-26 14:48:27 +02:00
|
|
|
new SceneGridRow({
|
2024-02-28 11:13:01 +02:00
|
|
|
key: 'panel-3',
|
2024-02-26 14:48:27 +02:00
|
|
|
children: [
|
|
|
|
|
new SceneGridItem({
|
|
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel C',
|
2024-02-28 11:13:01 +02:00
|
|
|
key: 'panel-4',
|
2024-02-26 14:48:27 +02:00
|
|
|
pluginId: 'table',
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
],
|
|
|
|
|
}),
|
2023-12-01 10:07:55 +01:00
|
|
|
new SceneGridItem({
|
|
|
|
|
body: new VizPanel({
|
|
|
|
|
title: 'Panel B',
|
|
|
|
|
key: 'panel-2-clone-1',
|
|
|
|
|
pluginId: 'table',
|
|
|
|
|
$data: new SceneQueryRunner({ key: 'data-query-runner2', queries: [{ refId: 'A' }] }),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
2023-07-12 13:37:26 +02:00
|
|
|
],
|
|
|
|
|
}),
|
2023-11-08 14:08:59 +01:00
|
|
|
...overrides,
|
2023-07-12 13:37:26 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return scene;
|
|
|
|
|
}
|
2024-01-19 10:58:20 +02:00
|
|
|
|
|
|
|
|
function getVersionMock(): DecoratedRevisionModel {
|
|
|
|
|
const dash: Dashboard = {
|
|
|
|
|
title: 'new name',
|
|
|
|
|
id: 5,
|
|
|
|
|
schemaVersion: 30,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: 2,
|
|
|
|
|
checked: false,
|
|
|
|
|
uid: 'uid',
|
|
|
|
|
parentVersion: 1,
|
|
|
|
|
version: 2,
|
|
|
|
|
created: new Date(),
|
|
|
|
|
createdBy: 'admin',
|
|
|
|
|
message: '',
|
|
|
|
|
data: dash,
|
|
|
|
|
createdDateString: '2017-02-22 20:43:01',
|
|
|
|
|
ageString: '7 years ago',
|
|
|
|
|
};
|
|
|
|
|
}
|