The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts

103 lines
3.6 KiB

import { Unsubscribable } from 'rxjs';
import { AppEvents } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { SceneObjectUrlSyncHandler, SceneObjectUrlValues } from '@grafana/scenes';
import appEvents from 'app/core/app_events';
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
import { createDashboardEditViewFor } from '../settings/utils';
import { findVizPanelByKey, isPanelClone } from '../utils/utils';
import { DashboardScene, DashboardSceneState } from './DashboardScene';
import { ViewPanelScene } from './ViewPanelScene';
import { DashboardRepeatsProcessedEvent } from './types';
export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
private _eventSub?: Unsubscribable;
constructor(private _scene: DashboardScene) {}
getKeys(): string[] {
return ['inspect', 'viewPanel', 'editview'];
}
getUrlState(): SceneObjectUrlValues {
const state = this._scene.state;
return {
inspect: state.inspectPanelKey,
viewPanel: state.viewPanelScene?.getUrlKey(),
editview: state.editview?.getUrlKey(),
};
}
updateFromUrl(values: SceneObjectUrlValues): void {
const { inspectPanelKey, viewPanelScene, meta, isEditing } = this._scene.state;
const update: Partial<DashboardSceneState> = {};
if (typeof values.editview === 'string' && meta.canEdit) {
update.editview = createDashboardEditViewFor(values.editview, this._scene.getRef());
// If we are not in editing (for example after full page reload)
if (!isEditing) {
// Not sure what is best to do here.
// The reason for the timeout is for this change to happen after the url sync has completed
setTimeout(() => this._scene.onEnterEditMode());
}
} else if (values.hasOwnProperty('editview')) {
update.editview = undefined;
}
// Handle inspect object state
if (typeof values.inspect === 'string') {
const panel = findVizPanelByKey(this._scene, values.inspect);
if (!panel) {
appEvents.emit(AppEvents.alertError, ['Panel not found']);
locationService.partial({ inspect: null });
return;
}
update.inspectPanelKey = values.inspect;
update.overlay = new PanelInspectDrawer({ panelRef: panel.getRef() });
} else if (inspectPanelKey) {
update.inspectPanelKey = undefined;
update.overlay = undefined;
}
// Handle view panel state
if (typeof values.viewPanel === 'string') {
const panel = findVizPanelByKey(this._scene, values.viewPanel);
if (!panel) {
// // If we are trying to view a repeat clone that can't be found it might be that the repeats have not been processed yet
if (isPanelClone(values.viewPanel)) {
this._handleViewRepeatClone(values.viewPanel);
return;
}
appEvents.emit(AppEvents.alertError, ['Panel not found']);
locationService.partial({ viewPanel: null });
return;
}
update.viewPanelScene = new ViewPanelScene({ panelRef: panel.getRef() });
} else if (viewPanelScene) {
update.viewPanelScene = undefined;
}
if (Object.keys(update).length > 0) {
this._scene.setState(update);
}
}
private _handleViewRepeatClone(viewPanel: string) {
if (!this._eventSub) {
this._eventSub = this._scene.subscribeToEvent(DashboardRepeatsProcessedEvent, () => {
const panel = findVizPanelByKey(this._scene, viewPanel);
if (panel) {
this._eventSub?.unsubscribe();
this._scene.setState({ viewPanelScene: new ViewPanelScene({ panelRef: panel.getRef() }) });
}
});
}
}
}