mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
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;
|
|
|
|
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;
|
|
}
|