DashboardScene serialization: Handle transformations and queries (#75907)

* Serialization: Handle transformations and queries

* Betterer
pull/75945/head
Dominik Prokop 2 years ago committed by GitHub
parent 40a41113aa
commit 1a5d5c2820
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .betterer.results
  2. 42
      public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModel.test.ts.snap
  3. 184
      public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts
  4. 66
      public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts
  5. 1
      public/app/features/dashboard-scene/utils/createPanelDataProvider.ts

@ -3016,7 +3016,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"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.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/dashboard-scene/utils/test-utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],

@ -123,6 +123,11 @@ exports[`transformSceneToSaveModel Given a scene with rows Should transform back
</div>",
"mode": "markdown",
},
"targets": [
{
"refId": "A",
},
],
"title": "",
"transformations": [],
"transparent": false,
@ -266,6 +271,10 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
"links": [],
"panels": [
{
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A",
},
"fieldConfig": {
"defaults": {
"color": {
@ -298,6 +307,18 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
"sort": "none",
},
},
"targets": [
{
"alias": "series",
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A",
},
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1,
},
],
"title": "Simple time series graph ",
"transformations": [],
"transparent": false,
@ -317,6 +338,10 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
"type": "row",
},
{
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A",
},
"fieldConfig": {
"defaults": {},
"overrides": [],
@ -329,6 +354,18 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
},
"id": 29,
"options": {},
"targets": [
{
"alias": "series",
"datasource": {
"type": "testdata",
"uid": "PD8C576611E62080A",
},
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 1,
},
],
"title": "panel inside row",
"transformations": [],
"transparent": false,
@ -355,6 +392,11 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
"content": "content",
"mode": "markdown",
},
"targets": [
{
"refId": "A",
},
],
"title": "Transparent text panel",
"transformations": [],
"transparent": true,

@ -8,6 +8,7 @@ import {
} from '@grafana/scenes';
import { Panel, RowPanel } from '@grafana/schema';
import { PanelModel } from 'app/features/dashboard/state';
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
@ -131,6 +132,189 @@ describe('transformSceneToSaveModel', () => {
expect(saveModel.annotations?.list?.[3].hide).toEqual(false);
});
});
describe('Queries', () => {
it('Given panel with queries', () => {
const panel = buildGridItemFromPanelSchema({
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
maxDataPoints: 100,
targets: [
{
refId: 'A',
expr: 'A',
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
},
{
refId: 'B',
expr: 'B',
},
],
});
const result = gridItemToPanel(panel);
expect(result.maxDataPoints).toBe(100);
expect(result.targets?.length).toBe(2);
expect(result.targets?.[0]).toEqual({
refId: 'A',
expr: 'A',
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
});
expect(result.datasource).toEqual({
type: 'grafana-testdata',
uid: 'abc',
});
});
it('Given panel with transformations', () => {
const panel = buildGridItemFromPanelSchema({
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
maxDataPoints: 100,
transformations: [
{
id: 'reduce',
options: {
reducers: ['max'],
mode: 'reduceFields',
includeTimeField: false,
},
},
],
targets: [
{
refId: 'A',
expr: 'A',
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
},
{
refId: 'B',
expr: 'B',
},
],
});
const result = gridItemToPanel(panel);
expect(result.transformations.length).toBe(1);
expect(result.maxDataPoints).toBe(100);
expect(result.targets?.length).toBe(2);
expect(result.targets?.[0]).toEqual({
refId: 'A',
expr: 'A',
datasource: {
type: 'grafana-testdata',
uid: 'abc',
},
});
expect(result.datasource).toEqual({
type: 'grafana-testdata',
uid: 'abc',
});
});
it('Given panel with shared query', () => {
const panel = buildGridItemFromPanelSchema({
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
targets: [
{
refId: 'A',
panelId: 1,
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
},
],
});
const result = gridItemToPanel(panel);
expect(result.targets?.length).toBe(1);
expect(result.targets?.[0]).toEqual({
refId: 'A',
panelId: 1,
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
});
expect(result.datasource).toEqual({
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
});
});
it('Given panel with shared query and transformations', () => {
const panel = buildGridItemFromPanelSchema({
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
targets: [
{
refId: 'A',
panelId: 1,
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
},
],
transformations: [
{
id: 'reduce',
options: {
reducers: ['max'],
mode: 'reduceFields',
includeTimeField: false,
},
},
],
});
const result = gridItemToPanel(panel);
expect(result.transformations.length).toBe(1);
expect(result.targets?.length).toBe(1);
expect(result.targets?.[0]).toEqual({
refId: 'A',
panelId: 1,
datasource: {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
},
});
expect(result.datasource).toEqual({
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
});
});
});
});
export function buildGridItemFromPanelSchema(panel: Partial<Panel>): SceneGridItemLike {

@ -7,14 +7,26 @@ import {
VizPanel,
dataLayers,
SceneDataLayerProvider,
SceneQueryRunner,
SceneDataTransformer,
} from '@grafana/scenes';
import { AnnotationQuery, Dashboard, defaultDashboard, FieldConfigSource, Panel, RowPanel } from '@grafana/schema';
import {
AnnotationQuery,
Dashboard,
DataTransformerConfig,
defaultDashboard,
FieldConfigSource,
Panel,
RowPanel,
} from '@grafana/schema';
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
import { DashboardScene } from '../scene/DashboardScene';
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
import { PanelTimeRange } from '../scene/PanelTimeRange';
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
import { ShareQueryDataProvider } from '../scene/ShareQueryDataProvider';
import { getPanelIdForVizPanel } from '../utils/utils';
export function transformSceneToSaveModel(scene: DashboardScene): Dashboard {
@ -118,6 +130,58 @@ export function gridItemToPanel(gridItem: SceneGridItemLike): Panel {
panel.hideTimeOverride = panelTime.state.hideTimeOverride;
}
const dataProvider = vizPanel.state.$data;
// Dashboard datasource handling
if (dataProvider instanceof ShareQueryDataProvider) {
panel.datasource = {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
};
panel.targets = [
{
datasource: { ...panel.datasource },
refId: 'A',
panelId: dataProvider.state.query.panelId,
topic: dataProvider.state.query.topic,
},
];
}
// Regular queries handling
if (dataProvider instanceof SceneQueryRunner) {
panel.targets = dataProvider.state.queries;
panel.maxDataPoints = dataProvider.state.maxDataPoints;
panel.datasource = dataProvider.state.datasource;
}
// Transformations handling
if (dataProvider instanceof SceneDataTransformer) {
const panelData = dataProvider.state.$data;
if (panelData instanceof ShareQueryDataProvider) {
panel.datasource = {
type: 'datasource',
uid: SHARED_DASHBOARD_QUERY,
};
panel.targets = [
{
datasource: { ...panel.datasource },
refId: 'A',
panelId: panelData.state.query.panelId,
topic: panelData.state.query.topic,
},
];
}
if (panelData instanceof SceneQueryRunner) {
panel.targets = panelData.state.queries;
panel.maxDataPoints = panelData.state.maxDataPoints;
panel.datasource = panelData.state.datasource;
}
panel.transformations = dataProvider.state.transformations as DataTransformerConfig[];
}
if (vizPanel.state.displayMode === 'transparent') {
panel.transparent = true;
}

@ -22,6 +22,7 @@ export function createPanelDataProvider(panel: PanelModel): SceneDataProvider |
dataProvider = new ShareQueryDataProvider({ query: panel.targets[0] });
} else {
dataProvider = new SceneQueryRunner({
datasource: panel.datasource ?? undefined,
queries: panel.targets,
maxDataPoints: panel.maxDataPoints ?? undefined,
dataLayerFilter: {

Loading…
Cancel
Save