Dashboard scenes: Change library panel to set dashboard key to panel instead of library panel. (#83420)

* change library panel so that the dashboard key is attached to the panel instead of the library panel

* make sure the save model gets the id from the panel and not the library panel

* do not reload everything when the library panel is already loaded

* Fix merge issue

* Clean up
This commit is contained in:
Oscar Kilhed 2024-02-27 17:56:29 +01:00 committed by GitHub
parent 96dfb385ca
commit 19743a7fef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 9 deletions

View File

@ -216,7 +216,7 @@ async function buildTestSceneWithLibraryPanel() {
name: 'LibraryPanel A',
title: 'LibraryPanel A title',
uid: '111',
key: 'panel-22',
panelKey: 'panel-22',
model: panel,
version: 1,
};

View File

@ -2,15 +2,22 @@ import { Unsubscribable } from 'rxjs';
import { AppEvents } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { SceneObjectBase, SceneObjectState, SceneObjectUrlSyncHandler, SceneObjectUrlValues } from '@grafana/scenes';
import {
SceneObjectBase,
SceneObjectState,
SceneObjectUrlSyncHandler,
SceneObjectUrlValues,
VizPanel,
} from '@grafana/scenes';
import appEvents from 'app/core/app_events';
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
import { buildPanelEditScene } from '../panel-edit/PanelEditor';
import { createDashboardEditViewFor } from '../settings/utils';
import { findVizPanelByKey, getDashboardSceneFor, isPanelClone } from '../utils/utils';
import { findVizPanelByKey, getDashboardSceneFor, isLibraryPanelChild, isPanelClone } from '../utils/utils';
import { DashboardScene, DashboardSceneState } from './DashboardScene';
import { LibraryVizPanel } from './LibraryVizPanel';
import { ViewPanelScene } from './ViewPanelScene';
import { DashboardRepeatsProcessedEvent } from './types';
@ -71,6 +78,7 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
// 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)) {
@ -83,6 +91,11 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
return;
}
if (isLibraryPanelChild(panel)) {
this._handleLibraryPanel(panel, (p) => this._buildLibraryPanelViewScene(p));
return;
}
update.viewPanelScene = new ViewPanelScene({ panelRef: panel.getRef() });
} else if (viewPanelScene && values.viewPanel === null) {
update.viewPanelScene = undefined;
@ -99,6 +112,11 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
if (!isEditing) {
this._scene.onEnterEditMode();
}
if (isLibraryPanelChild(panel)) {
this._handleLibraryPanel(panel, (p) => {
this._scene.setState({ editPanel: buildPanelEditScene(p) });
});
}
update.editPanel = buildPanelEditScene(panel);
} else if (editPanel && values.editPanel === null) {
update.editPanel = undefined;
@ -109,6 +127,25 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
}
}
private _buildLibraryPanelViewScene(vizPanel: VizPanel) {
this._scene.setState({ viewPanelScene: new ViewPanelScene({ panelRef: vizPanel.getRef() }) });
}
private _handleLibraryPanel(vizPanel: VizPanel, cb: (p: VizPanel) => void): void {
if (!(vizPanel.parent instanceof LibraryVizPanel)) {
throw new Error('Panel is not a child of a LibraryVizPanel');
}
const libraryPanel = vizPanel.parent;
if (libraryPanel.state.isLoaded) {
cb(vizPanel);
} else {
libraryPanel.subscribeToState((n) => {
cb(n.panel!);
});
libraryPanel.activate();
}
}
private _handleViewRepeatClone(viewPanel: string) {
if (!this._eventSub) {
this._eventSub = this._scene.subscribeToEvent(DashboardRepeatsProcessedEvent, () => {

View File

@ -16,6 +16,8 @@ interface LibraryVizPanelState extends SceneObjectState {
uid: string;
name: string;
panel?: VizPanel;
isLoaded?: boolean;
panelKey: string;
_loadedVersion?: number;
}
@ -24,7 +26,8 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
constructor(state: LibraryVizPanelState) {
super({
panel: state.panel ?? getLoadingPanel(state.title),
panel: state.panel ?? getLoadingPanel(state.title, state.panelKey),
isLoaded: state.isLoaded ?? false,
...state,
});
@ -32,7 +35,9 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
}
private _onActivate = () => {
if (!this.state.isLoaded) {
this.loadLibraryPanelFromPanelModel();
}
};
private async loadLibraryPanelFromPanelModel() {
@ -49,6 +54,7 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
const panel = new VizPanel({
title: this.state.title,
key: this.state.panelKey,
options: libPanelModel.options ?? {},
fieldConfig: libPanelModel.fieldConfig,
pluginId: libPanelModel.type,
@ -66,7 +72,7 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
],
});
this.setState({ panel, _loadedVersion: libPanel.version });
this.setState({ panel, _loadedVersion: libPanel.version, isLoaded: true });
} catch (err) {
vizPanel.setState({
_pluginLoadError: 'Unable to load library panel: ' + this.state.uid,
@ -75,8 +81,9 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
}
}
function getLoadingPanel(title: string) {
function getLoadingPanel(title: string, panelKey: string) {
return new VizPanel({
key: panelKey,
title,
menu: new VizPanelMenu({
$behaviors: [panelMenuBehavior],

View File

@ -408,7 +408,7 @@ export function buildGridItemForLibPanel(panel: PanelModel) {
title: panel.title,
uid: panel.libraryPanel.uid,
name: panel.libraryPanel.name,
key: getVizPanelKeyForPanelId(panel.id),
panelKey: getVizPanelKeyForPanelId(panel.id),
});
return new SceneGridItem({

View File

@ -153,8 +153,11 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
w = gridItem.state.width ?? 0;
h = gridItem.state.height ?? 0;
if (!gridItem.state.body.state.panel) {
throw new Error('Library panel has no panel');
}
return {
id: getPanelIdForVizPanel(gridItem.state.body),
id: getPanelIdForVizPanel(gridItem.state.body.state.panel),
title: gridItem.state.body.state.title,
gridPos: { x, y, w, h },
libraryPanel: {

View File

@ -15,6 +15,7 @@ import {
import { initialIntervalVariableModelState } from 'app/features/variables/interval/reducer';
import { DashboardScene } from '../scene/DashboardScene';
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
import { panelMenuBehavior } from '../scene/PanelMenuBehavior';
@ -259,3 +260,7 @@ export function getDefaultVizPanel(dashboard: DashboardScene): VizPanel {
}),
});
}
export function isLibraryPanelChild(vizPanel: VizPanel) {
return vizPanel.parent instanceof LibraryVizPanel;
}