209 lines
5.3 KiB
TypeScript
209 lines
5.3 KiB
TypeScript
import { Subscription } from 'rxjs';
|
|
|
|
import { AnnotationQuery, DashboardCursorSync, dateTimeFormat, DateTimeInput, EventBusSrv } from '@grafana/data';
|
|
import { TimeRangeUpdatedEvent } from '@grafana/runtime';
|
|
import { behaviors, sceneGraph, SceneObject, VizPanel } from '@grafana/scenes';
|
|
|
|
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
|
import { DashboardScene } from '../scene/DashboardScene';
|
|
import { dataLayersToAnnotations } from '../serialization/dataLayersToAnnotations';
|
|
|
|
import { PanelModelCompatibilityWrapper } from './PanelModelCompatibilityWrapper';
|
|
import { findVizPanelByKey, getVizPanelKeyForPanelId } from './utils';
|
|
|
|
/**
|
|
* Will move this to make it the main way we remain somewhat compatible with getDashboardSrv().getCurrent
|
|
*/
|
|
export class DashboardModelCompatibilityWrapper {
|
|
public events = new EventBusSrv();
|
|
private _subs = new Subscription();
|
|
|
|
public constructor(private _scene: DashboardScene) {
|
|
const timeRange = sceneGraph.getTimeRange(_scene);
|
|
|
|
// Copied from DashboardModel, as this function is passed around
|
|
this.formatDate = this.formatDate.bind(this);
|
|
|
|
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 description() {
|
|
return this._scene.state.description;
|
|
}
|
|
|
|
public get editable() {
|
|
return this._scene.state.editable;
|
|
}
|
|
|
|
public get graphTooltip() {
|
|
return this._getSyncMode();
|
|
}
|
|
|
|
public get timepicker() {
|
|
return {
|
|
refresh_intervals: this._scene.state.controls!.state.refreshPicker.state.intervals,
|
|
hidden: this._scene.state.controls!.state.hideTimeControls ?? false,
|
|
};
|
|
}
|
|
|
|
public get timezone() {
|
|
return this.getTimezone();
|
|
}
|
|
|
|
public get weekStart() {
|
|
return sceneGraph.getTimeRange(this._scene).state.weekStart;
|
|
}
|
|
|
|
public get tags() {
|
|
return this._scene.state.tags;
|
|
}
|
|
|
|
public get links() {
|
|
return this._scene.state.links;
|
|
}
|
|
|
|
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,
|
|
};
|
|
}
|
|
|
|
public get panels() {
|
|
const panels = findAllObjects(this._scene, (o) => {
|
|
return Boolean(o instanceof VizPanel);
|
|
});
|
|
return panels.map((p) => new PanelModelCompatibilityWrapper(p as VizPanel));
|
|
}
|
|
|
|
/**
|
|
* Used from from timeseries migration handler to migrate time regions to dashboard annotations
|
|
*/
|
|
public get annotations(): { list: AnnotationQuery[] } {
|
|
const annotations: { list: AnnotationQuery[] } = { list: [] };
|
|
|
|
if (this._scene.state.$data instanceof DashboardDataLayerSet) {
|
|
annotations.list = dataLayersToAnnotations(this._scene.state.$data.state.annotationLayers);
|
|
}
|
|
|
|
return annotations;
|
|
}
|
|
|
|
public getTimezone() {
|
|
const time = sceneGraph.getTimeRange(this._scene);
|
|
return time.getTimeZone();
|
|
}
|
|
|
|
public sharedTooltipModeEnabled() {
|
|
return this._getSyncMode() > 0;
|
|
}
|
|
|
|
public sharedCrosshairModeOnly() {
|
|
return this._getSyncMode() === 1;
|
|
}
|
|
|
|
private _getSyncMode() {
|
|
if (this._scene.state.$behaviors) {
|
|
for (const behavior of this._scene.state.$behaviors) {
|
|
if (behavior instanceof behaviors.CursorSync) {
|
|
return behavior.state.sync;
|
|
}
|
|
}
|
|
}
|
|
|
|
return DashboardCursorSync.Off;
|
|
}
|
|
|
|
public otherPanelInFullscreen(panel: unknown) {
|
|
return false;
|
|
}
|
|
|
|
public formatDate(date: DateTimeInput, format?: string) {
|
|
return dateTimeFormat(date, {
|
|
format,
|
|
timeZone: this.getTimezone(),
|
|
});
|
|
}
|
|
|
|
public getPanelById(id: number): PanelModelCompatibilityWrapper | null {
|
|
const vizPanel = findVizPanelByKey(this._scene, getVizPanelKeyForPanelId(id));
|
|
if (vizPanel) {
|
|
return new PanelModelCompatibilityWrapper(vizPanel);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Mainly implemented to support Getting started panel's dissmis button.
|
|
*/
|
|
public removePanel(panel: PanelModelCompatibilityWrapper) {
|
|
const vizPanel = findVizPanelByKey(this._scene, getVizPanelKeyForPanelId(panel.id));
|
|
if (!vizPanel) {
|
|
console.error('Trying to remove a panel that was not found in scene', panel);
|
|
return;
|
|
}
|
|
|
|
this._scene.removePanel(vizPanel);
|
|
}
|
|
|
|
public canEditAnnotations(dashboardUID?: string) {
|
|
if (!this._scene.canEditDashboard()) {
|
|
return false;
|
|
}
|
|
|
|
if (dashboardUID) {
|
|
return Boolean(this._scene.state.meta.annotationsPermissions?.dashboard.canEdit);
|
|
}
|
|
|
|
return Boolean(this._scene.state.meta.annotationsPermissions?.organization.canEdit);
|
|
}
|
|
|
|
public panelInitialized() {}
|
|
|
|
public destroy() {
|
|
this.events.removeAllListeners();
|
|
this._subs.unsubscribe();
|
|
}
|
|
|
|
public hasUnsavedChanges() {
|
|
return this._scene.state.isDirty;
|
|
}
|
|
}
|
|
|
|
function findAllObjects(root: SceneObject, check: (o: SceneObject) => boolean) {
|
|
let result: SceneObject[] = [];
|
|
root.forEachChild((child) => {
|
|
if (check(child)) {
|
|
result.push(child);
|
|
} else {
|
|
result = result.concat(findAllObjects(child, check));
|
|
}
|
|
});
|
|
|
|
return result;
|
|
}
|