mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardScene: Backward compatability with getDashboardSrv.getCurrent and DashboardModel props and functions (#76371)
* DashboardSrv.getCurrent backward compatibility * fixes
This commit is contained in:
parent
b01cbc7aef
commit
a42040a59a
@ -37,7 +37,7 @@ export function getAngularPanelReactWrapper(plugin: PanelPlugin): ComponentType<
|
||||
// @ts-ignore
|
||||
panel: fakePanel,
|
||||
// @ts-ignore
|
||||
dashboard: new DashboardModelCompatibilityWrapper(),
|
||||
dashboard: getDashboardSrv().getCurrent(),
|
||||
size: { width: props.width, height: props.height },
|
||||
queryRunner: queryRunner,
|
||||
};
|
||||
|
@ -1,9 +1,19 @@
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { sceneGraph, SceneGridItem, SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
|
||||
describe('DashboardScene', () => {
|
||||
describe('DashboardSrv.getCurrent compatibility', () => {
|
||||
it('Should set to compatibility wrapper', () => {
|
||||
const scene = buildTestScene();
|
||||
scene.activate();
|
||||
|
||||
expect(getDashboardSrv().getCurrent()?.uid).toBe('dash-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Editing and discarding', () => {
|
||||
describe('Given scene in edit mode', () => {
|
||||
let scene: DashboardScene;
|
||||
|
@ -14,10 +14,12 @@ import {
|
||||
SceneObjectStateChangedEvent,
|
||||
sceneUtils,
|
||||
} from '@grafana/scenes';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { DashboardMeta } from 'app/types';
|
||||
|
||||
import { DashboardSceneRenderer } from '../scene/DashboardSceneRenderer';
|
||||
import { SaveDashboardDrawer } from '../serialization/SaveDashboardDrawer';
|
||||
import { DashboardModelCompatibilityWrapper } from '../utils/DashboardModelCompatibilityWrapper';
|
||||
import {
|
||||
findVizPanelByKey,
|
||||
forceRenderChildren,
|
||||
@ -29,12 +31,21 @@ import {
|
||||
import { DashboardSceneUrlSync } from './DashboardSceneUrlSync';
|
||||
|
||||
export interface DashboardSceneState extends SceneObjectState {
|
||||
/** The title */
|
||||
title: string;
|
||||
/** A uid when saved */
|
||||
uid?: string;
|
||||
/** @deprecated */
|
||||
id?: number | null;
|
||||
/** Layout of panels */
|
||||
body: SceneObject;
|
||||
/** NavToolbar actions */
|
||||
actions?: SceneObject[];
|
||||
/** Fixed row at the top of the canvas with for example variables and time range controls */
|
||||
controls?: SceneObject[];
|
||||
/** True when editing */
|
||||
isEditing?: boolean;
|
||||
/** True when user made a change */
|
||||
isDirty?: boolean;
|
||||
/** meta flags */
|
||||
meta: DashboardMeta;
|
||||
@ -84,11 +95,17 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
this.startTrackingChanges();
|
||||
}
|
||||
|
||||
const oldDashboardWrapper = new DashboardModelCompatibilityWrapper(this);
|
||||
|
||||
// @ts-expect-error
|
||||
getDashboardSrv().setCurrent(oldDashboardWrapper);
|
||||
|
||||
// Deactivation logic
|
||||
return () => {
|
||||
window.__grafanaSceneContext = undefined;
|
||||
this.stopTrackingChanges();
|
||||
this.stopUrlSync();
|
||||
oldDashboardWrapper.destroy();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ export const NavToolbarActions = React.memo<Props>(({ dashboard }) => {
|
||||
if (uid) {
|
||||
toolbarActions.push(
|
||||
<DashNavButton
|
||||
key="share-dashboard-button"
|
||||
tooltip={t('dashboard.toolbar.share', 'Share dashboard')}
|
||||
icon="share-alt"
|
||||
iconSize="lg"
|
||||
@ -33,7 +34,7 @@ export const NavToolbarActions = React.memo<Props>(({ dashboard }) => {
|
||||
|
||||
toolbarActions.push(
|
||||
<DashNavButton
|
||||
key="button-scenes"
|
||||
key="view-in-old-dashboard-button"
|
||||
tooltip={'View as dashboard'}
|
||||
icon="apps"
|
||||
onClick={() => locationService.push(`/d/${uid}`)}
|
||||
|
@ -308,6 +308,7 @@ exports[`transformSceneToSaveModel Given a simple scene Should transform back to
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 1,
|
||||
"graphTooltip": 0,
|
||||
"id": 1351,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
|
@ -32,7 +32,6 @@ import {
|
||||
SceneDataLayerControls,
|
||||
AdHocFilterSet,
|
||||
} from '@grafana/scenes';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
@ -61,9 +60,6 @@ export function transformSaveModelToScene(rsp: DashboardDTO): DashboardScene {
|
||||
autoMigrateOldPanels: false,
|
||||
});
|
||||
|
||||
// Setting for built-in annotations query to run
|
||||
getDashboardSrv().setCurrent(oldModel);
|
||||
|
||||
return createDashboardSceneFromDashboardModel(oldModel);
|
||||
}
|
||||
|
||||
@ -215,6 +211,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel)
|
||||
return new DashboardScene({
|
||||
title: oldModel.title,
|
||||
uid: oldModel.uid,
|
||||
id: oldModel.id,
|
||||
meta: oldModel.meta,
|
||||
body: new SceneGridLayout({
|
||||
isLazy: true,
|
||||
|
@ -92,6 +92,7 @@ export function transformSceneToSaveModel(scene: DashboardScene, isSnapshot = fa
|
||||
...defaultDashboard,
|
||||
title: state.title,
|
||||
uid: state.uid,
|
||||
id: state.id,
|
||||
time: {
|
||||
from: timeRange.from,
|
||||
to: timeRange.to,
|
||||
|
@ -0,0 +1,85 @@
|
||||
import { TimeRangeUpdatedEvent } from '@grafana/runtime';
|
||||
import { behaviors, SceneGridItem, SceneGridLayout, SceneQueryRunner, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { DashboardCursorSync } from '@grafana/schema';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
|
||||
import { DashboardModelCompatibilityWrapper } from './DashboardModelCompatibilityWrapper';
|
||||
|
||||
describe('DashboardModelCompatibilityWrapper', () => {
|
||||
it('Provide basic prop and function of compatability', () => {
|
||||
const { wrapper } = setup();
|
||||
|
||||
expect(wrapper.uid).toBe('dash-1');
|
||||
expect(wrapper.title).toBe('hello');
|
||||
|
||||
expect(wrapper.time.from).toBe('now-6h');
|
||||
});
|
||||
|
||||
it('Shared tooltip functions', () => {
|
||||
const { scene, wrapper } = setup();
|
||||
expect(wrapper.sharedTooltipModeEnabled()).toBe(false);
|
||||
expect(wrapper.sharedCrosshairModeOnly()).toBe(false);
|
||||
|
||||
scene.setState({ $behaviors: [new behaviors.CursorSync({ sync: DashboardCursorSync.Crosshair })] });
|
||||
|
||||
expect(wrapper.sharedTooltipModeEnabled()).toBe(true);
|
||||
expect(wrapper.sharedCrosshairModeOnly()).toBe(true);
|
||||
});
|
||||
|
||||
it('Get timezone from time range', () => {
|
||||
const { wrapper } = setup();
|
||||
expect(wrapper.getTimezone()).toBe('America/New_York');
|
||||
});
|
||||
|
||||
it('Should emit TimeRangeUpdatedEvent when time range change', () => {
|
||||
const { scene, wrapper } = setup();
|
||||
let timeChanged = 0;
|
||||
wrapper.events.subscribe(TimeRangeUpdatedEvent, () => timeChanged++);
|
||||
|
||||
scene.state.$timeRange!.onRefresh();
|
||||
expect(timeChanged).toBe(1);
|
||||
});
|
||||
|
||||
it('Can get fake panel with getPanelById', () => {
|
||||
const { wrapper } = setup();
|
||||
|
||||
expect(wrapper.getPanelById(1)!.title).toBe('Panel A');
|
||||
expect(wrapper.getPanelById(2)!.title).toBe('Panel B');
|
||||
});
|
||||
});
|
||||
|
||||
function setup() {
|
||||
const scene = new DashboardScene({
|
||||
title: 'hello',
|
||||
uid: 'dash-1',
|
||||
$timeRange: new SceneTimeRange({
|
||||
timeZone: 'America/New_York',
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
key: 'panel-2',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
const wrapper = new DashboardModelCompatibilityWrapper(scene);
|
||||
|
||||
return { scene, wrapper };
|
||||
}
|
@ -1,17 +1,66 @@
|
||||
import { DashboardCursorSync, dateTimeFormat, DateTimeInput, EventBusSrv } from '@grafana/data';
|
||||
import { behaviors, sceneGraph } from '@grafana/scenes';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { AnnotationQuery, DashboardCursorSync, dateTimeFormat, DateTimeInput, EventBusSrv } from '@grafana/data';
|
||||
import { TimeRangeUpdatedEvent } from '@grafana/runtime';
|
||||
import { behaviors, SceneDataTransformer, sceneGraph, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
|
||||
import { findVizPanelByKey, getVizPanelKeyForPanelId } from './utils';
|
||||
|
||||
/**
|
||||
* Will move this to make it the main way we remain somewhat compatible with getDashboardSrv().getCurrent
|
||||
*/
|
||||
export class DashboardModelCompatibilityWrapper {
|
||||
events = new EventBusSrv();
|
||||
panelInitialized() {}
|
||||
public events = new EventBusSrv();
|
||||
private _subs = new Subscription();
|
||||
|
||||
public constructor(private _scene: DashboardScene) {
|
||||
const timeRange = sceneGraph.getTimeRange(_scene);
|
||||
|
||||
this._subs.add(
|
||||
timeRange.subscribeToState((state, prev) => {
|
||||
if (state.value !== prev.value) {
|
||||
this.events.publish(new TimeRangeUpdatedEvent(state.value));
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public get id(): number | null {
|
||||
return this._scene.state.id ?? null;
|
||||
}
|
||||
|
||||
public get uid() {
|
||||
return this._scene.state.uid ?? null;
|
||||
}
|
||||
|
||||
public get title() {
|
||||
return this._scene.state.title;
|
||||
}
|
||||
|
||||
public get meta() {
|
||||
return this._scene.state.meta;
|
||||
}
|
||||
|
||||
public get time() {
|
||||
const time = sceneGraph.getTimeRange(this._scene);
|
||||
return {
|
||||
from: time.state.from,
|
||||
to: time.state.to,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Used from from timeseries migration handler to migrate time regions to dashboard annotations
|
||||
*/
|
||||
public get annotations(): { list: AnnotationQuery[] } {
|
||||
console.error('Scenes DashboardModelCompatibilityWrapper.annotations not implemented (yet)');
|
||||
return { list: [] };
|
||||
}
|
||||
|
||||
public getTimezone() {
|
||||
const time = sceneGraph.getTimeRange(window.__grafanaSceneContext);
|
||||
const time = sceneGraph.getTimeRange(this._scene);
|
||||
return time.getTimeZone();
|
||||
}
|
||||
|
||||
@ -20,16 +69,14 @@ export class DashboardModelCompatibilityWrapper {
|
||||
}
|
||||
|
||||
public sharedCrosshairModeOnly() {
|
||||
return this._getSyncMode() > 1;
|
||||
return this._getSyncMode() === 1;
|
||||
}
|
||||
|
||||
private _getSyncMode() {
|
||||
const dashboard = this.getDashboardScene();
|
||||
|
||||
if (dashboard.state.$behaviors) {
|
||||
for (const behavior of dashboard.state.$behaviors) {
|
||||
if (this._scene.state.$behaviors) {
|
||||
for (const behavior of this._scene.state.$behaviors) {
|
||||
if (behavior instanceof behaviors.CursorSync) {
|
||||
return behavior.state.sync > 0;
|
||||
return behavior.state.sync;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,14 +84,6 @@ export class DashboardModelCompatibilityWrapper {
|
||||
return DashboardCursorSync.Off;
|
||||
}
|
||||
|
||||
private getDashboardScene(): DashboardScene {
|
||||
if (window.__grafanaSceneContext instanceof DashboardScene) {
|
||||
return window.__grafanaSceneContext;
|
||||
}
|
||||
|
||||
throw new Error('Dashboard scene not found');
|
||||
}
|
||||
|
||||
public otherPanelInFullscreen(panel: unknown) {
|
||||
return false;
|
||||
}
|
||||
@ -55,4 +94,62 @@ export class DashboardModelCompatibilityWrapper {
|
||||
timeZone: this.getTimezone(),
|
||||
});
|
||||
}
|
||||
|
||||
public getPanelById(id: number): PanelCompatibilityWrapper | null {
|
||||
const vizPanel = findVizPanelByKey(this._scene, getVizPanelKeyForPanelId(id));
|
||||
if (vizPanel) {
|
||||
return new PanelCompatibilityWrapper(vizPanel);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public removePanel(panel: PanelCompatibilityWrapper) {
|
||||
// TODO
|
||||
console.error('Scenes DashboardModelCompatibilityWrapper.removePanel not implemented (yet)');
|
||||
}
|
||||
|
||||
public canEditAnnotations(dashboardUID?: string) {
|
||||
// TOOD
|
||||
return false;
|
||||
}
|
||||
|
||||
public panelInitialized() {}
|
||||
|
||||
public destroy() {
|
||||
this.events.removeAllListeners();
|
||||
this._subs.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
class PanelCompatibilityWrapper {
|
||||
constructor(private _vizPanel: VizPanel) {}
|
||||
|
||||
public get type() {
|
||||
return this._vizPanel.state.pluginId;
|
||||
}
|
||||
|
||||
public get title() {
|
||||
return this._vizPanel.state.title;
|
||||
}
|
||||
|
||||
public get transformations() {
|
||||
if (this._vizPanel.state.$data instanceof SceneDataTransformer) {
|
||||
return this._vizPanel.state.$data.state.transformations;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
console.error('Scenes PanelCompatibilityWrapper.refresh no implemented (yet)');
|
||||
}
|
||||
|
||||
public render() {
|
||||
console.error('Scenes PanelCompatibilityWrapper.render no implemented (yet)');
|
||||
}
|
||||
|
||||
public getQueryRunner() {
|
||||
console.error('Scenes PanelCompatibilityWrapper.getQueryRunner no implemented (yet)');
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import React, { useState } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
|
||||
import { dateMath, dateTime, GrafanaTheme2, PanelProps } from '@grafana/data';
|
||||
import { getBackendSrv, getTemplateSrv } from '@grafana/runtime';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { Card, CustomScrollbar, Icon, useStyles2 } from '@grafana/ui';
|
||||
import alertDef from 'app/features/alerting/state/alertDef';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
@ -23,10 +23,9 @@ export function AlertList(props: PanelProps<AlertListOptions>) {
|
||||
const params: any = {
|
||||
state: getStateFilter(props.options.stateFilter),
|
||||
};
|
||||
const panel = getDashboardSrv().getCurrent()?.getPanelById(props.id)!;
|
||||
|
||||
if (props.options.alertName) {
|
||||
params.query = getTemplateSrv().replace(props.options.alertName, panel.scopedVars);
|
||||
params.query = props.replaceVariables(props.options.alertName);
|
||||
}
|
||||
|
||||
if (props.options.folderId >= 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user