grafana/public/app/features/dashboard-scene/scene/DashboardSceneUrlSync.ts

103 lines
3.4 KiB
TypeScript

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 } from '../utils/utils';
import { DashboardScene, DashboardSceneState } from './DashboardScene';
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.viewPanelKey,
editview: state.editview?.getUrlKey(),
};
}
updateFromUrl(values: SceneObjectUrlValues): void {
const { inspectPanelKey, viewPanelKey, meta, isEditing } = this._scene.state;
const update: Partial<DashboardSceneState> = {};
if (typeof values.editview === 'string' && meta.canEdit) {
update.editview = createDashboardEditViewFor(values.editview);
// 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 (values.viewPanel.indexOf('clone')) {
this._handleViewRepeatClone(values.viewPanel);
return;
}
appEvents.emit(AppEvents.alertError, ['Panel not found']);
locationService.partial({ viewPanel: null });
return;
}
update.viewPanelKey = values.viewPanel;
} else if (viewPanelKey) {
update.viewPanelKey = 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({ viewPanelKey: viewPanel });
}
});
}
}
}