Merge branch 'scene-share-query-rethink' of github.com:grafana/grafana into scene-share-query-rethink

This commit is contained in:
Torkel Ödegaard
2024-01-15 15:19:22 +00:00
10 changed files with 80 additions and 178 deletions
+12 -14
View File
@@ -2384,23 +2384,15 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"]
],
"public/app/features/dashboard-scene/panel-edit/VizPanelManager.tsx: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.", "3"]
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"public/app/features/dashboard-scene/scene/DashboardScene.test.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"public/app/features/dashboard-scene/scene/setDashboardPanelContext.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -2445,8 +2437,17 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/dashboard-scene/utils/DashboardModelCompatibilityWrapper.ts:5381": [
<<<<<<< HEAD
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
||||||| eb8dfe7933d
[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.", "3"]
=======
[0, 0, 0, "Do not use any type assertions.", "0"]
>>>>>>> 6073626683dd3e9f437a533ef55fd79baaceb982
],
"public/app/features/dashboard-scene/utils/test-utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@@ -4819,9 +4820,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/cloudwatch/utils/logsRetry.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/dashboard/runSharedRequest.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
@@ -10,7 +10,6 @@ import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/types';
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
import { ShareQueryDataProvider } from '../scene/ShareQueryDataProvider';
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
import { DashboardModelCompatibilityWrapper } from '../utils/DashboardModelCompatibilityWrapper';
import { findVizPanelByKey } from '../utils/utils';
@@ -426,11 +425,7 @@ describe('VizPanelManager', () => {
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((panel.state.$data as SceneQueryRunner).state.datasource).toEqual({
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: 'gdev-testdata',
type: 'grafana-testdata-datasource',
});
@@ -446,7 +441,7 @@ describe('VizPanelManager', () => {
},
} as any);
expect((panel.state.$data as SceneQueryRunner).state.datasource).toEqual({
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: 'gdev-prometheus',
type: 'grafana-prometheus-datasource',
});
@@ -457,11 +452,7 @@ describe('VizPanelManager', () => {
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((panel.state.$data as SceneQueryRunner).state.datasource).toEqual({
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: 'gdev-testdata',
type: 'grafana-testdata-datasource',
});
@@ -477,7 +468,10 @@ describe('VizPanelManager', () => {
},
} as any);
expect(panel.state.$data).toBeInstanceOf(ShareQueryDataProvider);
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: SHARED_DASHBOARD_QUERY,
type: 'datasource',
});
});
it('changing from dashboard data source to a plugin', async () => {
@@ -485,100 +479,10 @@ describe('VizPanelManager', () => {
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(ShareQueryDataProvider);
await vizPanelManager.changePanelDataSource({
name: 'grafana-prometheus',
type: 'grafana-prometheus-datasource',
uid: 'gdev-prometheus',
meta: {
name: 'Prometheus',
module: 'prometheus',
id: 'grafana-prometheus-datasource',
},
} as any);
expect(panel.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((panel.state.$data as SceneQueryRunner).state.datasource).toEqual({
uid: 'gdev-prometheus',
type: 'grafana-prometheus-datasource',
});
});
describe('with transformations', () => {
it('changing from one plugin to another', async () => {
const { vizPanelManager } = setupTest('panel-2');
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect((panel.state.$data?.state.$data as SceneQueryRunner).state.datasource).toEqual({
uid: 'gdev-testdata',
type: 'grafana-testdata-datasource',
});
await vizPanelManager.changePanelDataSource({
name: 'grafana-prometheus',
type: 'grafana-prometheus-datasource',
uid: 'gdev-prometheus',
meta: {
name: 'Prometheus',
module: 'prometheus',
id: 'grafana-prometheus-datasource',
},
} as any);
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect((panel.state.$data?.state.$data as SceneQueryRunner).state.datasource).toEqual({
uid: 'gdev-prometheus',
type: 'grafana-prometheus-datasource',
});
});
});
it('changing from a plugin to dashboard data source', async () => {
const { vizPanelManager } = setupTest('panel-2');
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect((panel.state.$data?.state.$data as SceneQueryRunner).state.datasource).toEqual({
uid: 'gdev-testdata',
type: 'grafana-testdata-datasource',
});
await vizPanelManager.changePanelDataSource({
name: SHARED_DASHBOARD_QUERY,
type: 'datasource',
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: SHARED_DASHBOARD_QUERY,
meta: {
name: 'Prometheus',
module: 'prometheus',
id: DASHBOARD_DATASOURCE_PLUGIN_ID,
},
} as any);
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect(panel.state.$data?.state.$data).toBeInstanceOf(ShareQueryDataProvider);
});
it('changing from a dashboard data source to a plugin', async () => {
const { vizPanelManager } = setupTest('panel-4');
vizPanelManager.activate();
await Promise.resolve();
const panel = vizPanelManager.state.panel;
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect(panel.state.$data?.state.$data).toBeInstanceOf(ShareQueryDataProvider);
type: 'datasource',
});
await vizPanelManager.changePanelDataSource({
name: 'grafana-prometheus',
@@ -591,9 +495,7 @@ describe('VizPanelManager', () => {
},
} as any);
expect(panel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect(panel.state.$data?.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((panel.state.$data?.state.$data as SceneQueryRunner).state.datasource).toEqual({
expect(vizPanelManager.queryRunner.state.datasource).toEqual({
uid: 'gdev-prometheus',
type: 'grafana-prometheus-datasource',
});
@@ -655,15 +557,8 @@ describe('VizPanelManager', () => {
panelId: panelWithTransformations.id,
},
]);
expect(vizPanelManager.panelData).toBeInstanceOf(ShareQueryDataProvider);
expect((vizPanelManager.panelData as ShareQueryDataProvider).state.query.panelId).toBe(
panelWithTransformations.id
);
expect(vizPanelManager.panelData.state.$data).toBeInstanceOf(SceneDataTransformer);
expect(vizPanelManager.panelData.state.$data?.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((vizPanelManager.panelData.state.$data?.state.$data as SceneQueryRunner).state.queries).toEqual(
panelWithTransformations.targets
);
expect(vizPanelManager.panelData).toBeInstanceOf(SceneDataTransformer);
expect(vizPanelManager.queryRunner.state.queries[0].panelId).toEqual(panelWithTransformations.id);
// Changing dashboard query to a panel with queries only
vizPanelManager.changeQueries([
@@ -676,9 +571,8 @@ describe('VizPanelManager', () => {
},
]);
expect(vizPanelManager.panelData).toBeInstanceOf(ShareQueryDataProvider);
expect((vizPanelManager.panelData as ShareQueryDataProvider).state.query.panelId).toBe(panelWithQueriesOnly.id);
expect(vizPanelManager.queryRunner.state.queries).toEqual(panelWithQueriesOnly.targets);
expect(vizPanelManager.panelData).toBeInstanceOf(SceneDataTransformer);
expect(vizPanelManager.queryRunner.state.queries[0].panelId).toBe(panelWithQueriesOnly.id);
});
});
});
@@ -19,7 +19,6 @@ import {
DeepPartial,
SceneQueryRunner,
sceneGraph,
SceneDataTransformer,
SceneDataProvider,
} from '@grafana/scenes';
import { DataQuery } from '@grafana/schema';
@@ -30,7 +29,7 @@ import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
import { QueryGroupOptions } from 'app/types';
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
import { getPanelIdForVizPanel } from '../utils/utils';
import { getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
interface VizPanelManagerState extends SceneObjectState {
panel: VizPanel;
@@ -229,13 +228,13 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
}
get queryRunner(): SceneQueryRunner {
const dataObj = this.state.panel.state.$data;
// Panel data object is always SceneQueryRunner wrapped in a SceneDataTransformer
const runner = getQueryRunnerFor(this.state.panel);
if (dataObj instanceof SceneDataTransformer) {
return dataObj.state.$data as SceneQueryRunner;
if (!runner) {
throw new Error('Query runner not found');
}
return dataObj as SceneQueryRunner;
return runner;
}
get panelData(): SceneDataProvider {
@@ -225,7 +225,7 @@ export function getPanelLinksBehavior(panel: PanelModel) {
function createExtensionContext(panel: VizPanel, dashboard: DashboardScene): PluginExtensionPanelContext {
const timeRange = sceneGraph.getTimeRange(panel);
let queryRunner = getQueryRunnerFor(panel);
let targets: DataQuery[] = [];
const targets: DataQuery[] = queryRunner?.state.queries as DataQuery[];
const id = getPanelIdForVizPanel(panel);
let scopedVars = {};
@@ -98,7 +98,7 @@ describe('sceneVariablesSetToVariables', () => {
allValue: 'test-all',
isMulti: true,
});
const set = new SceneVariableSet({
variables: [variable],
});
@@ -22,6 +22,7 @@ import {
SceneGridItem,
SceneGridLayout,
SceneGridRow,
SceneQueryRunner,
SceneRefreshPicker,
SceneTimePicker,
VizPanel,
@@ -44,7 +45,6 @@ import { DashboardControls } from '../scene/DashboardControls';
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
import { PanelTimeRange } from '../scene/PanelTimeRange';
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
import { ShareQueryDataProvider } from '../scene/ShareQueryDataProvider';
import { getQueryRunnerFor } from '../utils/utils';
import dashboard_to_load1 from './testfiles/dashboard_to_load1.json';
@@ -382,7 +382,9 @@ describe('transformSaveModelToScene', () => {
};
const { vizPanel } = buildGridItemForTest(panel);
expect(vizPanel.state.$data).toBeInstanceOf(ShareQueryDataProvider);
expect(vizPanel.state.$data).toBeInstanceOf(SceneDataTransformer);
expect(vizPanel.state.$data?.state.$data).toBeInstanceOf(SceneQueryRunner);
expect((vizPanel.state.$data?.state.$data as SceneQueryRunner).state.queries).toEqual(panel.targets);
});
it('should not set SceneQueryRunner for plugins with skipDataQuery', () => {
@@ -16,7 +16,6 @@ import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
import { DashboardControls } from '../scene/DashboardControls';
import { DashboardLinksControls } from '../scene/DashboardLinksControls';
import { DashboardScene } from '../scene/DashboardScene';
import { ShareQueryDataProvider } from '../scene/ShareQueryDataProvider';
import { DashboardModelCompatibilityWrapper } from './DashboardModelCompatibilityWrapper';
@@ -41,18 +40,14 @@ describe('DashboardModelCompatibilityWrapper', () => {
expect(wrapper.panels[0].targets[0]).toEqual({ refId: 'A' });
expect(wrapper.panels[1].targets).toHaveLength(0);
expect(wrapper.panels[2].targets).toHaveLength(1);
expect(wrapper.panels[2].targets).toEqual([
{ datasource: { uid: SHARED_DASHBOARD_QUERY, type: 'datasource' }, refId: 'A', panelId: 1 },
]);
expect(wrapper.panels[2].targets).toEqual([{ refId: 'A', panelId: 1 }]);
expect(wrapper.panels[3].targets).toHaveLength(1);
expect(wrapper.panels[3].targets[0]).toEqual({ refId: 'A' });
expect(wrapper.panels[4].targets).toHaveLength(1);
expect(wrapper.panels[4].targets).toEqual([
{ datasource: { uid: SHARED_DASHBOARD_QUERY, type: 'datasource' }, refId: 'A', panelId: 1 },
]);
expect(wrapper.panels[4].targets).toEqual([{ refId: 'A', panelId: 1 }]);
expect(wrapper.panels[0].datasource).toEqual({ uid: 'gdev-testdata', type: 'grafana-testdata-datasource' });
expect(wrapper.panels[1].datasource).toEqual(null);
expect(wrapper.panels[1].datasource).toEqual(undefined);
expect(wrapper.panels[2].datasource).toEqual({ uid: SHARED_DASHBOARD_QUERY, type: 'datasource' });
expect(wrapper.panels[3].datasource).toEqual({ uid: 'gdev-testdata', type: 'grafana-testdata-datasource' });
expect(wrapper.panels[4].datasource).toEqual({ uid: SHARED_DASHBOARD_QUERY, type: 'datasource' });
@@ -162,7 +157,11 @@ function setup() {
title: 'Panel with a shared query',
key: 'panel-3',
pluginId: 'table',
$data: new ShareQueryDataProvider({ query: { refId: 'A', panelId: 1 } }),
$data: new SceneQueryRunner({
key: 'data-query-runner',
queries: [{ refId: 'A', panelId: 1 }],
datasource: { uid: SHARED_DASHBOARD_QUERY, type: 'datasource' },
}),
}),
}),
@@ -187,7 +186,11 @@ function setup() {
key: 'panel-4',
pluginId: 'table',
$data: new SceneDataTransformer({
$data: new ShareQueryDataProvider({ query: { refId: 'A', panelId: 1 } }),
$data: new SceneQueryRunner({
key: 'data-query-runner',
queries: [{ refId: 'A', panelId: 1 }],
datasource: { uid: SHARED_DASHBOARD_QUERY, type: 'datasource' },
}),
transformations: [],
}),
}),
@@ -26,12 +26,8 @@ export function createPanelDataProvider(panel: PanelModel): SceneDataProvider |
});
// Wrap inner data provider in a data transformer
if (panel.transformations?.length) {
dataProvider = new SceneDataTransformer({
$data: dataProvider,
transformations: panel.transformations,
});
}
return dataProvider;
return new SceneDataTransformer({
$data: dataProvider,
transformations: panel.transformations || [],
});
}
@@ -14,6 +14,7 @@ import {
} from '../../../features/dashboard/state/__fixtures__/dashboardFixtures';
import { DashboardQueryEditor } from './DashboardQueryEditor';
import { DashboardDatasource } from './datasource';
import { SHARED_DASHBOARD_QUERY } from './types';
jest.mock('app/core/config', () => ({
@@ -78,10 +79,11 @@ describe('DashboardQueryEditor', () => {
it('does not show a panel with the SHARED_DASHBOARD_QUERY datasource as an option in the dropdown', async () => {
render(
<DashboardQueryEditor
queries={mockQueries}
panelData={mockPanelData}
datasource={{} as DashboardDatasource}
query={mockQueries[0]}
data={mockPanelData}
onChange={mockOnChange}
onRunQueries={mockOnRunQueries}
onRunQuery={mockOnRunQueries}
/>
);
const select = screen.getByText('Choose panel');
@@ -101,10 +103,11 @@ describe('DashboardQueryEditor', () => {
mockDashboard.initEditPanel(mockDashboard.panels[0]);
render(
<DashboardQueryEditor
queries={mockQueries}
panelData={mockPanelData}
datasource={{} as DashboardDatasource}
query={mockQueries[0]}
data={mockPanelData}
onChange={mockOnChange}
onRunQueries={mockOnRunQueries}
onRunQuery={mockOnRunQueries}
/>
);
const select = screen.getByText('Choose panel');
@@ -7,9 +7,13 @@ import {
DataSourceInstanceSettings,
TestDataSourceResponse,
} from '@grafana/data';
import { SceneDataTransformer, SceneObject } from '@grafana/scenes';
import { SceneDataProvider, SceneDataTransformer, SceneObject } from '@grafana/scenes';
import { PanelEditor } from 'app/features/dashboard-scene/panel-edit/PanelEditor';
import { findVizPanelByKey, getVizPanelKeyForPanelId } from 'app/features/dashboard-scene/utils/utils';
import {
findVizPanelByKey,
getQueryRunnerFor,
getVizPanelKeyForPanelId,
} from 'app/features/dashboard-scene/utils/utils';
import { DashboardQuery } from './types';
@@ -49,22 +53,25 @@ export class DashboardDatasource extends DataSourceApi<DashboardQuery> {
return of({ data: [], error: { message: 'Could not find source panel' } });
}
let sourceDataProvider = sourcePanel?.state.$data;
if (query.withTransforms && sourceDataProvider instanceof SceneDataTransformer) {
sourceDataProvider = sourceDataProvider.state.$data!;
}
let sourceDataProvider: SceneDataProvider | undefined = getQueryRunnerFor(sourcePanel);
if (!sourceDataProvider || !sourceDataProvider.getResultsStream) {
return of({ data: [] });
}
if (query.withTransforms && sourceDataProvider.parent) {
const transformer = sourceDataProvider.parent;
if (transformer && transformer instanceof SceneDataTransformer) {
sourceDataProvider = transformer;
}
}
if (!sourceDataProvider?.isActive) {
sourceDataProvider?.activate();
sourceDataProvider.setContainerWidth!(500);
}
return sourceDataProvider.getResultsStream().pipe(
return sourceDataProvider.getResultsStream!().pipe(
map((result) => {
return {
data: result.data.series,