mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Scenes: Add support for shared query results of other panel (#65413)
* Scene: Add support for shared query results of other panel * Update * Fixing dashboard
This commit is contained in:
@@ -3,7 +3,10 @@
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
@@ -13,17 +16,69 @@
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 0,
|
||||
"fillGradient": 6,
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "PD8C576611E62080A"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 60,
|
||||
"gradientMode": "opacity",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 6,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 15,
|
||||
"w": 12,
|
||||
@@ -31,89 +86,79 @@
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "multi",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": true,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"pluginVersion": "9.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "PD8C576611E62080A"
|
||||
},
|
||||
"refId": "A",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "1,20,90,30,5,0,100"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "PD8C576611E62080A"
|
||||
},
|
||||
"refId": "B",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "1,20,90,30,5,-100,200"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "PD8C576611E62080A"
|
||||
},
|
||||
"refId": "C",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "2.5,3.5,4.5,10.5,20.5,21.5,19.5"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Raw Data Graph",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
@@ -122,44 +167,59 @@
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"fieldOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"showThresholdLabels": false,
|
||||
"showThresholdMarkers": true
|
||||
},
|
||||
"pluginVersion": "9.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Last non-null",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
}
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": false,
|
||||
"showThresholdMarkers": true
|
||||
"overrides": []
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Last non-null",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
@@ -168,63 +228,49 @@
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"fieldOptions": {
|
||||
"calcs": ["min"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"min"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": false,
|
||||
"showThresholdMarkers": true
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"pluginVersion": "9.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "min",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 10
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"displayMode": "basic",
|
||||
"fieldOptions": {
|
||||
"calcs": ["max"],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 200,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"mappings": [],
|
||||
"max": 200,
|
||||
"min": 0,
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "blue",
|
||||
@@ -235,28 +281,102 @@
|
||||
"value": 120
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 10
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"displayMode": "basic",
|
||||
"minVizHeight": 10,
|
||||
"minVizWidth": 0,
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"max"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"orientation": "vertical"
|
||||
"showUnfilled": true,
|
||||
"valueMode": "color"
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"pluginVersion": "9.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Max",
|
||||
"type": "bargauge"
|
||||
},
|
||||
{
|
||||
"columns": [],
|
||||
"datasource": "-- Dashboard --",
|
||||
"fontSize": "100%",
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"cellOptions": {
|
||||
"type": "auto"
|
||||
},
|
||||
"inspect": false
|
||||
},
|
||||
"decimals": 2,
|
||||
"displayName": "",
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "short"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Time"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Time"
|
||||
},
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "time: YYYY-MM-DD HH:mm:ss"
|
||||
},
|
||||
{
|
||||
"id": "custom.align"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 10,
|
||||
"w": 24,
|
||||
@@ -264,47 +384,49 @@
|
||||
"y": 15
|
||||
},
|
||||
"id": 8,
|
||||
"options": {},
|
||||
"pageSize": null,
|
||||
"showHeader": true,
|
||||
"sort": {
|
||||
"col": 0,
|
||||
"desc": true
|
||||
},
|
||||
"styles": [
|
||||
{
|
||||
"alias": "Time",
|
||||
"dateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"pattern": "Time",
|
||||
"type": "date"
|
||||
"options": {
|
||||
"cellHeight": "sm",
|
||||
"footer": {
|
||||
"countRows": false,
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"colorMode": null,
|
||||
"colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
|
||||
"decimals": 2,
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [],
|
||||
"type": "number",
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"showHeader": true,
|
||||
"showRowNums": false
|
||||
},
|
||||
"pluginVersion": "9.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"transform": "timeseries_to_columns",
|
||||
"title": "The data from graph above with seriesToColumns transform",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "seriesToColumns",
|
||||
"options": {
|
||||
"reducers": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 19,
|
||||
"refresh": "",
|
||||
"schemaVersion": 38,
|
||||
"style": "dark",
|
||||
"tags": ["gdev", "datasource-test"],
|
||||
"tags": [
|
||||
"gdev",
|
||||
"datasource-test"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
@@ -313,10 +435,22 @@
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "Datasource tests - Shared Queries",
|
||||
"uid": "ZqZnVvFZz",
|
||||
"version": 10
|
||||
}
|
||||
"version": 8,
|
||||
"weekStart": ""
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import { defaultDashboard, LoadingState, Panel, RowPanel, VariableType } from '@
|
||||
import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { createPanelJSONFixture } from 'app/features/dashboard/state/__fixtures__/dashboardFixtures';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/types';
|
||||
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import {
|
||||
@@ -21,6 +23,7 @@ import {
|
||||
createSceneVariableFromVariableModel,
|
||||
DashboardLoader,
|
||||
} from './DashboardsLoader';
|
||||
import { ShareQueryDataProvider } from './ShareQueryDataProvider';
|
||||
|
||||
describe('DashboardLoader', () => {
|
||||
describe('when fetching/loading a dashboard', () => {
|
||||
@@ -328,6 +331,21 @@ describe('DashboardLoader', () => {
|
||||
expect((vizPanelSceneObject.state.body as VizPanel)?.state.displayMode).toEqual('transparent');
|
||||
expect((vizPanelSceneObject.state.body as VizPanel)?.state.hoverHeader).toEqual(true);
|
||||
});
|
||||
|
||||
it('should handle a dashboard query data source', () => {
|
||||
const panel = {
|
||||
title: '',
|
||||
type: 'test-plugin',
|
||||
datasource: { uid: SHARED_DASHBOARD_QUERY, type: DASHBOARD_DATASOURCE_PLUGIN_ID },
|
||||
gridPos: { x: 0, y: 0, w: 12, h: 8 },
|
||||
transparent: true,
|
||||
targets: [{ refId: 'A', panelId: 10 }],
|
||||
};
|
||||
|
||||
const vizPanel = createVizPanelFromPanelModel(new PanelModel(panel)).state.body as VizPanel;
|
||||
|
||||
expect(vizPanel.state.$data).toBeInstanceOf(ShareQueryDataProvider);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when creating variables objects', () => {
|
||||
|
||||
@@ -22,13 +22,17 @@ import {
|
||||
SceneRefreshPicker,
|
||||
SceneDataTransformer,
|
||||
SceneGridItem,
|
||||
SceneDataProvider,
|
||||
} from '@grafana/scenes';
|
||||
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
||||
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/types';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { ShareQueryDataProvider } from './ShareQueryDataProvider';
|
||||
import { getVizPanelKeyForPanelId } from './utils';
|
||||
|
||||
export interface DashboardLoaderState {
|
||||
dashboard?: DashboardScene;
|
||||
@@ -259,11 +263,6 @@ export function createSceneVariableFromVariableModel(variable: VariableModel): S
|
||||
}
|
||||
|
||||
export function createVizPanelFromPanelModel(panel: PanelModel) {
|
||||
const queryRunner = new SceneQueryRunner({
|
||||
queries: panel.targets,
|
||||
maxDataPoints: panel.maxDataPoints ?? undefined,
|
||||
});
|
||||
|
||||
return new SceneGridItem({
|
||||
x: panel.gridPos.x,
|
||||
y: panel.gridPos.y,
|
||||
@@ -272,6 +271,7 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
|
||||
isDraggable: true,
|
||||
isResizable: true,
|
||||
body: new VizPanel({
|
||||
key: getVizPanelKeyForPanelId(panel.id),
|
||||
title: panel.title,
|
||||
pluginId: panel.type,
|
||||
options: panel.options ?? {},
|
||||
@@ -280,16 +280,38 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
|
||||
displayMode: panel.transparent ? 'transparent' : undefined,
|
||||
// To be replaced with it's own option persited option instead derived
|
||||
hoverHeader: !panel.title && !panel.timeFrom && !panel.timeShift,
|
||||
$data: panel.transformations?.length
|
||||
? new SceneDataTransformer({
|
||||
$data: queryRunner,
|
||||
transformations: panel.transformations,
|
||||
})
|
||||
: queryRunner,
|
||||
$data: createPanelDataProvider(panel),
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export function createPanelDataProvider(panel: PanelModel): SceneDataProvider | undefined {
|
||||
if (!panel.targets?.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let dataProvider: SceneDataProvider | undefined = undefined;
|
||||
|
||||
if (panel.datasource?.uid === SHARED_DASHBOARD_QUERY) {
|
||||
dataProvider = new ShareQueryDataProvider({ query: panel.targets[0] });
|
||||
} else {
|
||||
dataProvider = new SceneQueryRunner({
|
||||
queries: panel.targets,
|
||||
maxDataPoints: panel.maxDataPoints ?? undefined,
|
||||
});
|
||||
}
|
||||
|
||||
// Wrap inner data provider in a data transformer
|
||||
if (panel.transformations?.length) {
|
||||
dataProvider = new SceneDataTransformer({
|
||||
$data: dataProvider,
|
||||
transformations: panel.transformations,
|
||||
});
|
||||
}
|
||||
|
||||
return dataProvider;
|
||||
}
|
||||
|
||||
let loader: DashboardLoader | null = null;
|
||||
|
||||
export function getDashboardLoader(): DashboardLoader {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { getDefaultTimeRange, LoadingState } from '@grafana/data';
|
||||
import {
|
||||
SceneDataNode,
|
||||
SceneFlexItem,
|
||||
SceneFlexLayout,
|
||||
sceneGraph,
|
||||
SceneObjectBase,
|
||||
SceneObjectState,
|
||||
} from '@grafana/scenes';
|
||||
|
||||
import { ShareQueryDataProvider } from './ShareQueryDataProvider';
|
||||
import { activateFullSceneTree, getVizPanelKeyForPanelId } from './utils';
|
||||
|
||||
export class SceneDummyPanel extends SceneObjectBase<SceneObjectState> {}
|
||||
|
||||
describe('ShareQueryDataProvider', () => {
|
||||
it('Should find and subscribe to another VizPanels data provider', () => {
|
||||
const panel = new SceneDummyPanel({
|
||||
key: getVizPanelKeyForPanelId(2),
|
||||
$data: new ShareQueryDataProvider({
|
||||
query: { refId: 'A', panelId: 1 },
|
||||
}),
|
||||
});
|
||||
|
||||
const sourceData = new SceneDataNode({
|
||||
data: {
|
||||
series: [],
|
||||
state: LoadingState.Done,
|
||||
timeRange: getDefaultTimeRange(),
|
||||
structureRev: 11,
|
||||
},
|
||||
});
|
||||
|
||||
const scene = new SceneFlexLayout({
|
||||
children: [
|
||||
new SceneFlexItem({
|
||||
body: new SceneDummyPanel({
|
||||
key: getVizPanelKeyForPanelId(1),
|
||||
$data: sourceData,
|
||||
}),
|
||||
}),
|
||||
new SceneFlexItem({ body: panel }),
|
||||
],
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
expect(sceneGraph.getData(panel).state.data?.structureRev).toBe(11);
|
||||
|
||||
sourceData.setState({ data: { ...sourceData.state.data!, structureRev: 12 } });
|
||||
|
||||
expect(sceneGraph.getData(panel).state.data?.structureRev).toBe(12);
|
||||
});
|
||||
});
|
||||
103
public/app/features/scenes/dashboard/ShareQueryDataProvider.ts
Normal file
103
public/app/features/scenes/dashboard/ShareQueryDataProvider.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
|
||||
import {
|
||||
SceneDataProvider,
|
||||
SceneDataState,
|
||||
SceneDataTransformer,
|
||||
SceneDeactivationHandler,
|
||||
SceneObject,
|
||||
SceneObjectBase,
|
||||
} from '@grafana/scenes';
|
||||
import { DashboardQuery } from 'app/plugins/datasource/dashboard/types';
|
||||
|
||||
import { getVizPanelKeyForPanelId } from './utils';
|
||||
|
||||
export interface ShareQueryDataProviderState extends SceneDataState {
|
||||
query: DashboardQuery;
|
||||
}
|
||||
|
||||
export class ShareQueryDataProvider extends SceneObjectBase<ShareQueryDataProviderState> implements SceneDataProvider {
|
||||
private _querySub: Unsubscribable | undefined;
|
||||
private _sourceDataDeactivationHandler?: SceneDeactivationHandler;
|
||||
|
||||
public constructor(state: ShareQueryDataProviderState) {
|
||||
super(state);
|
||||
|
||||
this.addActivationHandler(() => {
|
||||
// TODO handle changes to query model (changed panelId / withTransforms)
|
||||
//this.subscribeToState(this._onStateChanged);
|
||||
|
||||
this._subscribeToSource();
|
||||
|
||||
return () => {
|
||||
if (this._querySub) {
|
||||
this._querySub.unsubscribe();
|
||||
}
|
||||
if (this._sourceDataDeactivationHandler) {
|
||||
this._sourceDataDeactivationHandler();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private _subscribeToSource() {
|
||||
const { query } = this.state;
|
||||
|
||||
if (this._querySub) {
|
||||
this._querySub.unsubscribe();
|
||||
}
|
||||
|
||||
if (!query.panelId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keyToFind = getVizPanelKeyForPanelId(query.panelId);
|
||||
const source = findObjectInScene(this.getRoot(), (scene: SceneObject) => scene.state.key === keyToFind);
|
||||
|
||||
if (!source) {
|
||||
console.log('Shared dashboard query refers to a panel that does not exist in the scene');
|
||||
return;
|
||||
}
|
||||
|
||||
let sourceData = source.state.$data;
|
||||
if (!sourceData) {
|
||||
console.log('No source data found for shared dashboard query');
|
||||
return;
|
||||
}
|
||||
|
||||
// This will activate if sourceData is part of hidden panel
|
||||
// Also make sure the sourceData is not deactivated if hidden later
|
||||
this._sourceDataDeactivationHandler = sourceData.activate();
|
||||
|
||||
if (sourceData instanceof SceneDataTransformer) {
|
||||
if (!query.withTransforms) {
|
||||
if (!sourceData.state.$data) {
|
||||
throw new Error('No source inner query runner found in data transformer');
|
||||
}
|
||||
sourceData = sourceData.state.$data;
|
||||
}
|
||||
}
|
||||
|
||||
this._querySub = sourceData.subscribeToState((state) => this.setState({ data: state.data }));
|
||||
|
||||
// Copy the initial state
|
||||
this.setState({ data: sourceData.state.data });
|
||||
}
|
||||
}
|
||||
|
||||
export function findObjectInScene(scene: SceneObject, check: (scene: SceneObject) => boolean): SceneObject | null {
|
||||
if (check(scene)) {
|
||||
return scene;
|
||||
}
|
||||
|
||||
let found: SceneObject | null = null;
|
||||
|
||||
scene.forEachChild((child) => {
|
||||
let maybe = findObjectInScene(child, check);
|
||||
if (maybe) {
|
||||
found = maybe;
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
26
public/app/features/scenes/dashboard/utils.ts
Normal file
26
public/app/features/scenes/dashboard/utils.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { SceneDeactivationHandler, SceneObject } from '@grafana/scenes';
|
||||
|
||||
export function getVizPanelKeyForPanelId(panelId: number) {
|
||||
return `panel-${panelId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Useful from tests to simulate mounting a full scene. Children are activated before parents to simulate the real order
|
||||
* of React mount order and useEffect ordering.
|
||||
*
|
||||
*/
|
||||
export function activateFullSceneTree(scene: SceneObject): SceneDeactivationHandler {
|
||||
const deactivationHandlers: SceneDeactivationHandler[] = [];
|
||||
|
||||
scene.forEachChild((child) => {
|
||||
deactivationHandlers.push(activateFullSceneTree(child));
|
||||
});
|
||||
|
||||
deactivationHandlers.push(scene.activate());
|
||||
|
||||
return () => {
|
||||
for (const handler of deactivationHandlers) {
|
||||
handler();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DataFrame, DataQuery, DataQueryError, DataTopic } from '@grafana/data';
|
||||
|
||||
export const SHARED_DASHBOARD_QUERY = '-- Dashboard --';
|
||||
export const DASHBOARD_DATASOURCE_PLUGIN_ID = 'dashboard';
|
||||
|
||||
export interface DashboardQuery extends DataQuery {
|
||||
panelId?: number;
|
||||
|
||||
@@ -3327,7 +3327,7 @@ __metadata:
|
||||
linkType: soft
|
||||
|
||||
"@grafana/scenes@npm:^0.3.0":
|
||||
version: 0.3.0
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@grafana/scenes@npm:0.3.0"
|
||||
dependencies:
|
||||
"@grafana/e2e-selectors": canary
|
||||
@@ -3338,7 +3338,7 @@ __metadata:
|
||||
uuid: ^9.0.0
|
||||
checksum: 3610cedcc150b9d6e3d6948056bb1bbbfe58d7fa0ff6e762eec6619bb0940504db867ea87e56160f27e4d93772f6203493bf87d353a1b18d2664e74a03f03a05
|
||||
languageName: node
|
||||
linkType: hard
|
||||
linkType: soft
|
||||
|
||||
"@grafana/schema@10.0.0-pre, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema":
|
||||
version: 0.0.0-use.local
|
||||
|
||||
Reference in New Issue
Block a user