[v11.0.x] DashboardDataSourceBehaviour: Handle loading library panel (#87023)
DashboardDataSourceBehaviour: Handle loading library panel (#86980)
* DashboardDataSourceBehaviour: Handle loading library panel
* Remove timeout
* FIx test
(cherry picked from commit 67968df70e)
Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
co-authored by
Dominik Prokop
parent
5749f36f52
commit
c5f186fa22
@@ -21,6 +21,7 @@ import { activateFullSceneTree } from '../utils/test-utils';
|
||||
import { DashboardDatasourceBehaviour } from './DashboardDatasourceBehaviour';
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
|
||||
const grafanaDs = {
|
||||
id: 1,
|
||||
@@ -487,6 +488,87 @@ describe('DashboardDatasourceBehaviour', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Library panels', () => {
|
||||
it('should wait for library panel to be loaded', async () => {
|
||||
const sourcePanel = new LibraryVizPanel({
|
||||
name: 'My Library Panel',
|
||||
title: 'Panel title',
|
||||
uid: 'fdcvggvfy2qdca',
|
||||
panelKey: 'lib-panel',
|
||||
panel: new VizPanel({
|
||||
key: 'panel-1',
|
||||
title: 'Panel A',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
});
|
||||
|
||||
// query references inexistent panel
|
||||
const dashboardDSPanel = new VizPanel({
|
||||
title: 'Panel B',
|
||||
pluginId: 'table',
|
||||
key: 'panel-2',
|
||||
$data: new SceneQueryRunner({
|
||||
datasource: { uid: SHARED_DASHBOARD_QUERY },
|
||||
queries: [{ refId: 'A', panelId: 1 }],
|
||||
$behaviors: [new DashboardDatasourceBehaviour({})],
|
||||
}),
|
||||
});
|
||||
|
||||
const scene = new DashboardScene({
|
||||
title: 'hello',
|
||||
uid: 'dash-1',
|
||||
meta: {
|
||||
canEdit: true,
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: sourcePanel,
|
||||
}),
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: dashboardDSPanel,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
activateFullSceneTree(scene);
|
||||
|
||||
// spy on runQueries
|
||||
const spy = jest.spyOn(dashboardDSPanel.state.$data as SceneQueryRunner, 'runQueries');
|
||||
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
// Simulate library panel being loaded
|
||||
sourcePanel.setState({
|
||||
isLoaded: true,
|
||||
panel: new VizPanel({
|
||||
title: 'Panel A',
|
||||
pluginId: 'table',
|
||||
key: 'panel-1',
|
||||
$data: new SceneQueryRunner({
|
||||
datasource: { uid: 'grafana' },
|
||||
queries: [{ refId: 'A', queryType: 'randomWalk' }],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function buildTestScene() {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
|
||||
import { SceneObjectBase, SceneObjectState, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
|
||||
import { findVizPanelByKey, getDashboardSceneFor, getQueryRunnerFor, getVizPanelKeyForPanelId } from '../utils/utils';
|
||||
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { LibraryVizPanel, LibraryVizPanelState } from './LibraryVizPanel';
|
||||
|
||||
interface DashboardDatasourceBehaviourState extends SceneObjectState {}
|
||||
|
||||
@@ -18,6 +21,7 @@ export class DashboardDatasourceBehaviour extends SceneObjectBase<DashboardDatas
|
||||
private _activationHandler() {
|
||||
const queryRunner = this.parent;
|
||||
let dashboard: DashboardScene;
|
||||
let libraryPanelSub: Unsubscribable;
|
||||
|
||||
if (!(queryRunner instanceof SceneQueryRunner)) {
|
||||
throw new Error('DashboardDatasourceBehaviour must be attached to a SceneQueryRunner');
|
||||
@@ -50,15 +54,38 @@ export class DashboardDatasourceBehaviour extends SceneObjectBase<DashboardDatas
|
||||
const sourcePanelQueryRunner = getQueryRunnerFor(panel);
|
||||
|
||||
if (!(sourcePanelQueryRunner instanceof SceneQueryRunner)) {
|
||||
throw new Error('Could not find SceneQueryRunner for panel');
|
||||
}
|
||||
|
||||
if (this.prevRequestId && this.prevRequestId !== sourcePanelQueryRunner.state.data?.request?.requestId) {
|
||||
queryRunner.runQueries();
|
||||
if (!(panel.parent instanceof LibraryVizPanel)) {
|
||||
throw new Error('Could not find SceneQueryRunner for panel');
|
||||
} else {
|
||||
// Library panels load and create internal viz panel asynchroniously. Here we are subscribing to
|
||||
// library panel state, and run dashboard queries when the source panel query runner is ready.
|
||||
libraryPanelSub = panel.parent.subscribeToState((n, p) => {
|
||||
this.handleLibPanelStateUpdates(n, p, queryRunner);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (this.prevRequestId && this.prevRequestId !== sourcePanelQueryRunner.state.data?.request?.requestId) {
|
||||
queryRunner.runQueries();
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
this.prevRequestId = sourcePanelQueryRunner.state.data?.request?.requestId;
|
||||
this.prevRequestId = sourcePanelQueryRunner?.state.data?.request?.requestId;
|
||||
if (libraryPanelSub) {
|
||||
libraryPanelSub.unsubscribe();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private handleLibPanelStateUpdates(n: LibraryVizPanelState, p: LibraryVizPanelState, queryRunner: SceneQueryRunner) {
|
||||
if (n.panel && n.panel !== p.panel) {
|
||||
const libPanelQueryRunner = getQueryRunnerFor(n.panel);
|
||||
|
||||
if (!(libPanelQueryRunner instanceof SceneQueryRunner)) {
|
||||
throw new Error('Could not find SceneQueryRunner for panel');
|
||||
}
|
||||
|
||||
queryRunner.runQueries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { VizPanelLinks, VizPanelLinksMenu } from './PanelLinks';
|
||||
import { panelLinksBehavior, panelMenuBehavior } from './PanelMenuBehavior';
|
||||
import { PanelNotices } from './PanelNotices';
|
||||
|
||||
interface LibraryVizPanelState extends SceneObjectState {
|
||||
export 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;
|
||||
|
||||
Reference in New Issue
Block a user