mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 20:59:35 +08:00
DashboardScene: Allow unlinking a library panel (#83956)
* DashboardScene: Allow unlinking a library panel * Betterer * Revert * Review
This commit is contained in:
@ -490,6 +490,39 @@ describe('DashboardScene', () => {
|
|||||||
const gridRow = body.state.children[2] as SceneGridRow;
|
const gridRow = body.state.children[2] as SceneGridRow;
|
||||||
expect(gridRow.state.children.length).toBe(1);
|
expect(gridRow.state.children.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should unlink a library panel', () => {
|
||||||
|
const libPanel = new LibraryVizPanel({
|
||||||
|
title: 'title',
|
||||||
|
uid: 'abc',
|
||||||
|
name: 'lib panel',
|
||||||
|
panelKey: 'panel-1',
|
||||||
|
isLoaded: true,
|
||||||
|
panel: new VizPanel({
|
||||||
|
title: 'Panel B',
|
||||||
|
pluginId: 'table',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const scene = buildTestScene({
|
||||||
|
body: new SceneGridLayout({
|
||||||
|
children: [
|
||||||
|
new SceneGridItem({
|
||||||
|
key: 'griditem-2',
|
||||||
|
body: libPanel,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
scene.unlinkLibraryPanel(libPanel);
|
||||||
|
|
||||||
|
const body = scene.state.body as SceneGridLayout;
|
||||||
|
const gridItem = body.state.children[0] as SceneGridItem;
|
||||||
|
|
||||||
|
expect(body.state.children.length).toBe(1);
|
||||||
|
expect(gridItem.state.body).toBeInstanceOf(VizPanel);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -603,6 +603,23 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unlinkLibraryPanel(panel: LibraryVizPanel) {
|
||||||
|
if (!panel.parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridItem = panel.parent;
|
||||||
|
|
||||||
|
if (!(gridItem instanceof SceneGridItem || gridItem instanceof PanelRepeaterGridItem)) {
|
||||||
|
console.error('Trying to duplicate a panel in a layout that is not SceneGridItem or PanelRepeaterGridItem');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gridItem?.setState({
|
||||||
|
body: panel.state.panel?.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public showModal(modal: SceneObject) {
|
public showModal(modal: SceneObject) {
|
||||||
this.setState({ overlay: modal });
|
this.setState({ overlay: modal });
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '
|
|||||||
import { DashboardScene } from './DashboardScene';
|
import { DashboardScene } from './DashboardScene';
|
||||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||||
import { VizPanelLinks, VizPanelLinksMenu } from './PanelLinks';
|
import { VizPanelLinks, VizPanelLinksMenu } from './PanelLinks';
|
||||||
|
import { UnlinkLibraryPanelModal } from './UnlinkLibraryPanelModal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behavior is called when VizPanelMenu is activated (ie when it's opened).
|
* Behavior is called when VizPanelMenu is activated (ie when it's opened).
|
||||||
@ -37,6 +38,7 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||||||
// hm.. add another generic param to SceneObject to specify parent type?
|
// hm.. add another generic param to SceneObject to specify parent type?
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
const panel = menu.parent as VizPanel;
|
const panel = menu.parent as VizPanel;
|
||||||
|
const parent = panel.parent;
|
||||||
const plugin = panel.getPlugin();
|
const plugin = panel.getPlugin();
|
||||||
|
|
||||||
const items: PanelMenuItem[] = [];
|
const items: PanelMenuItem[] = [];
|
||||||
@ -101,8 +103,18 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (panel.parent instanceof LibraryVizPanel) {
|
if (parent instanceof LibraryVizPanel) {
|
||||||
// TODO: Implement lib panel unlinking
|
moreSubMenu.push({
|
||||||
|
text: t('panel.header-menu.unlink-library-panel', `Unlink library panel`),
|
||||||
|
onClick: () => {
|
||||||
|
DashboardInteractions.panelMenuItemClicked('unlinkLibraryPanel');
|
||||||
|
dashboard.showModal(
|
||||||
|
new UnlinkLibraryPanelModal({
|
||||||
|
panelRef: parent.getRef(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
moreSubMenu.push({
|
moreSubMenu.push({
|
||||||
text: t('panel.header-menu.create-library-panel', `Create library panel`),
|
text: t('panel.header-menu.create-library-panel', `Create library panel`),
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { SceneComponentProps, SceneObjectBase, SceneObjectRef, SceneObjectState } from '@grafana/scenes';
|
||||||
|
|
||||||
|
import { ModalSceneObjectLike } from '../sharing/types';
|
||||||
|
import { getDashboardSceneFor } from '../utils/utils';
|
||||||
|
|
||||||
|
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||||
|
import { UnlinkModal } from './UnlinkModal';
|
||||||
|
|
||||||
|
interface UnlinkLibraryPanelModalState extends SceneObjectState {
|
||||||
|
panelRef?: SceneObjectRef<LibraryVizPanel>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UnlinkLibraryPanelModal
|
||||||
|
extends SceneObjectBase<UnlinkLibraryPanelModalState>
|
||||||
|
implements ModalSceneObjectLike
|
||||||
|
{
|
||||||
|
static Component = UnlinkLibraryPanelModalRenderer;
|
||||||
|
|
||||||
|
public onDismiss = () => {
|
||||||
|
const dashboard = getDashboardSceneFor(this);
|
||||||
|
dashboard.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
public onConfirm = () => {
|
||||||
|
const dashboard = getDashboardSceneFor(this);
|
||||||
|
dashboard.unlinkLibraryPanel(this.state.panelRef!.resolve());
|
||||||
|
dashboard.closeModal();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnlinkLibraryPanelModalRenderer({ model }: SceneComponentProps<UnlinkLibraryPanelModal>) {
|
||||||
|
return (
|
||||||
|
<UnlinkModal
|
||||||
|
isOpen={true}
|
||||||
|
onConfirm={() => {
|
||||||
|
model.onConfirm();
|
||||||
|
model.onDismiss();
|
||||||
|
}}
|
||||||
|
onDismiss={model.onDismiss}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -33,7 +33,7 @@ import { StoreState } from 'app/types';
|
|||||||
import { PanelOptionsChangedEvent, ShowModalReactEvent } from 'app/types/events';
|
import { PanelOptionsChangedEvent, ShowModalReactEvent } from 'app/types/events';
|
||||||
|
|
||||||
import { notifyApp } from '../../../../core/actions';
|
import { notifyApp } from '../../../../core/actions';
|
||||||
import { UnlinkModal } from '../../../library-panels/components/UnlinkModal/UnlinkModal';
|
import { UnlinkModal } from '../../../dashboard-scene/scene/UnlinkModal';
|
||||||
import { isPanelModelLibraryPanel } from '../../../library-panels/guard';
|
import { isPanelModelLibraryPanel } from '../../../library-panels/guard';
|
||||||
import { getVariablesByKey } from '../../../variables/state/selectors';
|
import { getVariablesByKey } from '../../../variables/state/selectors';
|
||||||
import { DashboardPanel } from '../../dashgrid/DashboardPanel';
|
import { DashboardPanel } from '../../dashgrid/DashboardPanel';
|
||||||
|
@ -9,8 +9,8 @@ import store from 'app/core/store';
|
|||||||
import { ShareModal } from 'app/features/dashboard/components/ShareModal';
|
import { ShareModal } from 'app/features/dashboard/components/ShareModal';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
||||||
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
||||||
|
import { UnlinkModal } from 'app/features/dashboard-scene/scene/UnlinkModal';
|
||||||
import { AddLibraryPanelModal } from 'app/features/library-panels/components/AddLibraryPanelModal/AddLibraryPanelModal';
|
import { AddLibraryPanelModal } from 'app/features/library-panels/components/AddLibraryPanelModal/AddLibraryPanelModal';
|
||||||
import { UnlinkModal } from 'app/features/library-panels/components/UnlinkModal/UnlinkModal';
|
|
||||||
import { cleanUpPanelState } from 'app/features/panel/state/actions';
|
import { cleanUpPanelState } from 'app/features/panel/state/actions';
|
||||||
import { dispatch } from 'app/store/store';
|
import { dispatch } from 'app/store/store';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user