mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardLoaders: Add support for loading library panels (#73406)
* DashboardLoaders: Add support for loading library panels * Bump scenes * Scene object for loading library panels * Remove unused function * Remove console.log * Bump scenes * Review
This commit is contained in:
parent
88cdc38afa
commit
f00f56bbff
@ -244,7 +244,7 @@
|
||||
"@grafana/lezer-traceql": "0.0.4",
|
||||
"@grafana/monaco-logql": "^0.0.7",
|
||||
"@grafana/runtime": "workspace:*",
|
||||
"@grafana/scenes": "0.24.0",
|
||||
"@grafana/scenes": "0.24.2",
|
||||
"@grafana/schema": "workspace:*",
|
||||
"@grafana/ui": "workspace:*",
|
||||
"@kusto/monaco-kusto": "^7.4.0",
|
||||
|
@ -5,14 +5,12 @@ import {
|
||||
QueryVariableModel,
|
||||
VariableModel,
|
||||
} from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import {
|
||||
VizPanel,
|
||||
SceneTimePicker,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneTimeRange,
|
||||
SceneQueryRunner,
|
||||
SceneVariableSet,
|
||||
VariableValueSelectors,
|
||||
SceneVariable,
|
||||
@ -21,9 +19,7 @@ import {
|
||||
QueryVariable,
|
||||
ConstantVariable,
|
||||
SceneRefreshPicker,
|
||||
SceneDataTransformer,
|
||||
SceneGridItem,
|
||||
SceneDataProvider,
|
||||
SceneObject,
|
||||
SceneControlsSpacer,
|
||||
VizPanelMenu,
|
||||
@ -32,12 +28,12 @@ import {
|
||||
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 { DashboardScene } from './DashboardScene';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { panelMenuBehavior } from './PanelMenuBehavior';
|
||||
import { ShareQueryDataProvider } from './ShareQueryDataProvider';
|
||||
import { getVizPanelKeyForPanelId } from './utils';
|
||||
import { createPanelDataProvider } from './utils/createPanelDataProvider';
|
||||
|
||||
export interface DashboardLoaderState {
|
||||
dashboard?: DashboardScene;
|
||||
@ -129,6 +125,18 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): Array<Scen
|
||||
currentRowPanels = [];
|
||||
}
|
||||
}
|
||||
} else if (panel.libraryPanel?.uid && !('model' in panel.libraryPanel)) {
|
||||
const gridItem = new SceneGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
title: panel.title,
|
||||
uid: panel.libraryPanel.uid,
|
||||
}),
|
||||
y: panel.gridPos.y,
|
||||
x: panel.gridPos.x,
|
||||
width: panel.gridPos.w,
|
||||
height: panel.gridPos.h,
|
||||
});
|
||||
panels.push(gridItem);
|
||||
} else {
|
||||
const panelObject = createVizPanelFromPanelModel(panel);
|
||||
|
||||
@ -191,13 +199,13 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel)
|
||||
title: oldModel.title,
|
||||
uid: oldModel.uid,
|
||||
body: new SceneGridLayout({
|
||||
isLazy: true,
|
||||
children: createSceneObjectsForPanels(oldModel.panels),
|
||||
}),
|
||||
$timeRange: new SceneTimeRange(oldModel.time),
|
||||
$variables: variables,
|
||||
$behaviors: [
|
||||
new behaviors.CursorSync({
|
||||
key: 'dashboard',
|
||||
sync: oldModel.graphTooltip,
|
||||
}),
|
||||
],
|
||||
@ -294,39 +302,6 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
|
||||
});
|
||||
}
|
||||
|
||||
export function createPanelDataProvider(panel: PanelModel): SceneDataProvider | undefined {
|
||||
// Skip setting query runner for panels without queries
|
||||
if (!panel.targets?.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Skip setting query runner for panel plugins with skipDataQuery
|
||||
if (config.panels[panel.type]?.skipDataQuery) {
|
||||
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 {
|
||||
|
60
public/app/features/scenes/dashboard/LibraryVizPanel.tsx
Normal file
60
public/app/features/scenes/dashboard/LibraryVizPanel.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { getLibraryPanel } from 'app/features/library-panels/state/api';
|
||||
|
||||
import { createPanelDataProvider } from './utils/createPanelDataProvider';
|
||||
|
||||
interface LibraryVizPanelState extends SceneObjectState {
|
||||
// Library panels use title from dashboard JSON's panel model, not from library panel definition, hence we pass it.
|
||||
title: string;
|
||||
uid: string;
|
||||
panel?: VizPanel;
|
||||
}
|
||||
|
||||
export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
|
||||
static Component = LibraryPanelRenderer;
|
||||
|
||||
constructor({ uid, title }: Pick<LibraryVizPanelState, 'uid' | 'title'>) {
|
||||
super({ uid, title });
|
||||
|
||||
this.addActivationHandler(this._onActivate);
|
||||
}
|
||||
|
||||
private _onActivate = () => {
|
||||
this.loadLibraryPanelFromPanelModel();
|
||||
};
|
||||
|
||||
private async loadLibraryPanelFromPanelModel() {
|
||||
const { title } = this.state;
|
||||
let vizPanel = new VizPanel({ title });
|
||||
try {
|
||||
const libPanel = await getLibraryPanel(this.state.uid, true);
|
||||
const libPanelModel = new PanelModel(libPanel.model);
|
||||
vizPanel.setState({
|
||||
options: libPanelModel.options ?? {},
|
||||
fieldConfig: libPanelModel.fieldConfig,
|
||||
pluginVersion: libPanelModel.pluginVersion,
|
||||
displayMode: libPanelModel.transparent ? 'transparent' : undefined,
|
||||
$data: createPanelDataProvider(libPanelModel),
|
||||
});
|
||||
} catch (err) {
|
||||
vizPanel.setState({
|
||||
pluginLoadError: 'Unable to load library panel: ' + this.state.uid,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({ panel: vizPanel });
|
||||
}
|
||||
}
|
||||
|
||||
function LibraryPanelRenderer({ model }: SceneComponentProps<LibraryVizPanel>) {
|
||||
const { panel } = model.useState();
|
||||
|
||||
if (!panel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <panel.Component model={panel} />;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneDataProvider, SceneDataTransformer, SceneQueryRunner } from '@grafana/scenes';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
|
||||
import { ShareQueryDataProvider } from '../ShareQueryDataProvider';
|
||||
|
||||
export function createPanelDataProvider(panel: PanelModel): SceneDataProvider | undefined {
|
||||
// Skip setting query runner for panels without queries
|
||||
if (!panel.targets?.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Skip setting query runner for panel plugins with skipDataQuery
|
||||
if (config.panels[panel.type]?.skipDataQuery) {
|
||||
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;
|
||||
}
|
10
yarn.lock
10
yarn.lock
@ -3929,9 +3929,9 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@grafana/scenes@npm:0.24.0":
|
||||
version: 0.24.0
|
||||
resolution: "@grafana/scenes@npm:0.24.0"
|
||||
"@grafana/scenes@npm:0.24.2":
|
||||
version: 0.24.2
|
||||
resolution: "@grafana/scenes@npm:0.24.2"
|
||||
dependencies:
|
||||
"@grafana/e2e-selectors": 10.0.2
|
||||
react-grid-layout: 1.3.4
|
||||
@ -3943,7 +3943,7 @@ __metadata:
|
||||
"@grafana/runtime": 10.0.3
|
||||
"@grafana/schema": 10.0.3
|
||||
"@grafana/ui": 10.0.3
|
||||
checksum: b9cfc535228f0426ee4e422d3e8872f56212f9785acfcdb86aefe6e9c2ff5c98ef750eef0d72cd0ebc2feb67719fac86877b2eae6d376bdd45691da9068b5194
|
||||
checksum: 26797a4c90ff3b6d2e80f3da1d3be9721a371d9d9569e443dad14c81eba8413ef3fff78ab85602f9bfe3e243d7555a834134ac0c1c8542c23b9cc572bd40ad0a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -19248,7 +19248,7 @@ __metadata:
|
||||
"@grafana/lezer-traceql": 0.0.4
|
||||
"@grafana/monaco-logql": ^0.0.7
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/scenes": 0.24.0
|
||||
"@grafana/scenes": 0.24.2
|
||||
"@grafana/schema": "workspace:*"
|
||||
"@grafana/toolkit": "workspace:*"
|
||||
"@grafana/tsconfig": ^1.3.0-rc1
|
||||
|
Loading…
Reference in New Issue
Block a user