mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DashboardScene: Use numeric panel ids in url (#74005)
* DashboardScene: Use numeric panel ids in url * Rename fix * Fixed tests
This commit is contained in:
parent
dc6675cade
commit
0563b51098
@ -133,7 +133,7 @@ describe('DashboardScenePage', () => {
|
||||
|
||||
expect(await screen.findByTitle('Panel A')).toBeInTheDocument();
|
||||
|
||||
act(() => locationService.partial({ viewPanel: 'panel-2' }));
|
||||
act(() => locationService.partial({ viewPanel: '2' }));
|
||||
|
||||
expect(screen.queryByTitle('Panel A')).not.toBeInTheDocument();
|
||||
expect(await screen.findByTitle('Panel B')).toBeInTheDocument();
|
||||
|
@ -6,20 +6,20 @@ describe('DashboardScene', () => {
|
||||
describe('Given a standard scene', () => {
|
||||
it('Should set inspectPanelKey when url has inspect key', () => {
|
||||
const scene = buildTestScene();
|
||||
scene.urlSync?.updateFromUrl({ inspect: 'panel-2' });
|
||||
expect(scene.state.inspectPanelKey).toBe('panel-2');
|
||||
scene.urlSync?.updateFromUrl({ inspect: '2' });
|
||||
expect(scene.state.inspectPanelId).toBe('2');
|
||||
});
|
||||
|
||||
it('Should handle inspect key that is not found', () => {
|
||||
const scene = buildTestScene();
|
||||
scene.urlSync?.updateFromUrl({ inspect: '12321' });
|
||||
expect(scene.state.inspectPanelKey).toBe(undefined);
|
||||
expect(scene.state.inspectPanelId).toBe(undefined);
|
||||
});
|
||||
|
||||
it('Should set viewPanelKey when url has viewPanel', () => {
|
||||
const scene = buildTestScene();
|
||||
scene.urlSync?.updateFromUrl({ viewPanel: 'panel-2' });
|
||||
expect(scene.state.viewPanelKey).toBe('panel-2');
|
||||
scene.urlSync?.updateFromUrl({ viewPanel: '2' });
|
||||
expect(scene.state.viewPanelId).toBe('2');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -16,8 +16,7 @@ import {
|
||||
|
||||
import { DashboardSceneRenderer } from '../scene/DashboardSceneRenderer';
|
||||
import { SaveDashboardDrawer } from '../serialization/SaveDashboardDrawer';
|
||||
import { findVizPanel } from '../utils/findVizPanel';
|
||||
import { forceRenderChildren } from '../utils/utils';
|
||||
import { findVizPanelById, forceRenderChildren } from '../utils/utils';
|
||||
|
||||
import { DashboardSceneUrlSync } from './DashboardSceneUrlSync';
|
||||
|
||||
@ -29,10 +28,10 @@ export interface DashboardSceneState extends SceneObjectState {
|
||||
controls?: SceneObject[];
|
||||
isEditing?: boolean;
|
||||
isDirty?: boolean;
|
||||
/** Scene object key for object to inspect */
|
||||
inspectPanelKey?: string;
|
||||
/** Scene object key for object to view in fullscreen */
|
||||
viewPanelKey?: string;
|
||||
/** Panel to inspect */
|
||||
inspectPanelId?: string;
|
||||
/** Panel to view in full screen */
|
||||
viewPanelId?: string;
|
||||
/** Scene object that handles the current drawer */
|
||||
drawer?: SceneObject;
|
||||
}
|
||||
@ -129,7 +128,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
url: locationUtil.getUrlForPartial(location, { viewPanel: null, inspect: null }),
|
||||
};
|
||||
|
||||
if (this.state.viewPanelKey) {
|
||||
if (this.state.viewPanelId) {
|
||||
pageNav = {
|
||||
text: 'View panel',
|
||||
parentItem: pageNav,
|
||||
@ -142,8 +141,8 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
/**
|
||||
* Returns the body (layout) or the full view panel
|
||||
*/
|
||||
public getBodyToRender(viewPanelKey?: string): SceneObject {
|
||||
const viewPanel = findVizPanel(this, viewPanelKey);
|
||||
public getBodyToRender(viewPanelId?: string): SceneObject {
|
||||
const viewPanel = findVizPanelById(this, viewPanelId);
|
||||
return viewPanel ?? this.state.body;
|
||||
}
|
||||
|
||||
|
@ -11,11 +11,11 @@ import { DashboardScene } from './DashboardScene';
|
||||
import { NavToolbarActions } from './NavToolbarActions';
|
||||
|
||||
export function DashboardSceneRenderer({ model }: SceneComponentProps<DashboardScene>) {
|
||||
const { controls, viewPanelKey, drawer } = model.useState();
|
||||
const { controls, viewPanelId, drawer } = model.useState();
|
||||
const styles = useStyles2(getStyles);
|
||||
const location = useLocation();
|
||||
const pageNav = model.getPageNav(location);
|
||||
const bodyToRender = model.getBodyToRender(viewPanelKey);
|
||||
const bodyToRender = model.getBodyToRender(viewPanelId);
|
||||
|
||||
return (
|
||||
<Page navId="scenes" pageNav={pageNav} layout={PageLayoutType.Custom}>
|
||||
|
@ -4,7 +4,7 @@ import { SceneObjectUrlSyncHandler, SceneObjectUrlValues } from '@grafana/scenes
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
|
||||
import { findVizPanel } from '../utils/findVizPanel';
|
||||
import { findVizPanelById } from '../utils/utils';
|
||||
|
||||
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
||||
|
||||
@ -17,41 +17,41 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
||||
|
||||
getUrlState(): SceneObjectUrlValues {
|
||||
const state = this._scene.state;
|
||||
return { inspect: state.inspectPanelKey, viewPanel: state.viewPanelKey };
|
||||
return { inspect: state.inspectPanelId, viewPanel: state.viewPanelId };
|
||||
}
|
||||
|
||||
updateFromUrl(values: SceneObjectUrlValues): void {
|
||||
const { inspectPanelKey, viewPanelKey } = this._scene.state;
|
||||
const { inspectPanelId, viewPanelId } = this._scene.state;
|
||||
const update: Partial<DashboardSceneState> = {};
|
||||
|
||||
// Handle inspect object state
|
||||
if (typeof values.inspect === 'string') {
|
||||
const panel = findVizPanel(this._scene, values.inspect);
|
||||
const panel = findVizPanelById(this._scene, values.inspect);
|
||||
if (!panel) {
|
||||
appEvents.emit(AppEvents.alertError, ['Panel not found']);
|
||||
locationService.partial({ inspect: null });
|
||||
return;
|
||||
}
|
||||
|
||||
update.inspectPanelKey = values.inspect;
|
||||
update.inspectPanelId = values.inspect;
|
||||
update.drawer = new PanelInspectDrawer(panel);
|
||||
} else if (inspectPanelKey) {
|
||||
update.inspectPanelKey = undefined;
|
||||
} else if (inspectPanelId) {
|
||||
update.inspectPanelId = undefined;
|
||||
update.drawer = undefined;
|
||||
}
|
||||
|
||||
// Handle view panel state
|
||||
if (typeof values.viewPanel === 'string') {
|
||||
const panel = findVizPanel(this._scene, values.viewPanel);
|
||||
const panel = findVizPanelById(this._scene, values.viewPanel);
|
||||
if (!panel) {
|
||||
appEvents.emit(AppEvents.alertError, ['Panel not found']);
|
||||
locationService.partial({ viewPanel: null });
|
||||
return;
|
||||
}
|
||||
|
||||
update.viewPanelKey = values.viewPanel;
|
||||
} else if (viewPanelKey) {
|
||||
update.viewPanelKey = undefined;
|
||||
update.viewPanelId = values.viewPanel;
|
||||
} else if (viewPanelId) {
|
||||
update.viewPanelId = undefined;
|
||||
}
|
||||
|
||||
if (Object.keys(update).length > 0) {
|
||||
|
@ -13,7 +13,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export const NavToolbarActions = React.memo<Props>(({ dashboard }) => {
|
||||
const { actions = [], isEditing, viewPanelKey, isDirty, uid } = dashboard.useState();
|
||||
const { actions = [], isEditing, viewPanelId, isDirty, uid } = dashboard.useState();
|
||||
const toolbarActions = (actions ?? []).map((action) => <action.Component key={action.state.key} model={action} />);
|
||||
|
||||
if (uid) {
|
||||
@ -29,7 +29,7 @@ export const NavToolbarActions = React.memo<Props>(({ dashboard }) => {
|
||||
|
||||
toolbarActions.push(<NavToolbarSeparator leftActionsSeparator key="separator" />);
|
||||
|
||||
if (viewPanelKey) {
|
||||
if (viewPanelId) {
|
||||
toolbarActions.push(
|
||||
<Button
|
||||
onClick={() => locationService.partial({ viewPanel: null })}
|
||||
|
@ -3,6 +3,8 @@ import { locationService } from '@grafana/runtime';
|
||||
import { VizPanel, VizPanelMenu } from '@grafana/scenes';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
import { getPanelIdForVizPanel } from '../utils/utils';
|
||||
|
||||
/**
|
||||
* Behavior is called when VizPanelMenu is activated (ie when it's opened).
|
||||
*/
|
||||
@ -22,7 +24,7 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
||||
iconClassName: 'eye',
|
||||
shortcut: 'v',
|
||||
// Hm... need the numeric id to be url compatible?
|
||||
href: locationUtil.getUrlForPartial(location, { viewPanel: panel.state.key }),
|
||||
href: locationUtil.getUrlForPartial(location, { viewPanel: getPanelIdForVizPanel(panel) }),
|
||||
});
|
||||
|
||||
items.push({
|
||||
@ -30,7 +32,7 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
||||
iconClassName: 'info-circle',
|
||||
shortcut: 'i',
|
||||
// Hm... need the numeric id to be url compatible?
|
||||
href: locationUtil.getUrlForPartial(location, { inspect: panel.state.key }),
|
||||
href: locationUtil.getUrlForPartial(location, { inspect: getPanelIdForVizPanel(panel) }),
|
||||
});
|
||||
|
||||
menu.setState({ items });
|
||||
|
@ -3,7 +3,7 @@ import { Dashboard, defaultDashboard, FieldConfigSource, Panel } from '@grafana/
|
||||
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { getPanelIdForVizPanelKey } from '../utils/utils';
|
||||
import { getPanelIdForVizPanel } from '../utils/utils';
|
||||
|
||||
export function transformSceneToSaveModel(scene: DashboardScene): Dashboard {
|
||||
const state = scene.state;
|
||||
@ -40,7 +40,7 @@ function gridItemToPanel(gridItem: SceneGridItem): Panel {
|
||||
}
|
||||
|
||||
const panel: Panel = {
|
||||
id: getPanelIdForVizPanelKey(vizPanel.state.key!),
|
||||
id: getPanelIdForVizPanel(vizPanel),
|
||||
type: vizPanel.state.pluginId,
|
||||
title: vizPanel.state.title,
|
||||
gridPos: {
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { sceneGraph, SceneObject, VizPanel } from '@grafana/scenes';
|
||||
|
||||
export function findVizPanel(scene: SceneObject, key: string | undefined): VizPanel | null {
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const obj = sceneGraph.findObject(scene, (obj) => obj.state.key === key);
|
||||
if (obj instanceof VizPanel) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
@ -1,11 +1,27 @@
|
||||
import { SceneDeactivationHandler, SceneObject } from '@grafana/scenes';
|
||||
import { SceneDeactivationHandler, sceneGraph, SceneObject, VizPanel } from '@grafana/scenes';
|
||||
|
||||
export function getVizPanelKeyForPanelId(panelId: number) {
|
||||
return `panel-${panelId}`;
|
||||
}
|
||||
|
||||
export function getPanelIdForVizPanelKey(key: string) {
|
||||
return parseInt(key.replace('panel-', ''), 10);
|
||||
export function getPanelIdForVizPanel(panel: VizPanel): number {
|
||||
return parseInt(panel.state.key!.replace('panel-', ''), 10);
|
||||
}
|
||||
|
||||
export function findVizPanelById(scene: SceneObject, id: string | undefined): VizPanel | null {
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const panelId = parseInt(id, 10);
|
||||
const key = getVizPanelKeyForPanelId(panelId);
|
||||
|
||||
const obj = sceneGraph.findObject(scene, (obj) => obj.state.key === key);
|
||||
if (obj instanceof VizPanel) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user