Scenes: Copy/paste library panels (#83962)
* Scenes: Copy/paste library panels * more tests
This commit is contained in:
@@ -17,7 +17,11 @@ import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { VariablesChanged } from 'app/features/variables/types';
|
||||
|
||||
import { createWorker } from '../saving/createDetectChangesWorker';
|
||||
import { buildGridItemForPanel, transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
|
||||
import {
|
||||
buildGridItemForLibPanel,
|
||||
buildGridItemForPanel,
|
||||
transformSaveModelToScene,
|
||||
} from '../serialization/transformSaveModelToScene';
|
||||
import { DecoratedRevisionModel } from '../settings/VersionsEditView';
|
||||
import { historySrv } from '../settings/version-history/HistorySrv';
|
||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||
@@ -25,6 +29,7 @@ import { djb2Hash } from '../utils/djb2Hash';
|
||||
|
||||
import { DashboardControls } from './DashboardControls';
|
||||
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
|
||||
jest.mock('../settings/version-history/HistorySrv');
|
||||
jest.mock('../serialization/transformSaveModelToScene');
|
||||
@@ -244,7 +249,7 @@ describe('DashboardScene', () => {
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(5);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
||||
expect(gridItem.state.y).toBe(0);
|
||||
});
|
||||
@@ -255,7 +260,7 @@ describe('DashboardScene', () => {
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(5);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
||||
});
|
||||
|
||||
@@ -265,7 +270,7 @@ describe('DashboardScene', () => {
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridRow = body.state.children[0] as SceneGridRow;
|
||||
|
||||
expect(body.state.children.length).toBe(3);
|
||||
expect(body.state.children.length).toBe(4);
|
||||
expect(gridRow.state.key).toBe('panel-5');
|
||||
expect(gridRow.state.children[0].state.key).toBe('griditem-1');
|
||||
expect(gridRow.state.children[1].state.key).toBe('griditem-2');
|
||||
@@ -313,7 +318,7 @@ describe('DashboardScene', () => {
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridRow = body.state.children[0] as SceneGridRow;
|
||||
|
||||
expect(body.state.children.length).toBe(4);
|
||||
expect(body.state.children.length).toBe(5);
|
||||
expect(gridRow.state.children.length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -333,6 +338,36 @@ describe('DashboardScene', () => {
|
||||
expect(gridRow.state.children.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Should fail to copy a panel if it does not have a grid item parent', () => {
|
||||
const vizPanel = new VizPanel({
|
||||
title: 'Panel Title',
|
||||
key: 'panel-5',
|
||||
pluginId: 'timeseries',
|
||||
});
|
||||
|
||||
scene.copyPanel(vizPanel);
|
||||
|
||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
||||
});
|
||||
|
||||
it('Should fail to copy a library panel if it does not have a grid item parent', () => {
|
||||
const libVizPanel = new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'libraryPanel',
|
||||
panelKey: 'panel-4',
|
||||
title: 'Library Panel',
|
||||
panel: new VizPanel({
|
||||
title: 'Library Panel',
|
||||
key: 'panel-4',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
});
|
||||
|
||||
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
||||
|
||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
||||
});
|
||||
|
||||
it('Should copy a panel', () => {
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body;
|
||||
scene.copyPanel(vizPanel as VizPanel);
|
||||
@@ -340,6 +375,15 @@ describe('DashboardScene', () => {
|
||||
expect(scene.state.hasCopiedPanel).toBe(true);
|
||||
});
|
||||
|
||||
it('Should copy a library viz panel', () => {
|
||||
const libVizPanel = ((scene.state.body as SceneGridLayout).state.children[4] as SceneGridItem).state
|
||||
.body as LibraryVizPanel;
|
||||
|
||||
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
||||
|
||||
expect(scene.state.hasCopiedPanel).toBe(true);
|
||||
});
|
||||
|
||||
it('Should paste a panel', () => {
|
||||
scene.setState({ hasCopiedPanel: true });
|
||||
jest.spyOn(JSON, 'parse').mockReturnThis();
|
||||
@@ -359,19 +403,49 @@ describe('DashboardScene', () => {
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(5);
|
||||
expect(buildGridItemForPanel).toHaveBeenCalledTimes(1);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
||||
expect(gridItem.state.y).toBe(0);
|
||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
||||
});
|
||||
|
||||
it('Should paste a library viz panel', () => {
|
||||
scene.setState({ hasCopiedPanel: true });
|
||||
jest.spyOn(JSON, 'parse').mockReturnValue({ libraryPanel: { uid: 'uid', name: 'libraryPanel' } });
|
||||
jest.mocked(buildGridItemForLibPanel).mockReturnValue(
|
||||
new SceneGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
title: 'Library Panel',
|
||||
uid: 'uid',
|
||||
name: 'libraryPanel',
|
||||
panelKey: 'panel-4',
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
scene.pastePanel();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
|
||||
const libVizPanel = gridItem.state.body as LibraryVizPanel;
|
||||
|
||||
expect(buildGridItemForLibPanel).toHaveBeenCalledTimes(1);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(libVizPanel.state.panelKey).toBe('panel-5');
|
||||
expect(libVizPanel.state.panel?.state.key).toBe('panel-5');
|
||||
expect(gridItem.state.y).toBe(0);
|
||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
||||
});
|
||||
|
||||
it('Should create a new add library panel widget', () => {
|
||||
scene.onCreateLibPanelWidget();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(5);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
||||
expect(gridItem.state.y).toBe(0);
|
||||
});
|
||||
@@ -575,6 +649,19 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner2', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'libraryPanel',
|
||||
panelKey: 'panel-4',
|
||||
title: 'Library Panel',
|
||||
panel: new VizPanel({
|
||||
title: 'Library Panel',
|
||||
key: 'panel-4',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
...overrides,
|
||||
|
||||
@@ -33,7 +33,11 @@ import { PanelEditor } from '../panel-edit/PanelEditor';
|
||||
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
|
||||
import { SaveDashboardDrawer } from '../saving/SaveDashboardDrawer';
|
||||
import { DashboardSceneRenderer } from '../scene/DashboardSceneRenderer';
|
||||
import { buildGridItemForPanel, transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
|
||||
import {
|
||||
buildGridItemForLibPanel,
|
||||
buildGridItemForPanel,
|
||||
transformSaveModelToScene,
|
||||
} from '../serialization/transformSaveModelToScene';
|
||||
import { gridItemToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
import { DecoratedRevisionModel } from '../settings/VersionsEditView';
|
||||
import { DashboardEditView } from '../settings/utils';
|
||||
@@ -57,6 +61,7 @@ import {
|
||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
||||
import { DashboardControls } from './DashboardControls';
|
||||
import { DashboardSceneUrlSync } from './DashboardSceneUrlSync';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from './PanelRepeaterGridItem';
|
||||
import { ViewPanelScene } from './ViewPanelScene';
|
||||
import { setupKeyboardShortcuts } from './keyboardShortcuts';
|
||||
@@ -480,7 +485,17 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
return;
|
||||
}
|
||||
|
||||
const gridItem = vizPanel.parent;
|
||||
let gridItem = vizPanel.parent;
|
||||
|
||||
if (vizPanel.parent instanceof LibraryVizPanel) {
|
||||
const libraryVizPanel = vizPanel.parent;
|
||||
|
||||
if (!libraryVizPanel.parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
gridItem = libraryVizPanel.parent;
|
||||
}
|
||||
|
||||
const jsonData = gridItemToPanel(gridItem);
|
||||
|
||||
@@ -497,8 +512,10 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
const jsonData = store.get(LS_PANEL_COPY_KEY);
|
||||
const jsonObj = JSON.parse(jsonData);
|
||||
const panelModel = new PanelModel(jsonObj);
|
||||
const gridItem = !panelModel.libraryPanel
|
||||
? buildGridItemForPanel(panelModel)
|
||||
: buildGridItemForLibPanel(panelModel);
|
||||
|
||||
const gridItem = buildGridItemForPanel(panelModel);
|
||||
const sceneGridLayout = this.state.body;
|
||||
|
||||
if (!(gridItem instanceof SceneGridItem) && !(gridItem instanceof PanelRepeaterGridItem)) {
|
||||
@@ -507,7 +524,17 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
|
||||
const panelId = dashboardSceneGraph.getNextPanelId(this);
|
||||
|
||||
if (gridItem instanceof SceneGridItem && gridItem.state.body) {
|
||||
if (gridItem instanceof SceneGridItem && gridItem.state.body instanceof LibraryVizPanel) {
|
||||
const panelKey = getVizPanelKeyForPanelId(panelId);
|
||||
|
||||
gridItem.state.body.setState({ panelKey });
|
||||
|
||||
const vizPanel = gridItem.state.body.state.panel;
|
||||
|
||||
if (vizPanel instanceof VizPanel) {
|
||||
vizPanel.setState({ key: panelKey });
|
||||
}
|
||||
} else if (gridItem instanceof SceneGridItem && gridItem.state.body) {
|
||||
gridItem.state.body.setState({
|
||||
key: getVizPanelKeyForPanelId(panelId),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user