[v11.0.x] DashboardScene: Move add library panel view from grid item to drawer (#86409)
DashboardScene: Move add library panel view from grid item to drawer (#86257)
* DashboardScene: Add library panel in drawer
* DashboardScene: Move add libray panel view to a drawer instead of a grid item
* Update
* Update tests
(cherry picked from commit 5837def850)
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
co-authored by
Torkel Ödegaard
parent
df2fee63a5
commit
6881eabedf
@@ -0,0 +1,74 @@
|
|||||||
|
import { SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
|
||||||
|
import { LibraryPanel } from '@grafana/schema/dist/esm/index.gen';
|
||||||
|
|
||||||
|
import { activateFullSceneTree } from '../utils/test-utils';
|
||||||
|
|
||||||
|
import { AddLibraryPanelDrawer } from './AddLibraryPanelDrawer';
|
||||||
|
import { DashboardGridItem } from './DashboardGridItem';
|
||||||
|
import { DashboardScene } from './DashboardScene';
|
||||||
|
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||||
|
|
||||||
|
describe('AddLibraryPanelWidget', () => {
|
||||||
|
let dashboard: DashboardScene;
|
||||||
|
let addLibPanelDrawer: AddLibraryPanelDrawer;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const result = await buildTestScene();
|
||||||
|
dashboard = result.dashboard;
|
||||||
|
addLibPanelDrawer = result.drawer;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add library panel from menu', () => {
|
||||||
|
const panelInfo: LibraryPanel = {
|
||||||
|
uid: 'uid',
|
||||||
|
model: {
|
||||||
|
type: 'timeseries',
|
||||||
|
},
|
||||||
|
name: 'name',
|
||||||
|
version: 1,
|
||||||
|
type: 'timeseries',
|
||||||
|
};
|
||||||
|
|
||||||
|
addLibPanelDrawer.onAddLibraryPanel(panelInfo);
|
||||||
|
|
||||||
|
const layout = dashboard.state.body as SceneGridLayout;
|
||||||
|
const gridItem = layout.state.children[0] as DashboardGridItem;
|
||||||
|
|
||||||
|
expect(layout.state.children.length).toBe(1);
|
||||||
|
expect(gridItem.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||||
|
expect((gridItem.state.body! as LibraryVizPanel).state.panelKey).toBe('panel-1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error if adding lib panel in a layout that is not SceneGridLayout', () => {
|
||||||
|
dashboard.setState({ body: undefined });
|
||||||
|
|
||||||
|
expect(() => addLibPanelDrawer.onAddLibraryPanel({} as LibraryPanel)).toThrow(
|
||||||
|
'Trying to add a library panel in a layout that is not SceneGridLayout'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function buildTestScene() {
|
||||||
|
const drawer = new AddLibraryPanelDrawer({});
|
||||||
|
const dashboard = new DashboardScene({
|
||||||
|
$timeRange: new SceneTimeRange({}),
|
||||||
|
title: 'hello',
|
||||||
|
uid: 'dash-1',
|
||||||
|
version: 4,
|
||||||
|
meta: {
|
||||||
|
canEdit: true,
|
||||||
|
},
|
||||||
|
body: new SceneGridLayout({
|
||||||
|
children: [],
|
||||||
|
}),
|
||||||
|
overlay: drawer,
|
||||||
|
});
|
||||||
|
|
||||||
|
activateFullSceneTree(dashboard);
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 1));
|
||||||
|
|
||||||
|
dashboard.onEnterEditMode();
|
||||||
|
|
||||||
|
return { dashboard, drawer };
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { SceneComponentProps, SceneGridLayout, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||||
|
import { LibraryPanel } from '@grafana/schema';
|
||||||
|
import { Drawer } from '@grafana/ui';
|
||||||
|
import { t } from 'app/core/internationalization';
|
||||||
|
import {
|
||||||
|
LibraryPanelsSearch,
|
||||||
|
LibraryPanelsSearchVariant,
|
||||||
|
} from 'app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch';
|
||||||
|
|
||||||
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||||
|
import { NEW_PANEL_HEIGHT, NEW_PANEL_WIDTH, getDashboardSceneFor, getVizPanelKeyForPanelId } from '../utils/utils';
|
||||||
|
|
||||||
|
import { DashboardGridItem } from './DashboardGridItem';
|
||||||
|
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||||
|
|
||||||
|
export interface AddLibraryPanelDrawerState extends SceneObjectState {}
|
||||||
|
|
||||||
|
export class AddLibraryPanelDrawer extends SceneObjectBase<AddLibraryPanelDrawerState> {
|
||||||
|
public onClose = () => {
|
||||||
|
getDashboardSceneFor(this).closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
public onAddLibraryPanel = (panelInfo: LibraryPanel) => {
|
||||||
|
const dashboard = getDashboardSceneFor(this);
|
||||||
|
const layout = dashboard.state.body;
|
||||||
|
|
||||||
|
if (!(layout instanceof SceneGridLayout)) {
|
||||||
|
throw new Error('Trying to add a library panel in a layout that is not SceneGridLayout');
|
||||||
|
}
|
||||||
|
|
||||||
|
const panelId = dashboardSceneGraph.getNextPanelId(dashboard);
|
||||||
|
|
||||||
|
const body = new LibraryVizPanel({
|
||||||
|
title: 'Panel Title',
|
||||||
|
uid: panelInfo.uid,
|
||||||
|
name: panelInfo.name,
|
||||||
|
panelKey: getVizPanelKeyForPanelId(panelId),
|
||||||
|
});
|
||||||
|
|
||||||
|
const newGridItem = new DashboardGridItem({
|
||||||
|
height: NEW_PANEL_HEIGHT,
|
||||||
|
width: NEW_PANEL_WIDTH,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
body: body,
|
||||||
|
key: `grid-item-${panelId}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
layout.setState({ children: [newGridItem, ...layout.state.children] });
|
||||||
|
|
||||||
|
this.onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
static Component = ({ model }: SceneComponentProps<AddLibraryPanelDrawer>) => {
|
||||||
|
const title = t('library-panel.add-widget.title', 'Add panel from panel library');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Drawer title={title} onClose={model.onClose}>
|
||||||
|
<LibraryPanelsSearch
|
||||||
|
onClick={model.onAddLibraryPanel}
|
||||||
|
variant={LibraryPanelsSearchVariant.Tight}
|
||||||
|
showPanelFilter
|
||||||
|
/>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
import { SceneGridLayout, SceneGridRow, SceneTimeRange } from '@grafana/scenes';
|
|
||||||
import { LibraryPanel } from '@grafana/schema/dist/esm/index.gen';
|
|
||||||
|
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
|
||||||
import { activateFullSceneTree } from '../utils/test-utils';
|
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
|
||||||
import { DashboardGridItem } from './DashboardGridItem';
|
|
||||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
|
||||||
|
|
||||||
describe('AddLibraryPanelWidget', () => {
|
|
||||||
let dashboard: DashboardScene;
|
|
||||||
let addLibPanelWidget: AddLibraryPanelWidget;
|
|
||||||
const mockEvent = {
|
|
||||||
preventDefault: jest.fn(),
|
|
||||||
} as unknown as React.MouseEvent<HTMLButtonElement>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const result = await buildTestScene();
|
|
||||||
dashboard = result.dashboard;
|
|
||||||
addLibPanelWidget = result.addLibPanelWidget;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the dashboard', () => {
|
|
||||||
expect(addLibPanelWidget.getDashboard()).toBe(dashboard);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should cancel adding a lib panel', () => {
|
|
||||||
addLibPanelWidget.onCancelAddPanel(mockEvent);
|
|
||||||
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should cancel lib panel at correct position', () => {
|
|
||||||
const anotherLibPanelWidget = new AddLibraryPanelWidget({ key: 'panel-2' });
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
|
|
||||||
body.setState({
|
|
||||||
children: [
|
|
||||||
...body.state.children,
|
|
||||||
new DashboardGridItem({
|
|
||||||
key: 'griditem-2',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 10,
|
|
||||||
height: 12,
|
|
||||||
body: anotherLibPanelWidget,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
dashboard.setState({ body });
|
|
||||||
|
|
||||||
anotherLibPanelWidget.onCancelAddPanel(mockEvent);
|
|
||||||
|
|
||||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(1);
|
|
||||||
expect(gridItem.state.body!.state.key).toBe(addLibPanelWidget.state.key);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should cancel lib panel inside a row child', () => {
|
|
||||||
const anotherLibPanelWidget = new AddLibraryPanelWidget({ key: 'panel-2' });
|
|
||||||
dashboard.setState({
|
|
||||||
body: new SceneGridLayout({
|
|
||||||
children: [
|
|
||||||
new SceneGridRow({
|
|
||||||
key: 'panel-2',
|
|
||||||
children: [
|
|
||||||
new DashboardGridItem({
|
|
||||||
key: 'griditem-2',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 10,
|
|
||||||
height: 12,
|
|
||||||
body: anotherLibPanelWidget,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
|
|
||||||
anotherLibPanelWidget.onCancelAddPanel(mockEvent);
|
|
||||||
|
|
||||||
const gridRow = body.state.children[0] as SceneGridRow;
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(1);
|
|
||||||
expect(gridRow.state.children.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add library panel from menu', () => {
|
|
||||||
const panelInfo: LibraryPanel = {
|
|
||||||
uid: 'uid',
|
|
||||||
model: {
|
|
||||||
type: 'timeseries',
|
|
||||||
},
|
|
||||||
name: 'name',
|
|
||||||
version: 1,
|
|
||||||
type: 'timeseries',
|
|
||||||
};
|
|
||||||
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
|
||||||
|
|
||||||
expect(gridItem.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
|
||||||
|
|
||||||
addLibPanelWidget.onAddLibraryPanel(panelInfo);
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(1);
|
|
||||||
expect(gridItem.state.body!).toBeInstanceOf(LibraryVizPanel);
|
|
||||||
expect((gridItem.state.body! as LibraryVizPanel).state.panelKey).toBe(addLibPanelWidget.state.key);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add a lib panel at correct position', () => {
|
|
||||||
const anotherLibPanelWidget = new AddLibraryPanelWidget({ key: 'panel-2' });
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
|
|
||||||
body.setState({
|
|
||||||
children: [
|
|
||||||
...body.state.children,
|
|
||||||
new DashboardGridItem({
|
|
||||||
key: 'griditem-2',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 10,
|
|
||||||
height: 12,
|
|
||||||
body: anotherLibPanelWidget,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
dashboard.setState({ body });
|
|
||||||
|
|
||||||
const panelInfo: LibraryPanel = {
|
|
||||||
uid: 'uid',
|
|
||||||
model: {
|
|
||||||
type: 'timeseries',
|
|
||||||
},
|
|
||||||
name: 'name',
|
|
||||||
version: 1,
|
|
||||||
type: 'timeseries',
|
|
||||||
};
|
|
||||||
|
|
||||||
anotherLibPanelWidget.onAddLibraryPanel(panelInfo);
|
|
||||||
|
|
||||||
const gridItemOne = body.state.children[0] as DashboardGridItem;
|
|
||||||
const gridItemTwo = body.state.children[1] as DashboardGridItem;
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(2);
|
|
||||||
expect(gridItemOne.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
|
||||||
expect((gridItemTwo.state.body! as LibraryVizPanel).state.panelKey).toBe(anotherLibPanelWidget.state.key);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add library panel from menu to a row child', () => {
|
|
||||||
const anotherLibPanelWidget = new AddLibraryPanelWidget({ key: 'panel-2' });
|
|
||||||
dashboard.setState({
|
|
||||||
body: new SceneGridLayout({
|
|
||||||
children: [
|
|
||||||
new SceneGridRow({
|
|
||||||
key: 'panel-2',
|
|
||||||
children: [
|
|
||||||
new DashboardGridItem({
|
|
||||||
key: 'griditem-2',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 10,
|
|
||||||
height: 12,
|
|
||||||
body: anotherLibPanelWidget,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const panelInfo: LibraryPanel = {
|
|
||||||
uid: 'uid',
|
|
||||||
model: {
|
|
||||||
type: 'timeseries',
|
|
||||||
},
|
|
||||||
name: 'name',
|
|
||||||
version: 1,
|
|
||||||
type: 'timeseries',
|
|
||||||
};
|
|
||||||
|
|
||||||
const body = dashboard.state.body as SceneGridLayout;
|
|
||||||
|
|
||||||
anotherLibPanelWidget.onAddLibraryPanel(panelInfo);
|
|
||||||
|
|
||||||
const gridRow = body.state.children[0] as SceneGridRow;
|
|
||||||
const gridItem = gridRow.state.children[0] as DashboardGridItem;
|
|
||||||
|
|
||||||
expect(body.state.children.length).toBe(1);
|
|
||||||
expect(gridItem.state.body!).toBeInstanceOf(LibraryVizPanel);
|
|
||||||
expect((gridItem.state.body! as LibraryVizPanel).state.panelKey).toBe(anotherLibPanelWidget.state.key);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error if adding lib panel in a layout that is not SceneGridLayout', () => {
|
|
||||||
dashboard.setState({
|
|
||||||
body: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(() => addLibPanelWidget.onAddLibraryPanel({} as LibraryPanel)).toThrow(
|
|
||||||
'Trying to add a library panel in a layout that is not SceneGridLayout'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error if removing the library panel widget in a layout that is not SceneGridLayout', () => {
|
|
||||||
dashboard.setState({
|
|
||||||
body: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(() => addLibPanelWidget.onCancelAddPanel(mockEvent)).toThrow(
|
|
||||||
'Trying to remove the library panel widget in a layout that is not SceneGridLayout'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function buildTestScene() {
|
|
||||||
const addLibPanelWidget = new AddLibraryPanelWidget({ key: 'panel-1' });
|
|
||||||
const dashboard = new DashboardScene({
|
|
||||||
$timeRange: new SceneTimeRange({}),
|
|
||||||
title: 'hello',
|
|
||||||
uid: 'dash-1',
|
|
||||||
version: 4,
|
|
||||||
meta: {
|
|
||||||
canEdit: true,
|
|
||||||
},
|
|
||||||
body: new SceneGridLayout({
|
|
||||||
children: [
|
|
||||||
new DashboardGridItem({
|
|
||||||
key: 'griditem-1',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 10,
|
|
||||||
height: 12,
|
|
||||||
body: addLibPanelWidget,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
activateFullSceneTree(dashboard);
|
|
||||||
|
|
||||||
await new Promise((r) => setTimeout(r, 1));
|
|
||||||
|
|
||||||
dashboard.onEnterEditMode();
|
|
||||||
|
|
||||||
return { dashboard, addLibPanelWidget };
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
import { css, cx, keyframes } from '@emotion/css';
|
|
||||||
import React from 'react';
|
|
||||||
import tinycolor from 'tinycolor2';
|
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
|
||||||
import { SceneComponentProps, SceneGridLayout, SceneGridRow, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
|
||||||
import { LibraryPanel } from '@grafana/schema';
|
|
||||||
import { IconButton, useStyles2 } from '@grafana/ui';
|
|
||||||
import { Trans } from 'app/core/internationalization';
|
|
||||||
import {
|
|
||||||
LibraryPanelsSearch,
|
|
||||||
LibraryPanelsSearchVariant,
|
|
||||||
} from 'app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch';
|
|
||||||
|
|
||||||
import { getDashboardSceneFor } from '../utils/utils';
|
|
||||||
|
|
||||||
import { DashboardGridItem } from './DashboardGridItem';
|
|
||||||
import { DashboardScene } from './DashboardScene';
|
|
||||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
|
||||||
|
|
||||||
export interface AddLibraryPanelWidgetState extends SceneObjectState {
|
|
||||||
key: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AddLibraryPanelWidget extends SceneObjectBase<AddLibraryPanelWidgetState> {
|
|
||||||
public constructor(state: AddLibraryPanelWidgetState) {
|
|
||||||
super({
|
|
||||||
...state,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _dashboard(): DashboardScene {
|
|
||||||
return getDashboardSceneFor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getDashboard(): DashboardScene {
|
|
||||||
return this._dashboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
public onCancelAddPanel = (evt: React.MouseEvent<HTMLButtonElement>) => {
|
|
||||||
evt.preventDefault();
|
|
||||||
|
|
||||||
if (!(this._dashboard.state.body instanceof SceneGridLayout)) {
|
|
||||||
throw new Error('Trying to remove the library panel widget in a layout that is not SceneGridLayout');
|
|
||||||
}
|
|
||||||
|
|
||||||
const sceneGridLayout = this._dashboard.state.body;
|
|
||||||
const children = [];
|
|
||||||
|
|
||||||
for (const child of sceneGridLayout.state.children) {
|
|
||||||
if (child.state.key !== this.parent?.state.key) {
|
|
||||||
children.push(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (child instanceof SceneGridRow) {
|
|
||||||
const rowChildren = [];
|
|
||||||
|
|
||||||
for (const rowChild of child.state.children) {
|
|
||||||
if (rowChild instanceof DashboardGridItem && rowChild.state.key !== this.parent?.state.key) {
|
|
||||||
rowChildren.push(rowChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
child.setState({ children: rowChildren });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sceneGridLayout.setState({ children });
|
|
||||||
};
|
|
||||||
|
|
||||||
public onAddLibraryPanel = (panelInfo: LibraryPanel) => {
|
|
||||||
if (!(this._dashboard.state.body instanceof SceneGridLayout)) {
|
|
||||||
throw new Error('Trying to add a library panel in a layout that is not SceneGridLayout');
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = new LibraryVizPanel({
|
|
||||||
title: 'Panel Title',
|
|
||||||
uid: panelInfo.uid,
|
|
||||||
name: panelInfo.name,
|
|
||||||
panelKey: this.state.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.parent instanceof DashboardGridItem) {
|
|
||||||
this.parent.setState({ body });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static Component = ({ model }: SceneComponentProps<AddLibraryPanelWidget>) => {
|
|
||||||
const dashboard = model.getDashboard();
|
|
||||||
const styles = useStyles2(getStyles);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.wrapper}>
|
|
||||||
<div className={cx('panel-container', styles.callToAction)}>
|
|
||||||
<div className={cx(styles.headerRow, `grid-drag-handle-${dashboard.state.body.state.key}`)}>
|
|
||||||
<span>
|
|
||||||
<Trans i18nKey="library-panel.add-widget.title">Add panel from panel library</Trans>
|
|
||||||
</span>
|
|
||||||
<div className="flex-grow-1" />
|
|
||||||
<IconButton
|
|
||||||
aria-label="Close 'Add Panel' widget"
|
|
||||||
name="times"
|
|
||||||
onClick={model.onCancelAddPanel}
|
|
||||||
tooltip="Close widget"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<LibraryPanelsSearch
|
|
||||||
onClick={model.onAddLibraryPanel}
|
|
||||||
variant={LibraryPanelsSearchVariant.Tight}
|
|
||||||
showPanelFilter
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
|
||||||
const pulsate = keyframes({
|
|
||||||
'0%': {
|
|
||||||
boxShadow: `0 0 0 2px ${theme.colors.background.canvas}, 0 0 0px 4px ${theme.colors.primary.main}`,
|
|
||||||
},
|
|
||||||
'50%': {
|
|
||||||
boxShadow: `0 0 0 2px ${theme.components.dashboard.background}, 0 0 0px 4px ${tinycolor(theme.colors.primary.main)
|
|
||||||
.darken(20)
|
|
||||||
.toHexString()}`,
|
|
||||||
},
|
|
||||||
'100%': {
|
|
||||||
boxShadow: `0 0 0 2px ${theme.components.dashboard.background}, 0 0 0px 4px ${theme.colors.primary.main}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
// wrapper is used to make sure box-shadow animation isn't cut off in dashboard page
|
|
||||||
wrapper: css({
|
|
||||||
height: '100%',
|
|
||||||
paddingTop: `${theme.spacing(0.5)}`,
|
|
||||||
}),
|
|
||||||
headerRow: css({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
height: '38px',
|
|
||||||
flexShrink: 0,
|
|
||||||
width: '100%',
|
|
||||||
fontSize: theme.typography.fontSize,
|
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
|
||||||
paddingLeft: `${theme.spacing(1)}`,
|
|
||||||
transition: 'background-color 0.1s ease-in-out',
|
|
||||||
cursor: 'move',
|
|
||||||
|
|
||||||
'&:hover': {
|
|
||||||
background: `${theme.colors.background.secondary}`,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
callToAction: css({
|
|
||||||
overflow: 'hidden',
|
|
||||||
outline: '2px dotted transparent',
|
|
||||||
outlineOffset: '2px',
|
|
||||||
boxShadow: '0 0 0 2px black, 0 0 0px 4px #1f60c4',
|
|
||||||
animation: `${pulsate} 2s ease infinite`,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -22,13 +22,13 @@ import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
|
|||||||
|
|
||||||
import { getMultiVariableValues } from '../utils/utils';
|
import { getMultiVariableValues } from '../utils/utils';
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
import { AddLibraryPanelDrawer } from './AddLibraryPanelDrawer';
|
||||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||||
import { repeatPanelMenuBehavior } from './PanelMenuBehavior';
|
import { repeatPanelMenuBehavior } from './PanelMenuBehavior';
|
||||||
import { DashboardRepeatsProcessedEvent } from './types';
|
import { DashboardRepeatsProcessedEvent } from './types';
|
||||||
|
|
||||||
interface DashboardGridItemState extends SceneGridItemStateLike {
|
interface DashboardGridItemState extends SceneGridItemStateLike {
|
||||||
body: VizPanel | LibraryVizPanel | AddLibraryPanelWidget;
|
body: VizPanel | LibraryVizPanel | AddLibraryPanelDrawer;
|
||||||
repeatedPanels?: VizPanel[];
|
repeatedPanels?: VizPanel[];
|
||||||
variableName?: string;
|
variableName?: string;
|
||||||
itemHeight?: number;
|
itemHeight?: number;
|
||||||
@@ -89,7 +89,7 @@ export class DashboardGridItem extends SceneObjectBase<DashboardGridItemState> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _performRepeat() {
|
private _performRepeat() {
|
||||||
if (this.state.body instanceof AddLibraryPanelWidget) {
|
if (this.state.body instanceof AddLibraryPanelDrawer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.state.variableName || this._variableDependency.hasDependencyInLoadingState()) {
|
if (!this.state.variableName || this._variableDependency.hasDependencyInLoadingState()) {
|
||||||
@@ -191,7 +191,7 @@ export class DashboardGridItem extends SceneObjectBase<DashboardGridItemState> i
|
|||||||
return <body.Component model={body} key={body.state.key} />;
|
return <body.Component model={body} key={body.state.key} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body instanceof AddLibraryPanelWidget) {
|
if (body instanceof AddLibraryPanelDrawer) {
|
||||||
return <body.Component model={body} key={body.state.key} />;
|
return <body.Component model={body} key={body.state.key} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -670,21 +670,6 @@ describe('DashboardScene', () => {
|
|||||||
expect(scene.state.hasCopiedPanel).toBe(false);
|
expect(scene.state.hasCopiedPanel).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should create a new add library panel widget', () => {
|
|
||||||
scene.exitEditMode({ skipConfirm: true });
|
|
||||||
expect(scene.state.isEditing).toBe(false);
|
|
||||||
|
|
||||||
scene.onCreateLibPanelWidget();
|
|
||||||
|
|
||||||
const body = scene.state.body as SceneGridLayout;
|
|
||||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
|
||||||
|
|
||||||
expect(scene.state.isEditing).toBe(true);
|
|
||||||
expect(body.state.children.length).toBe(6);
|
|
||||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
|
||||||
expect(gridItem.state.y).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should remove a panel', () => {
|
it('Should remove a panel', () => {
|
||||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
||||||
scene.removePanel(vizPanel as VizPanel);
|
scene.removePanel(vizPanel as VizPanel);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ import {
|
|||||||
isPanelClone,
|
isPanelClone,
|
||||||
} from '../utils/utils';
|
} from '../utils/utils';
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
import { AddLibraryPanelDrawer } from './AddLibraryPanelDrawer';
|
||||||
import { DashboardControls } from './DashboardControls';
|
import { DashboardControls } from './DashboardControls';
|
||||||
import { DashboardGridItem } from './DashboardGridItem';
|
import { DashboardGridItem } from './DashboardGridItem';
|
||||||
import { DashboardSceneRenderer } from './DashboardSceneRenderer';
|
import { DashboardSceneRenderer } from './DashboardSceneRenderer';
|
||||||
@@ -117,7 +117,6 @@ export interface DashboardSceneState extends SceneObjectState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||||
static listenToChangesInProps = PERSISTED_PROPS;
|
|
||||||
static Component = DashboardSceneRenderer;
|
static Component = DashboardSceneRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -761,30 +760,9 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
|||||||
locationService.partial({ editview: 'settings' });
|
locationService.partial({ editview: 'settings' });
|
||||||
};
|
};
|
||||||
|
|
||||||
public onCreateLibPanelWidget() {
|
public onShowAddLibraryPanelDrawer() {
|
||||||
if (!(this.state.body instanceof SceneGridLayout)) {
|
this.setState({
|
||||||
throw new Error('Trying to add a panel in a layout that is not SceneGridLayout');
|
overlay: new AddLibraryPanelDrawer({}),
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.state.isEditing) {
|
|
||||||
this.onEnterEditMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
const sceneGridLayout = this.state.body;
|
|
||||||
|
|
||||||
const panelId = dashboardSceneGraph.getNextPanelId(this);
|
|
||||||
|
|
||||||
const newGridItem = new DashboardGridItem({
|
|
||||||
height: NEW_PANEL_HEIGHT,
|
|
||||||
width: NEW_PANEL_WIDTH,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
body: new AddLibraryPanelWidget({ key: getVizPanelKeyForPanelId(panelId) }),
|
|
||||||
key: `grid-item-${panelId}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
sceneGridLayout.setState({
|
|
||||||
children: [newGridItem, ...sceneGridLayout.state.children],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ export function ToolbarActions({ dashboard }: Props) {
|
|||||||
testId={selectors.pages.AddDashboard.itemButton('Add new panel from panel library menu item')}
|
testId={selectors.pages.AddDashboard.itemButton('Add new panel from panel library menu item')}
|
||||||
label={t('dashboard.add-menu.import', 'Import from library')}
|
label={t('dashboard.add-menu.import', 'Import from library')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dashboard.onCreateLibPanelWidget();
|
dashboard.onShowAddLibraryPanelDrawer();
|
||||||
DashboardInteractions.toolbarAddButtonClicked({ item: 'add_library_panel' });
|
DashboardInteractions.toolbarAddButtonClicked({ item: 'add_library_panel' });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+21
-70
@@ -40,14 +40,13 @@ import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
|||||||
import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/types';
|
import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/types';
|
||||||
import { DashboardDataDTO } from 'app/types';
|
import { DashboardDataDTO } from 'app/types';
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
|
||||||
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
||||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||||
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
||||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||||
import { NEW_LINK } from '../settings/links/utils';
|
import { NEW_LINK } from '../settings/links/utils';
|
||||||
import { getQueryRunnerFor, getVizPanelKeyForPanelId } from '../utils/utils';
|
import { getQueryRunnerFor } from '../utils/utils';
|
||||||
|
|
||||||
import { buildNewDashboardSaveModel } from './buildNewDashboardSaveModel';
|
import { buildNewDashboardSaveModel } from './buildNewDashboardSaveModel';
|
||||||
import { GRAFANA_DATASOURCE_REF } from './const';
|
import { GRAFANA_DATASOURCE_REF } from './const';
|
||||||
@@ -60,7 +59,6 @@ import {
|
|||||||
transformSaveModelToScene,
|
transformSaveModelToScene,
|
||||||
convertOldSnapshotToScenesSnapshot,
|
convertOldSnapshotToScenesSnapshot,
|
||||||
buildGridItemForLibPanel,
|
buildGridItemForLibPanel,
|
||||||
buildGridItemForLibraryPanelWidget,
|
|
||||||
} from './transformSaveModelToScene';
|
} from './transformSaveModelToScene';
|
||||||
|
|
||||||
describe('transformSaveModelToScene', () => {
|
describe('transformSaveModelToScene', () => {
|
||||||
@@ -192,11 +190,6 @@ describe('transformSaveModelToScene', () => {
|
|||||||
gridPos: { x: 1, y: 0, w: 12, h: 8 },
|
gridPos: { x: 1, y: 0, w: 12, h: 8 },
|
||||||
}) as Panel;
|
}) as Panel;
|
||||||
|
|
||||||
const widgetLibPanel = {
|
|
||||||
title: 'Widget Panel',
|
|
||||||
type: 'add-library-panel',
|
|
||||||
};
|
|
||||||
|
|
||||||
const libPanel = createPanelSaveModel({
|
const libPanel = createPanelSaveModel({
|
||||||
title: 'Library Panel',
|
title: 'Library Panel',
|
||||||
gridPos: { x: 0, y: 0, w: 12, h: 8 },
|
gridPos: { x: 0, y: 0, w: 12, h: 8 },
|
||||||
@@ -211,7 +204,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
type: 'row',
|
type: 'row',
|
||||||
gridPos: { x: 0, y: 0, w: 12, h: 1 },
|
gridPos: { x: 0, y: 0, w: 12, h: 1 },
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
panels: [panel, widgetLibPanel, libPanel],
|
panels: [panel, libPanel],
|
||||||
}) as unknown as RowPanel;
|
}) as unknown as RowPanel;
|
||||||
|
|
||||||
const dashboard = {
|
const dashboard = {
|
||||||
@@ -230,14 +223,12 @@ describe('transformSaveModelToScene', () => {
|
|||||||
expect(rowScene.state.title).toEqual(row.title);
|
expect(rowScene.state.title).toEqual(row.title);
|
||||||
expect(rowScene.state.y).toEqual(row.gridPos!.y);
|
expect(rowScene.state.y).toEqual(row.gridPos!.y);
|
||||||
expect(rowScene.state.isCollapsed).toEqual(row.collapsed);
|
expect(rowScene.state.isCollapsed).toEqual(row.collapsed);
|
||||||
expect(rowScene.state.children).toHaveLength(3);
|
expect(rowScene.state.children).toHaveLength(2);
|
||||||
expect(rowScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
expect(rowScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||||
expect(rowScene.state.children[1]).toBeInstanceOf(DashboardGridItem);
|
expect(rowScene.state.children[1]).toBeInstanceOf(DashboardGridItem);
|
||||||
expect(rowScene.state.children[2]).toBeInstanceOf(DashboardGridItem);
|
|
||||||
// Panels are sorted by position in the row
|
// Panels are sorted by position in the row
|
||||||
expect((rowScene.state.children[0] as DashboardGridItem).state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
expect((rowScene.state.children[0] as DashboardGridItem).state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||||
expect((rowScene.state.children[1] as DashboardGridItem).state.body!).toBeInstanceOf(LibraryVizPanel);
|
expect((rowScene.state.children[1] as DashboardGridItem).state.body!).toBeInstanceOf(VizPanel);
|
||||||
expect((rowScene.state.children[2] as DashboardGridItem).state.body!).toBeInstanceOf(VizPanel);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create panels within expanded row', () => {
|
it('should create panels within expanded row', () => {
|
||||||
@@ -250,16 +241,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const widgetLibPanelOutOfRow = {
|
|
||||||
title: 'Widget Panel',
|
|
||||||
type: 'add-library-panel',
|
|
||||||
gridPos: {
|
|
||||||
h: 8,
|
|
||||||
w: 12,
|
|
||||||
x: 12,
|
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const libPanelOutOfRow = createPanelSaveModel({
|
const libPanelOutOfRow = createPanelSaveModel({
|
||||||
title: 'Library Panel',
|
title: 'Library Panel',
|
||||||
gridPos: { x: 0, y: 8, w: 12, h: 8 },
|
gridPos: { x: 0, y: 8, w: 12, h: 8 },
|
||||||
@@ -268,6 +250,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
name: 'My Panel',
|
name: 'My Panel',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const rowWithPanel = createPanelSaveModel({
|
const rowWithPanel = createPanelSaveModel({
|
||||||
title: 'Row with panel',
|
title: 'Row with panel',
|
||||||
type: 'row',
|
type: 'row',
|
||||||
@@ -282,6 +265,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
// This panels array is not used if the row is not collapsed
|
// This panels array is not used if the row is not collapsed
|
||||||
panels: [],
|
panels: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const panelInRow = createPanelSaveModel({
|
const panelInRow = createPanelSaveModel({
|
||||||
gridPos: {
|
gridPos: {
|
||||||
h: 8,
|
h: 8,
|
||||||
@@ -291,16 +275,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
},
|
},
|
||||||
title: 'In row 1',
|
title: 'In row 1',
|
||||||
});
|
});
|
||||||
const widgetLibPanelInRow = {
|
|
||||||
title: 'Widget Panel',
|
|
||||||
type: 'add-library-panel',
|
|
||||||
gridPos: {
|
|
||||||
h: 8,
|
|
||||||
w: 12,
|
|
||||||
x: 12,
|
|
||||||
y: 17,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const libPanelInRow = createPanelSaveModel({
|
const libPanelInRow = createPanelSaveModel({
|
||||||
title: 'Library Panel',
|
title: 'Library Panel',
|
||||||
gridPos: { x: 0, y: 25, w: 12, h: 8 },
|
gridPos: { x: 0, y: 25, w: 12, h: 8 },
|
||||||
@@ -309,6 +284,7 @@ describe('transformSaveModelToScene', () => {
|
|||||||
name: 'My Panel',
|
name: 'My Panel',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emptyRow = createPanelSaveModel({
|
const emptyRow = createPanelSaveModel({
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
gridPos: {
|
gridPos: {
|
||||||
@@ -322,18 +298,10 @@ describe('transformSaveModelToScene', () => {
|
|||||||
title: 'Empty row',
|
title: 'Empty row',
|
||||||
type: 'row',
|
type: 'row',
|
||||||
});
|
});
|
||||||
|
|
||||||
const dashboard = {
|
const dashboard = {
|
||||||
...defaultDashboard,
|
...defaultDashboard,
|
||||||
panels: [
|
panels: [panelOutOfRow, libPanelOutOfRow, rowWithPanel, panelInRow, libPanelInRow, emptyRow],
|
||||||
panelOutOfRow,
|
|
||||||
widgetLibPanelOutOfRow,
|
|
||||||
libPanelOutOfRow,
|
|
||||||
rowWithPanel,
|
|
||||||
panelInRow,
|
|
||||||
widgetLibPanelInRow,
|
|
||||||
libPanelInRow,
|
|
||||||
emptyRow,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const oldModel = new DashboardModel(dashboard);
|
const oldModel = new DashboardModel(dashboard);
|
||||||
@@ -341,37 +309,31 @@ describe('transformSaveModelToScene', () => {
|
|||||||
const scene = createDashboardSceneFromDashboardModel(oldModel);
|
const scene = createDashboardSceneFromDashboardModel(oldModel);
|
||||||
const body = scene.state.body as SceneGridLayout;
|
const body = scene.state.body as SceneGridLayout;
|
||||||
|
|
||||||
expect(body.state.children).toHaveLength(5);
|
expect(body.state.children).toHaveLength(4);
|
||||||
expect(body).toBeInstanceOf(SceneGridLayout);
|
expect(body).toBeInstanceOf(SceneGridLayout);
|
||||||
// Panel out of row
|
// Panel out of row
|
||||||
expect(body.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
expect(body.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||||
const panelOutOfRowVizPanel = body.state.children[0] as DashboardGridItem;
|
const panelOutOfRowVizPanel = body.state.children[0] as DashboardGridItem;
|
||||||
expect((panelOutOfRowVizPanel.state.body as VizPanel)?.state.title).toBe(panelOutOfRow.title);
|
expect((panelOutOfRowVizPanel.state.body as VizPanel)?.state.title).toBe(panelOutOfRow.title);
|
||||||
// widget lib panel out of row
|
|
||||||
expect(body.state.children[1]).toBeInstanceOf(DashboardGridItem);
|
|
||||||
const panelOutOfRowWidget = body.state.children[1] as DashboardGridItem;
|
|
||||||
expect(panelOutOfRowWidget.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
|
||||||
// lib panel out of row
|
// lib panel out of row
|
||||||
expect(body.state.children[2]).toBeInstanceOf(DashboardGridItem);
|
expect(body.state.children[1]).toBeInstanceOf(DashboardGridItem);
|
||||||
const panelOutOfRowLibVizPanel = body.state.children[2] as DashboardGridItem;
|
const panelOutOfRowLibVizPanel = body.state.children[1] as DashboardGridItem;
|
||||||
expect(panelOutOfRowLibVizPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
expect(panelOutOfRowLibVizPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||||
// Row with panels
|
// Row with panels
|
||||||
expect(body.state.children[3]).toBeInstanceOf(SceneGridRow);
|
expect(body.state.children[2]).toBeInstanceOf(SceneGridRow);
|
||||||
const rowWithPanelsScene = body.state.children[3] as SceneGridRow;
|
const rowWithPanelsScene = body.state.children[2] as SceneGridRow;
|
||||||
expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title);
|
expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title);
|
||||||
expect(rowWithPanelsScene.state.key).toBe('panel-10');
|
expect(rowWithPanelsScene.state.key).toBe('panel-10');
|
||||||
expect(rowWithPanelsScene.state.children).toHaveLength(3);
|
expect(rowWithPanelsScene.state.children).toHaveLength(2);
|
||||||
const widget = rowWithPanelsScene.state.children[1] as DashboardGridItem;
|
const libPanel = rowWithPanelsScene.state.children[1] as DashboardGridItem;
|
||||||
expect(widget.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
|
||||||
const libPanel = rowWithPanelsScene.state.children[2] as DashboardGridItem;
|
|
||||||
expect(libPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
expect(libPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||||
// Panel within row
|
// Panel within row
|
||||||
expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||||
const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as DashboardGridItem;
|
const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as DashboardGridItem;
|
||||||
expect((panelInRowVizPanel.state.body as VizPanel).state.title).toBe(panelInRow.title);
|
expect((panelInRowVizPanel.state.body as VizPanel).state.title).toBe(panelInRow.title);
|
||||||
// Empty row
|
// Empty row
|
||||||
expect(body.state.children[4]).toBeInstanceOf(SceneGridRow);
|
expect(body.state.children[3]).toBeInstanceOf(SceneGridRow);
|
||||||
const emptyRowScene = body.state.children[4] as SceneGridRow;
|
const emptyRowScene = body.state.children[3] as SceneGridRow;
|
||||||
expect(emptyRowScene.state.title).toBe(emptyRow.title);
|
expect(emptyRowScene.state.title).toBe(emptyRow.title);
|
||||||
expect(emptyRowScene.state.children).toHaveLength(0);
|
expect(emptyRowScene.state.children).toHaveLength(0);
|
||||||
});
|
});
|
||||||
@@ -540,17 +502,6 @@ describe('transformSaveModelToScene', () => {
|
|||||||
expect(runner.state.cacheTimeout).toBe('10');
|
expect(runner.state.cacheTimeout).toBe('10');
|
||||||
expect(runner.state.queryCachingTTL).toBe(200000);
|
expect(runner.state.queryCachingTTL).toBe(200000);
|
||||||
});
|
});
|
||||||
it('should convert saved lib widget to AddLibraryPanelWidget', () => {
|
|
||||||
const panel = {
|
|
||||||
id: 10,
|
|
||||||
type: 'add-library-panel',
|
|
||||||
};
|
|
||||||
|
|
||||||
const gridItem = buildGridItemForLibraryPanelWidget(new PanelModel(panel))!;
|
|
||||||
const libPanelWidget = gridItem.state.body as AddLibraryPanelWidget;
|
|
||||||
|
|
||||||
expect(libPanelWidget.state.key).toEqual(getVizPanelKeyForPanelId(panel.id));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should convert saved lib panel to LibraryVizPanel', () => {
|
it('should convert saved lib panel to LibraryVizPanel', () => {
|
||||||
const panel = {
|
const panel = {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
|||||||
import { trackDashboardLoaded } from 'app/features/dashboard/utils/tracking';
|
import { trackDashboardLoaded } from 'app/features/dashboard/utils/tracking';
|
||||||
import { DashboardDTO } from 'app/types';
|
import { DashboardDTO } from 'app/types';
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
|
||||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||||
import { DashboardControls } from '../scene/DashboardControls';
|
import { DashboardControls } from '../scene/DashboardControls';
|
||||||
@@ -112,18 +111,6 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneGridI
|
|||||||
currentRowPanels = [];
|
currentRowPanels = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (panel.type === 'add-library-panel') {
|
|
||||||
const gridItem = buildGridItemForLibraryPanelWidget(panel);
|
|
||||||
|
|
||||||
if (!gridItem) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentRow) {
|
|
||||||
currentRowPanels.push(gridItem);
|
|
||||||
} else {
|
|
||||||
panels.push(gridItem);
|
|
||||||
}
|
|
||||||
} else if (panel.libraryPanel?.uid && !('model' in panel.libraryPanel)) {
|
} else if (panel.libraryPanel?.uid && !('model' in panel.libraryPanel)) {
|
||||||
const gridItem = buildGridItemForLibPanel(panel);
|
const gridItem = buildGridItemForLibPanel(panel);
|
||||||
|
|
||||||
@@ -170,15 +157,7 @@ function createRowFromPanelModel(row: PanelModel, content: SceneGridItemLike[]):
|
|||||||
saveModel = new PanelModel(saveModel);
|
saveModel = new PanelModel(saveModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (saveModel.type === 'add-library-panel') {
|
if (saveModel.libraryPanel?.uid && !('model' in saveModel.libraryPanel)) {
|
||||||
const gridItem = buildGridItemForLibraryPanelWidget(saveModel);
|
|
||||||
|
|
||||||
if (!gridItem) {
|
|
||||||
throw new Error('Failed to build grid item for library panel widget');
|
|
||||||
}
|
|
||||||
|
|
||||||
return gridItem;
|
|
||||||
} else if (saveModel.libraryPanel?.uid && !('model' in saveModel.libraryPanel)) {
|
|
||||||
const gridItem = buildGridItemForLibPanel(saveModel);
|
const gridItem = buildGridItemForLibPanel(saveModel);
|
||||||
|
|
||||||
if (!gridItem) {
|
if (!gridItem) {
|
||||||
@@ -435,24 +414,6 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildGridItemForLibraryPanelWidget(panel: PanelModel) {
|
|
||||||
if (panel.type !== 'add-library-panel') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = new AddLibraryPanelWidget({
|
|
||||||
key: getVizPanelKeyForPanelId(panel.id),
|
|
||||||
});
|
|
||||||
|
|
||||||
return new DashboardGridItem({
|
|
||||||
body,
|
|
||||||
y: panel.gridPos.y,
|
|
||||||
x: panel.gridPos.x,
|
|
||||||
width: panel.gridPos.w,
|
|
||||||
height: panel.gridPos.h,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildGridItemForLibPanel(panel: PanelModel) {
|
export function buildGridItemForLibPanel(panel: PanelModel) {
|
||||||
if (!panel.libraryPanel) {
|
if (!panel.libraryPanel) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import snapshotableDashboardJson from './testfiles/snapshotable_dashboard.json';
|
|||||||
import snapshotableWithRowsDashboardJson from './testfiles/snapshotable_with_rows.json';
|
import snapshotableWithRowsDashboardJson from './testfiles/snapshotable_with_rows.json';
|
||||||
import {
|
import {
|
||||||
buildGridItemForLibPanel,
|
buildGridItemForLibPanel,
|
||||||
buildGridItemForLibraryPanelWidget,
|
|
||||||
buildGridItemForPanel,
|
buildGridItemForPanel,
|
||||||
transformSaveModelToScene,
|
transformSaveModelToScene,
|
||||||
} from './transformSaveModelToScene';
|
} from './transformSaveModelToScene';
|
||||||
@@ -1027,8 +1026,6 @@ describe('transformSceneToSaveModel', () => {
|
|||||||
export function buildGridItemFromPanelSchema(panel: Partial<Panel>) {
|
export function buildGridItemFromPanelSchema(panel: Partial<Panel>) {
|
||||||
if (panel.libraryPanel) {
|
if (panel.libraryPanel) {
|
||||||
return buildGridItemForLibPanel(new PanelModel(panel))!;
|
return buildGridItemForLibPanel(new PanelModel(panel))!;
|
||||||
} else if (panel.type === 'add-library-panel') {
|
|
||||||
return buildGridItemForLibraryPanelWidget(new PanelModel(panel))!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildGridItemForPanel(new PanelModel(panel));
|
return buildGridItemForPanel(new PanelModel(panel));
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import { getPanelDataFrames } from 'app/features/dashboard/components/HelpWizard
|
|||||||
import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/DashboardMigrator';
|
import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/DashboardMigrator';
|
||||||
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
||||||
|
|
||||||
import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
|
||||||
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet';
|
||||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||||
import { DashboardScene } from '../scene/DashboardScene';
|
import { DashboardScene } from '../scene/DashboardScene';
|
||||||
@@ -187,20 +186,6 @@ export function gridItemToPanel(gridItem: DashboardGridItem, isSnapshot = false)
|
|||||||
return libraryVizPanelToPanel(gridItem.state.body, { x, y, w, h });
|
return libraryVizPanelToPanel(gridItem.state.body, { x, y, w, h });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle library panel widget as well and exit early
|
|
||||||
if (gridItem.state.body instanceof AddLibraryPanelWidget) {
|
|
||||||
x = gridItem.state.x ?? 0;
|
|
||||||
y = gridItem.state.y ?? 0;
|
|
||||||
w = gridItem.state.width ?? 0;
|
|
||||||
h = gridItem.state.height ?? 0;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: getPanelIdForVizPanel(gridItem.state.body),
|
|
||||||
type: 'add-library-panel',
|
|
||||||
gridPos: { x, y, w, h },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(gridItem.state.body instanceof VizPanel)) {
|
if (!(gridItem.state.body instanceof VizPanel)) {
|
||||||
throw new Error('DashboardGridItem body expected to be VizPanel');
|
throw new Error('DashboardGridItem body expected to be VizPanel');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
const onAddLibraryPanel = () => {
|
const onAddLibraryPanel = () => {
|
||||||
DashboardInteractions.emptyDashboardButtonClicked({ item: 'import_from_library' });
|
DashboardInteractions.emptyDashboardButtonClicked({ item: 'import_from_library' });
|
||||||
if (dashboard instanceof DashboardScene) {
|
if (dashboard instanceof DashboardScene) {
|
||||||
dashboard.onCreateLibPanelWidget();
|
dashboard.onShowAddLibraryPanelDrawer();
|
||||||
} else {
|
} else {
|
||||||
onAddLibraryPanelImpl(dashboard);
|
onAddLibraryPanelImpl(dashboard);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user