mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
PanelGridItemRepeater: Refactor (#84710)
* wip * serialisation tests updates * VizPanelManager test updates * ests updates * Making it green * Use DashboardGridItem instead of SceneGridItem * Cleanup tests that unnecessarily depend on dashboard grid items * Fix row repeater behavior test * Update public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com> * Fix unnecessary library panel changes detection * Fix test --------- Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
This commit is contained in:
parent
20bb9d60dc
commit
a4ff2abd9d
@ -3,15 +3,9 @@ import React from 'react';
|
||||
|
||||
import { FieldType, getDefaultTimeRange, LoadingState, toDataFrame } from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import {
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneQueryRunner,
|
||||
SceneTimeRange,
|
||||
VizPanel,
|
||||
VizPanelMenu,
|
||||
} from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneQueryRunner, SceneTimeRange, VizPanel, VizPanelMenu } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../../scene/DashboardScene';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
|
||||
import { panelMenuBehavior } from '../../scene/PanelMenuBehavior';
|
||||
@ -76,7 +70,7 @@ async function buildTestScene() {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -1,13 +1,7 @@
|
||||
import { FieldType, getDefaultTimeRange, LoadingState, toDataFrame } from '@grafana/data';
|
||||
import {
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneQueryRunner,
|
||||
SceneTimeRange,
|
||||
VizPanel,
|
||||
VizPanelMenu,
|
||||
} from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneQueryRunner, SceneTimeRange, VizPanel, VizPanelMenu } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../../scene/DashboardScene';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
|
||||
import { panelMenuBehavior } from '../../scene/PanelMenuBehavior';
|
||||
@ -122,7 +116,7 @@ async function buildTestScene() {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -11,9 +11,10 @@ import {
|
||||
DataTopic,
|
||||
} from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneGridItem, VizPanel } from '@grafana/scenes';
|
||||
import { VizPanel } from '@grafana/scenes';
|
||||
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
||||
|
||||
import { DashboardGridItem } from '../../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../../scene/LibraryVizPanel';
|
||||
import { gridItemToPanel, vizPanelToPanel } from '../../serialization/transformSceneToSaveModel';
|
||||
import { getQueryRunnerFor } from '../../utils/utils';
|
||||
@ -62,14 +63,16 @@ export function getGithubMarkdown(panel: VizPanel, snapshot: string): string {
|
||||
|
||||
export async function getDebugDashboard(panel: VizPanel, rand: Randomize, timeRange: TimeRange) {
|
||||
let saveModel;
|
||||
const isLibraryPanel = panel.parent instanceof LibraryVizPanel;
|
||||
const gridItem = (isLibraryPanel ? panel.parent.parent : panel.parent) as DashboardGridItem;
|
||||
|
||||
if (panel.parent instanceof LibraryVizPanel && panel.parent.parent instanceof SceneGridItem) {
|
||||
if (isLibraryPanel) {
|
||||
saveModel = {
|
||||
...gridItemToPanel(panel.parent.parent),
|
||||
...gridItemToPanel(gridItem),
|
||||
...vizPanelToPanel(panel),
|
||||
};
|
||||
} else {
|
||||
saveModel = gridItemToPanel(panel.parent as SceneGridItem);
|
||||
saveModel = gridItemToPanel(gridItem);
|
||||
}
|
||||
|
||||
const dashboard = cloneDeep(embeddedDataTemplate);
|
||||
|
@ -10,17 +10,11 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils, setRunRequest } from '@grafana/runtime';
|
||||
import {
|
||||
SceneCanvasText,
|
||||
SceneDataTransformer,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneQueryRunner,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { SceneCanvasText, SceneDataTransformer, SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import * as libpanels from 'app/features/library-panels/state/api';
|
||||
import { getStandardTransformers } from 'app/features/transformers/standardTransformers';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
||||
@ -146,7 +140,7 @@ describe('InspectJsonTab', () => {
|
||||
|
||||
const panel2 = findVizPanelByKey(scene, panel.state.key)!;
|
||||
expect(panel2.state.title).toBe('New title');
|
||||
expect((panel2.parent as SceneGridItem).state.width!).toBe(3);
|
||||
expect((panel2.parent as DashboardGridItem).state.width!).toBe(3);
|
||||
|
||||
expect(tab.state.onClose).toHaveBeenCalled();
|
||||
});
|
||||
@ -185,7 +179,7 @@ async function buildTestScene() {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -232,7 +226,7 @@ async function buildTestSceneWithLibraryPanel() {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
SceneComponentProps,
|
||||
SceneDataTransformer,
|
||||
sceneGraph,
|
||||
SceneGridItem,
|
||||
SceneGridItemStateLike,
|
||||
SceneObjectBase,
|
||||
SceneObjectRef,
|
||||
@ -28,8 +27,8 @@ import { getPrettyJSON } from 'app/features/inspector/utils/utils';
|
||||
import { reportPanelInspectInteraction } from 'app/features/search/page/reporting';
|
||||
|
||||
import { VizPanelManager } from '../panel-edit/VizPanelManager';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { buildGridItemForPanel } from '../serialization/transformSaveModelToScene';
|
||||
import { gridItemToPanel, vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
||||
@ -110,7 +109,7 @@ export class InspectJsonTab extends SceneObjectBase<InspectJsonTabState> {
|
||||
const gridItem = buildGridItemForPanel(panelModel);
|
||||
const newState = sceneUtils.cloneSceneObjectState(gridItem.state);
|
||||
|
||||
if (!(panel.parent instanceof SceneGridItem) || !(gridItem instanceof SceneGridItem)) {
|
||||
if (!(panel.parent instanceof DashboardGridItem)) {
|
||||
console.error('Cannot update state of panel', panel, gridItem);
|
||||
return;
|
||||
}
|
||||
@ -143,8 +142,13 @@ export class InspectJsonTab extends SceneObjectBase<InspectJsonTabState> {
|
||||
|
||||
const panel = this.state.panelRef.resolve();
|
||||
|
||||
// Library panels are not editable from the inspect
|
||||
if (panel.parent instanceof LibraryVizPanel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only support normal grid items for now and not repeated items
|
||||
if (!(panel.parent instanceof SceneGridItem)) {
|
||||
if (panel.parent instanceof DashboardGridItem && panel.parent.isRepeated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -203,15 +207,23 @@ function getJsonText(show: ShowContent, panel: VizPanel): string {
|
||||
case 'panel-json': {
|
||||
reportPanelInspectInteraction(InspectTab.JSON, 'panelData');
|
||||
|
||||
const parent = panel.parent!;
|
||||
const isInspectingLibraryPanel = panel.parent instanceof LibraryVizPanel;
|
||||
const gridItem = isInspectingLibraryPanel ? panel.parent.parent : panel.parent;
|
||||
|
||||
if (parent instanceof SceneGridItem || parent instanceof PanelRepeaterGridItem) {
|
||||
objToStringify = gridItemToPanel(parent);
|
||||
} else if (parent instanceof LibraryVizPanel) {
|
||||
if (isInspectingLibraryPanel) {
|
||||
objToStringify = libraryPanelChildToLegacyRepresentation(panel);
|
||||
} else if (parent instanceof VizPanelManager) {
|
||||
objToStringify = parent.getPanelSaveModel();
|
||||
break;
|
||||
}
|
||||
|
||||
if (panel.parent instanceof VizPanelManager) {
|
||||
objToStringify = panel.parent.getPanelSaveModel();
|
||||
break;
|
||||
}
|
||||
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
objToStringify = gridItemToPanel(gridItem);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -245,7 +257,7 @@ function getJsonText(show: ShowContent, panel: VizPanel): string {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param panel Must be child of a LibraryVizPanel that is in turn the child of a SceneGridItem
|
||||
* @param panel Must be child of a LibraryVizPanel that is in turn the child of a DashboardGridItem
|
||||
* @returns object representation of the legacy library panel structure.
|
||||
*/
|
||||
function libraryPanelChildToLegacyRepresentation(panel: VizPanel<{}, {}>) {
|
||||
@ -253,8 +265,8 @@ function libraryPanelChildToLegacyRepresentation(panel: VizPanel<{}, {}>) {
|
||||
throw 'Panel not child of LibraryVizPanel';
|
||||
}
|
||||
|
||||
if (!(panel.parent.parent instanceof SceneGridItem)) {
|
||||
throw 'LibraryPanel not child of SceneGridItem';
|
||||
if (!(panel.parent.parent instanceof DashboardGridItem)) {
|
||||
throw 'LibraryPanel not child of DashboardGridItem';
|
||||
}
|
||||
|
||||
const gridItem = panel.parent.parent;
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { PanelPlugin, PanelPluginMeta, PluginType } from '@grafana/data';
|
||||
import { SceneGridItem, SceneGridLayout, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, VizPanel } from '@grafana/scenes';
|
||||
import * as libAPI from 'app/features/library-panels/state/api';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
@ -38,8 +39,9 @@ describe('PanelEditor', () => {
|
||||
pluginId: 'text',
|
||||
});
|
||||
|
||||
const gridItem = new DashboardGridItem({ body: panel });
|
||||
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const gridItem = new SceneGridItem({ body: panel });
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
isEditing: true,
|
||||
@ -85,13 +87,13 @@ describe('PanelEditor', () => {
|
||||
panel: panel,
|
||||
_loadedPanel: libraryPanelModel,
|
||||
});
|
||||
const gridItem = new DashboardGridItem({ body: libraryPanel });
|
||||
|
||||
const apiCall = jest
|
||||
.spyOn(libAPI, 'updateLibraryVizPanel')
|
||||
.mockResolvedValue({ type: 'panel', ...libAPI.libraryVizPanelToSaveModel(libraryPanel), version: 2 });
|
||||
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const gridItem = new SceneGridItem({ body: libraryPanel });
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
isEditing: true,
|
||||
@ -125,6 +127,10 @@ describe('PanelEditor', () => {
|
||||
key: 'panel-1',
|
||||
pluginId: 'text',
|
||||
});
|
||||
new DashboardGridItem({
|
||||
body: panel,
|
||||
});
|
||||
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
@ -142,6 +148,10 @@ describe('PanelEditor', () => {
|
||||
key: 'panel-1',
|
||||
pluginId: 'timeseries',
|
||||
});
|
||||
|
||||
new DashboardGridItem({
|
||||
body: panel,
|
||||
});
|
||||
const editScene = buildPanelEditScene(panel);
|
||||
const scene = new DashboardScene({
|
||||
editPanel: editScene,
|
||||
|
@ -2,10 +2,10 @@ import * as H from 'history';
|
||||
|
||||
import { NavIndex } from '@grafana/data';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
import { SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { getDashboardSceneFor, getPanelIdForVizPanel } from '../utils/utils';
|
||||
|
||||
import { PanelDataPane } from './PanelDataPane/PanelDataPane';
|
||||
@ -104,82 +104,23 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
const panelManager = this.state.vizManager;
|
||||
const sourcePanel = panelManager.state.sourcePanel.resolve();
|
||||
const sourcePanelParent = sourcePanel!.parent;
|
||||
const isLibraryPanel = sourcePanelParent instanceof LibraryVizPanel;
|
||||
|
||||
const normalToRepeat = !this._initialRepeatOptions.repeat && panelManager.state.repeat;
|
||||
const repeatToNormal = this._initialRepeatOptions.repeat && !panelManager.state.repeat;
|
||||
const gridItem = isLibraryPanel ? sourcePanelParent.parent : sourcePanelParent;
|
||||
|
||||
if (sourcePanelParent instanceof LibraryVizPanel) {
|
||||
if (isLibraryPanel) {
|
||||
// Library panels handled separately
|
||||
return;
|
||||
} else if (sourcePanelParent instanceof SceneGridItem) {
|
||||
if (normalToRepeat) {
|
||||
this.replaceSceneGridItemWithPanelRepeater(sourcePanelParent);
|
||||
} else {
|
||||
panelManager.commitChanges();
|
||||
}
|
||||
} else if (sourcePanelParent instanceof PanelRepeaterGridItem) {
|
||||
if (repeatToNormal) {
|
||||
this.replacePanelRepeaterWithGridItem(sourcePanelParent);
|
||||
} else {
|
||||
this.handleRepeatOptionChanges(sourcePanelParent);
|
||||
}
|
||||
}
|
||||
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
this.handleRepeatOptionChanges(gridItem);
|
||||
} else {
|
||||
console.error('Unsupported scene object type');
|
||||
}
|
||||
}
|
||||
|
||||
private replaceSceneGridItemWithPanelRepeater(gridItem: SceneGridItem) {
|
||||
const gridLayout = gridItem.parent;
|
||||
if (!(gridLayout instanceof SceneGridLayout)) {
|
||||
console.error('Expected grandparent to be SceneGridLayout!');
|
||||
return;
|
||||
}
|
||||
|
||||
const panelManager = this.state.vizManager;
|
||||
const repeatDirection = panelManager.state.repeatDirection ?? 'h';
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
key: gridItem.state.key,
|
||||
x: gridItem.state.x,
|
||||
y: gridItem.state.y,
|
||||
width: repeatDirection === 'h' ? 24 : gridItem.state.width,
|
||||
height: gridItem.state.height,
|
||||
itemHeight: gridItem.state.height,
|
||||
source: panelManager.getPanelCloneWithData(),
|
||||
variableName: panelManager.state.repeat!,
|
||||
repeatedPanels: [],
|
||||
repeatDirection: panelManager.state.repeatDirection,
|
||||
maxPerRow: panelManager.state.maxPerRow,
|
||||
});
|
||||
gridLayout.setState({
|
||||
children: gridLayout.state.children.map((child) => (child.state.key === gridItem.state.key ? repeater : child)),
|
||||
});
|
||||
}
|
||||
|
||||
private replacePanelRepeaterWithGridItem(panelRepeater: PanelRepeaterGridItem) {
|
||||
const gridLayout = panelRepeater.parent;
|
||||
if (!(gridLayout instanceof SceneGridLayout)) {
|
||||
console.error('Expected grandparent to be SceneGridLayout!');
|
||||
return;
|
||||
}
|
||||
|
||||
const panelManager = this.state.vizManager;
|
||||
const panelClone = panelManager.getPanelCloneWithData();
|
||||
const gridItem = new SceneGridItem({
|
||||
key: panelRepeater.state.key,
|
||||
x: panelRepeater.state.x,
|
||||
y: panelRepeater.state.y,
|
||||
width: this._initialRepeatOptions.repeatDirection === 'h' ? 8 : panelRepeater.state.width,
|
||||
height: this._initialRepeatOptions.repeatDirection === 'v' ? 8 : panelRepeater.state.height,
|
||||
body: panelClone,
|
||||
});
|
||||
gridLayout.setState({
|
||||
children: gridLayout.state.children.map((child) =>
|
||||
child.state.key === panelRepeater.state.key ? gridItem : child
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
private handleRepeatOptionChanges(panelRepeater: PanelRepeaterGridItem) {
|
||||
private handleRepeatOptionChanges(panelRepeater: DashboardGridItem) {
|
||||
let width = panelRepeater.state.width ?? 1;
|
||||
let height = panelRepeater.state.height;
|
||||
|
||||
@ -195,7 +136,7 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
}
|
||||
|
||||
panelRepeater.setState({
|
||||
source: panelManager.getPanelCloneWithData(),
|
||||
body: panelManager.getPanelCloneWithData(),
|
||||
repeatDirection: panelManager.state.repeatDirection,
|
||||
variableName: panelManager.state.repeat,
|
||||
maxPerRow: panelManager.state.maxPerRow,
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { act, fireEvent, render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { SceneGridItem, VizPanel } from '@grafana/scenes';
|
||||
import { VizPanel } from '@grafana/scenes';
|
||||
import { OptionFilter } from 'app/features/dashboard/components/PanelEditor/OptionsPaneOptions';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { vizPanelToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
|
||||
@ -42,7 +43,7 @@ describe('PanelOptions', () => {
|
||||
_loadedPanel: libraryPanelModel,
|
||||
});
|
||||
|
||||
new SceneGridItem({ body: libraryPanel });
|
||||
new DashboardGridItem({ body: libraryPanel });
|
||||
|
||||
const panelManger = VizPanelManager.createFor(panel);
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { map, of } from 'rxjs';
|
||||
|
||||
import { DataQueryRequest, DataSourceApi, DataSourceInstanceSettings, LoadingState, PanelData } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import { SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import { DataQuery, DataSourceJsonData, DataSourceRef } from '@grafana/schema';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { InspectTab } from 'app/features/inspector/types';
|
||||
@ -10,6 +10,7 @@ import * as libAPI from 'app/features/library-panels/state/api';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard/types';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
|
||||
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
|
||||
@ -172,6 +173,10 @@ describe('VizPanelManager', () => {
|
||||
},
|
||||
});
|
||||
|
||||
new DashboardGridItem({
|
||||
body: vizPanel,
|
||||
});
|
||||
|
||||
const vizPanelManager = VizPanelManager.createFor(vizPanel);
|
||||
|
||||
expect(vizPanelManager.state.panel.state.fieldConfig.defaults.custom).toBe('Custom');
|
||||
@ -196,6 +201,10 @@ describe('VizPanelManager', () => {
|
||||
fieldConfig: { defaults: { custom: 'Custom' }, overrides: [] },
|
||||
});
|
||||
|
||||
new DashboardGridItem({
|
||||
body: vizPanel,
|
||||
});
|
||||
|
||||
const vizPanelManager = VizPanelManager.createFor(vizPanel);
|
||||
|
||||
vizPanelManager.changePluginType('timeseries');
|
||||
@ -237,7 +246,7 @@ describe('VizPanelManager', () => {
|
||||
_loadedPanel: libraryPanelModel,
|
||||
});
|
||||
|
||||
new SceneGridItem({ body: libraryPanel });
|
||||
new DashboardGridItem({ body: libraryPanel });
|
||||
|
||||
const panelManager = VizPanelManager.createFor(panel);
|
||||
|
||||
@ -276,7 +285,7 @@ describe('VizPanelManager', () => {
|
||||
_loadedPanel: libraryPanelModel,
|
||||
});
|
||||
|
||||
const gridItem = new SceneGridItem({ body: libraryPanel });
|
||||
const gridItem = new DashboardGridItem({ body: libraryPanel });
|
||||
|
||||
const panelManager = VizPanelManager.createFor(panel);
|
||||
panelManager.unlinkLibraryPanel();
|
||||
|
@ -17,7 +17,6 @@ import {
|
||||
PanelBuilders,
|
||||
SceneComponentProps,
|
||||
SceneDataTransformer,
|
||||
SceneGridItem,
|
||||
SceneObjectBase,
|
||||
SceneObjectRef,
|
||||
SceneObjectState,
|
||||
@ -36,8 +35,8 @@ import { updateQueries } from 'app/features/query/state/updateQueries';
|
||||
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
||||
import { QueryGroupOptions } from 'app/types';
|
||||
|
||||
import { DashboardGridItem, RepeatDirection } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem, RepeatDirection } from '../scene/PanelRepeaterGridItem';
|
||||
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
|
||||
import { gridItemToPanel } from '../serialization/transformSceneToSaveModel';
|
||||
import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
||||
@ -77,11 +76,17 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
*/
|
||||
public static createFor(sourcePanel: VizPanel) {
|
||||
let repeatOptions: Pick<VizPanelManagerState, 'repeat' | 'repeatDirection' | 'maxPerRow'> = {};
|
||||
if (sourcePanel.parent instanceof PanelRepeaterGridItem) {
|
||||
const { variableName: repeat, repeatDirection, maxPerRow } = sourcePanel.parent.state;
|
||||
repeatOptions = { repeat, repeatDirection, maxPerRow };
|
||||
|
||||
const gridItem = sourcePanel.parent instanceof LibraryVizPanel ? sourcePanel.parent.parent : sourcePanel.parent;
|
||||
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
console.error('VizPanel is not a child of a dashboard grid item');
|
||||
throw new Error('VizPanel is not a child of a dashboard grid item');
|
||||
}
|
||||
|
||||
const { variableName: repeat, repeatDirection, maxPerRow } = gridItem.state;
|
||||
repeatOptions = { repeat, repeatDirection, maxPerRow };
|
||||
|
||||
return new VizPanelManager({
|
||||
panel: sourcePanel.clone({ $data: undefined }),
|
||||
$data: sourcePanel.state.$data?.clone(),
|
||||
@ -345,7 +350,8 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
}
|
||||
|
||||
const gridItem = sourcePanel.parent.parent;
|
||||
if (!(gridItem instanceof SceneGridItem)) {
|
||||
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
throw new Error('Library panel not a child of a grid item');
|
||||
}
|
||||
|
||||
@ -353,14 +359,21 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
gridItem.setState({
|
||||
body: newSourcePanel,
|
||||
});
|
||||
|
||||
this.setState({ sourcePanel: newSourcePanel.getRef() });
|
||||
}
|
||||
|
||||
public commitChanges() {
|
||||
const sourcePanel = this.state.sourcePanel.resolve();
|
||||
|
||||
if (sourcePanel.parent instanceof SceneGridItem) {
|
||||
const repeatUpdate = {
|
||||
variableName: this.state.repeat,
|
||||
repeatDirection: this.state.repeatDirection,
|
||||
maxPerRow: this.state.maxPerRow,
|
||||
};
|
||||
if (sourcePanel.parent instanceof DashboardGridItem) {
|
||||
sourcePanel.parent.setState({
|
||||
...repeatUpdate,
|
||||
body: this.state.panel.clone({
|
||||
$data: this.state.$data?.clone(),
|
||||
}),
|
||||
@ -368,7 +381,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
}
|
||||
|
||||
if (sourcePanel.parent instanceof LibraryVizPanel) {
|
||||
if (sourcePanel.parent.parent instanceof SceneGridItem) {
|
||||
if (sourcePanel.parent.parent instanceof DashboardGridItem) {
|
||||
const newLibPanel = sourcePanel.parent.clone({
|
||||
panel: this.state.panel.clone({
|
||||
$data: this.state.$data?.clone(),
|
||||
@ -376,6 +389,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
});
|
||||
sourcePanel.parent.parent.setState({
|
||||
body: newLibPanel,
|
||||
...repeatUpdate,
|
||||
});
|
||||
updateLibraryVizPanel(newLibPanel!).then((p) => {
|
||||
if (sourcePanel.parent instanceof LibraryVizPanel) {
|
||||
@ -392,17 +406,20 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
||||
public getPanelSaveModel(): Panel | object {
|
||||
const sourcePanel = this.state.sourcePanel.resolve();
|
||||
|
||||
if (sourcePanel.parent instanceof SceneGridItem) {
|
||||
const parentClone = sourcePanel.parent.clone({
|
||||
body: this.state.panel.clone({
|
||||
$data: this.state.$data?.clone(),
|
||||
}),
|
||||
});
|
||||
const isLibraryPanel = sourcePanel.parent instanceof LibraryVizPanel;
|
||||
const gridItem = isLibraryPanel ? sourcePanel.parent.parent : sourcePanel.parent;
|
||||
|
||||
return gridItemToPanel(parentClone);
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
return { error: 'Unsupported panel parent' };
|
||||
}
|
||||
|
||||
return { error: 'Unsupported panel parent' };
|
||||
const parentClone = gridItem.clone({
|
||||
body: this.state.panel.clone({
|
||||
$data: this.state.$data?.clone(),
|
||||
}),
|
||||
});
|
||||
|
||||
return gridItemToPanel(parentClone);
|
||||
}
|
||||
|
||||
public getPanelCloneWithData(): VizPanel {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { SceneGridItem, SceneGridLayout, SceneQueryRunner, SceneTimeRange, VizPanel, behaviors } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneQueryRunner, SceneTimeRange, VizPanel, behaviors } from '@grafana/scenes';
|
||||
import { ContextSrv, setContextSrv } from 'app/core/services/context_srv';
|
||||
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
|
||||
import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
||||
|
||||
@ -137,7 +138,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$behaviors: [new behaviors.CursorSync({})],
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
|
@ -2,7 +2,6 @@ import { Unsubscribable } from 'rxjs';
|
||||
|
||||
import {
|
||||
SceneDataLayers,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneObjectStateChangedEvent,
|
||||
SceneRefreshPicker,
|
||||
@ -14,6 +13,7 @@ import { createWorker } from 'app/features/dashboard-scene/saving/createDetectCh
|
||||
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene, PERSISTED_PROPS } from '../scene/DashboardScene';
|
||||
import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
||||
import { isSceneVariableInstance } from '../settings/variables/utils';
|
||||
@ -41,7 +41,7 @@ export class DashboardSceneChangeTracker {
|
||||
if (payload.changedObject instanceof SceneDataLayers) {
|
||||
this.detectChanges();
|
||||
}
|
||||
if (payload.changedObject instanceof SceneGridItem) {
|
||||
if (payload.changedObject instanceof DashboardGridItem) {
|
||||
this.detectChanges();
|
||||
}
|
||||
if (payload.changedObject instanceof SceneGridLayout) {
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { SceneGridItem, SceneGridLayout, SceneGridRow, SceneTimeRange } from '@grafana/scenes';
|
||||
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', () => {
|
||||
@ -39,7 +40,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
body.setState({
|
||||
children: [
|
||||
...body.state.children,
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -53,7 +54,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
|
||||
anotherLibPanelWidget.onCancelAddPanel(mockEvent);
|
||||
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
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);
|
||||
@ -67,7 +68,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
new SceneGridRow({
|
||||
key: 'panel-2',
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -103,7 +104,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
};
|
||||
|
||||
const body = dashboard.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(gridItem.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
||||
|
||||
@ -121,7 +122,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
body.setState({
|
||||
children: [
|
||||
...body.state.children,
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -145,8 +146,8 @@ describe('AddLibraryPanelWidget', () => {
|
||||
|
||||
anotherLibPanelWidget.onAddLibraryPanel(panelInfo);
|
||||
|
||||
const gridItemOne = body.state.children[0] as SceneGridItem;
|
||||
const gridItemTwo = body.state.children[1] as SceneGridItem;
|
||||
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);
|
||||
@ -161,7 +162,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
new SceneGridRow({
|
||||
key: 'panel-2',
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -190,7 +191,7 @@ describe('AddLibraryPanelWidget', () => {
|
||||
anotherLibPanelWidget.onAddLibraryPanel(panelInfo);
|
||||
|
||||
const gridRow = body.state.children[0] as SceneGridRow;
|
||||
const gridItem = gridRow.state.children[0] as SceneGridItem;
|
||||
const gridItem = gridRow.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(1);
|
||||
expect(gridItem.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||
@ -230,7 +231,7 @@ async function buildTestScene() {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -3,14 +3,7 @@ import React from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import {
|
||||
SceneComponentProps,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObjectBase,
|
||||
SceneObjectState,
|
||||
} from '@grafana/scenes';
|
||||
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';
|
||||
@ -21,6 +14,7 @@ import {
|
||||
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
|
||||
@ -62,7 +56,7 @@ export class AddLibraryPanelWidget extends SceneObjectBase<AddLibraryPanelWidget
|
||||
const rowChildren = [];
|
||||
|
||||
for (const rowChild of child.state.children) {
|
||||
if (rowChild instanceof SceneGridItem && rowChild.state.key !== this.parent?.state.key) {
|
||||
if (rowChild instanceof DashboardGridItem && rowChild.state.key !== this.parent?.state.key) {
|
||||
rowChildren.push(rowChild);
|
||||
}
|
||||
}
|
||||
@ -86,7 +80,7 @@ export class AddLibraryPanelWidget extends SceneObjectBase<AddLibraryPanelWidget
|
||||
panelKey: this.state.key,
|
||||
});
|
||||
|
||||
if (this.parent instanceof SceneGridItem) {
|
||||
if (this.parent instanceof DashboardGridItem) {
|
||||
this.parent.setState({ body });
|
||||
}
|
||||
};
|
||||
|
@ -22,14 +22,15 @@ import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
|
||||
|
||||
import { getMultiVariableValues } from '../utils/utils';
|
||||
|
||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { repeatPanelMenuBehavior } from './PanelMenuBehavior';
|
||||
import { DashboardRepeatsProcessedEvent } from './types';
|
||||
|
||||
interface PanelRepeaterGridItemState extends SceneGridItemStateLike {
|
||||
source: VizPanel | LibraryVizPanel;
|
||||
interface DashboardGridItemState extends SceneGridItemStateLike {
|
||||
body: VizPanel | LibraryVizPanel | AddLibraryPanelWidget;
|
||||
repeatedPanels?: VizPanel[];
|
||||
variableName: string;
|
||||
variableName?: string;
|
||||
itemHeight?: number;
|
||||
repeatDirection?: RepeatDirection;
|
||||
maxPerRow?: number;
|
||||
@ -37,33 +38,37 @@ interface PanelRepeaterGridItemState extends SceneGridItemStateLike {
|
||||
|
||||
export type RepeatDirection = 'v' | 'h';
|
||||
|
||||
export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItemState> implements SceneGridItemLike {
|
||||
export class DashboardGridItem extends SceneObjectBase<DashboardGridItemState> implements SceneGridItemLike {
|
||||
protected _variableDependency = new VariableDependencyConfig(this, {
|
||||
variableNames: [this.state.variableName],
|
||||
variableNames: this.state.variableName ? [this.state.variableName] : [],
|
||||
onVariableUpdateCompleted: this._onVariableUpdateCompleted.bind(this),
|
||||
});
|
||||
|
||||
public constructor(state: PanelRepeaterGridItemState) {
|
||||
public constructor(state: DashboardGridItemState) {
|
||||
super(state);
|
||||
|
||||
this.addActivationHandler(() => this._activationHandler());
|
||||
}
|
||||
|
||||
private _activationHandler() {
|
||||
this._subs.add(this.subscribeToState((newState, prevState) => this._handleGridResize(newState, prevState)));
|
||||
this._performRepeat();
|
||||
if (this.state.variableName) {
|
||||
this._subs.add(this.subscribeToState((newState, prevState) => this._handleGridResize(newState, prevState)));
|
||||
this._performRepeat();
|
||||
}
|
||||
}
|
||||
|
||||
private _onVariableUpdateCompleted(): void {
|
||||
this._performRepeat();
|
||||
if (this.state.variableName) {
|
||||
this._performRepeat();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the current repeat item count to calculate the user intended desired itemHeight
|
||||
*/
|
||||
private _handleGridResize(newState: PanelRepeaterGridItemState, prevState: PanelRepeaterGridItemState) {
|
||||
private _handleGridResize(newState: DashboardGridItemState, prevState: DashboardGridItemState) {
|
||||
const itemCount = this.state.repeatedPanels?.length ?? 1;
|
||||
const stateChange: Partial<PanelRepeaterGridItemState> = {};
|
||||
const stateChange: Partial<DashboardGridItemState> = {};
|
||||
|
||||
// Height changed
|
||||
if (newState.height === prevState.height) {
|
||||
@ -84,7 +89,10 @@ export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItem
|
||||
}
|
||||
|
||||
private _performRepeat() {
|
||||
if (this._variableDependency.hasDependencyInLoadingState()) {
|
||||
if (this.state.body instanceof AddLibraryPanelWidget) {
|
||||
return;
|
||||
}
|
||||
if (!this.state.variableName || this._variableDependency.hasDependencyInLoadingState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -99,12 +107,11 @@ export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItem
|
||||
});
|
||||
|
||||
if (!(variable instanceof MultiValueVariable)) {
|
||||
console.error('PanelRepeaterGridItem: Variable is not a MultiValueVariable');
|
||||
console.error('DashboardGridItem: Variable is not a MultiValueVariable');
|
||||
return;
|
||||
}
|
||||
|
||||
let panelToRepeat =
|
||||
this.state.source instanceof LibraryVizPanel ? this.state.source.state.panel! : this.state.source;
|
||||
let panelToRepeat = this.state.body instanceof LibraryVizPanel ? this.state.body.state.panel! : this.state.body;
|
||||
const { values, texts } = getMultiVariableValues(variable);
|
||||
const repeatedPanels: VizPanel[] = [];
|
||||
|
||||
@ -128,7 +135,7 @@ export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItem
|
||||
}
|
||||
|
||||
const direction = this.getRepeatDirection();
|
||||
const stateChange: Partial<PanelRepeaterGridItemState> = { repeatedPanels: repeatedPanels };
|
||||
const stateChange: Partial<DashboardGridItemState> = { repeatedPanels: repeatedPanels };
|
||||
const itemHeight = this.state.itemHeight ?? 10;
|
||||
const prevHeight = this.state.height;
|
||||
const maxPerRow = this.getMaxPerRow();
|
||||
@ -166,11 +173,29 @@ export class PanelRepeaterGridItem extends SceneObjectBase<PanelRepeaterGridItem
|
||||
return 'panel-repeater-grid-item';
|
||||
}
|
||||
|
||||
public static Component = ({ model }: SceneComponentProps<PanelRepeaterGridItem>) => {
|
||||
const { repeatedPanels, itemHeight } = model.useState();
|
||||
public isRepeated() {
|
||||
return this.state.variableName !== undefined;
|
||||
}
|
||||
|
||||
public static Component = ({ model }: SceneComponentProps<DashboardGridItem>) => {
|
||||
const { repeatedPanels, itemHeight, variableName, body } = model.useState();
|
||||
const itemCount = repeatedPanels?.length ?? 0;
|
||||
const layoutStyle = useLayoutStyle(model.getRepeatDirection(), itemCount, model.getMaxPerRow(), itemHeight ?? 10);
|
||||
|
||||
if (!variableName) {
|
||||
if (body instanceof VizPanel) {
|
||||
return <body.Component model={body} key={body.state.key} />;
|
||||
}
|
||||
|
||||
if (body instanceof LibraryVizPanel) {
|
||||
return <body.Component model={body} key={body.state.key} />;
|
||||
}
|
||||
|
||||
if (body instanceof AddLibraryPanelWidget) {
|
||||
return <body.Component model={body} key={body.state.key} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (!repeatedPanels) {
|
||||
return null;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import {
|
||||
sceneGraph,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneTimeRange,
|
||||
SceneQueryRunner,
|
||||
@ -28,9 +27,9 @@ import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||
import { djb2Hash } from '../utils/djb2Hash';
|
||||
|
||||
import { DashboardControls } from './DashboardControls';
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from './PanelRepeaterGridItem';
|
||||
|
||||
jest.mock('../settings/version-history/HistorySrv');
|
||||
jest.mock('../serialization/transformSaveModelToScene');
|
||||
@ -142,13 +141,13 @@ describe('DashboardScene', () => {
|
||||
});
|
||||
|
||||
it('A change to griditem pos should set isDirty true', () => {
|
||||
const gridItem = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as SceneGridItem;
|
||||
const gridItem = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as DashboardGridItem;
|
||||
gridItem.setState({ x: 10, y: 0, width: 10, height: 10 });
|
||||
|
||||
expect(scene.state.isDirty).toBe(true);
|
||||
|
||||
scene.exitEditMode({ skipConfirm: true });
|
||||
const gridItem2 = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as SceneGridItem;
|
||||
const gridItem2 = sceneGraph.findObject(scene, (p) => p.state.key === 'griditem-1') as DashboardGridItem;
|
||||
expect(gridItem2.state.x).toBe(0);
|
||||
});
|
||||
|
||||
@ -275,7 +274,7 @@ describe('DashboardScene', () => {
|
||||
scene.addPanel(vizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-5');
|
||||
@ -286,7 +285,7 @@ describe('DashboardScene', () => {
|
||||
scene.onCreateNewPanel();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
||||
@ -308,7 +307,7 @@ describe('DashboardScene', () => {
|
||||
const scene = buildTestScene({
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -318,7 +317,7 @@ describe('DashboardScene', () => {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
@ -372,7 +371,7 @@ describe('DashboardScene', () => {
|
||||
|
||||
scene.removeRow(row);
|
||||
|
||||
const vizPanel = (body.state.children[2] as SceneGridItem).state.body as VizPanel;
|
||||
const vizPanel = (body.state.children[2] as DashboardGridItem).state.body as VizPanel;
|
||||
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(vizPanel.state.key).toBe('panel-4');
|
||||
@ -438,14 +437,14 @@ describe('DashboardScene', () => {
|
||||
});
|
||||
|
||||
it('Should copy a panel', () => {
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body;
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
||||
scene.copyPanel(vizPanel as VizPanel);
|
||||
|
||||
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
|
||||
const libVizPanel = ((scene.state.body as SceneGridLayout).state.children[4] as DashboardGridItem).state
|
||||
.body as LibraryVizPanel;
|
||||
|
||||
scene.copyPanel(libVizPanel.state.panel as VizPanel);
|
||||
@ -457,7 +456,7 @@ describe('DashboardScene', () => {
|
||||
scene.setState({ hasCopiedPanel: true });
|
||||
jest.spyOn(JSON, 'parse').mockReturnThis();
|
||||
jest.mocked(buildGridItemForPanel).mockReturnValue(
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-9',
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
@ -470,7 +469,7 @@ describe('DashboardScene', () => {
|
||||
scene.pastePanel();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(buildGridItemForPanel).toHaveBeenCalledTimes(1);
|
||||
expect(body.state.children.length).toBe(6);
|
||||
@ -483,7 +482,7 @@ describe('DashboardScene', () => {
|
||||
scene.setState({ hasCopiedPanel: true });
|
||||
jest.spyOn(JSON, 'parse').mockReturnValue({ libraryPanel: { uid: 'uid', name: 'libraryPanel' } });
|
||||
jest.mocked(buildGridItemForLibPanel).mockReturnValue(
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
title: 'Library Panel',
|
||||
uid: 'uid',
|
||||
@ -496,7 +495,7 @@ describe('DashboardScene', () => {
|
||||
scene.pastePanel();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
const libVizPanel = gridItem.state.body as LibraryVizPanel;
|
||||
|
||||
@ -512,7 +511,7 @@ describe('DashboardScene', () => {
|
||||
scene.onCreateLibPanelWidget();
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
||||
@ -520,7 +519,7 @@ describe('DashboardScene', () => {
|
||||
});
|
||||
|
||||
it('Should remove a panel', () => {
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body;
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
||||
scene.removePanel(vizPanel as VizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
@ -529,7 +528,8 @@ describe('DashboardScene', () => {
|
||||
|
||||
it('Should remove a panel within a row', () => {
|
||||
const vizPanel = (
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state.children[0] as SceneGridItem
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state
|
||||
.children[0] as DashboardGridItem
|
||||
).state.body;
|
||||
scene.removePanel(vizPanel as VizPanel);
|
||||
|
||||
@ -539,7 +539,7 @@ describe('DashboardScene', () => {
|
||||
});
|
||||
|
||||
it('Should remove a library panel', () => {
|
||||
const libraryPanel = ((scene.state.body as SceneGridLayout).state.children[4] as SceneGridItem).state.body;
|
||||
const libraryPanel = ((scene.state.body as SceneGridLayout).state.children[4] as DashboardGridItem).state.body;
|
||||
const vizPanel = (libraryPanel as LibraryVizPanel).state.panel;
|
||||
scene.removePanel(vizPanel as VizPanel);
|
||||
|
||||
@ -549,7 +549,8 @@ describe('DashboardScene', () => {
|
||||
|
||||
it('Should remove a library panel within a row', () => {
|
||||
const libraryPanel = (
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state.children[1] as SceneGridItem
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state
|
||||
.children[1] as DashboardGridItem
|
||||
).state.body;
|
||||
const vizPanel = (libraryPanel as LibraryVizPanel).state.panel;
|
||||
|
||||
@ -561,23 +562,23 @@ describe('DashboardScene', () => {
|
||||
});
|
||||
|
||||
it('Should duplicate a panel', () => {
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body;
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body;
|
||||
scene.duplicatePanel(vizPanel as VizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[5] as SceneGridItem;
|
||||
const gridItem = body.state.children[5] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(6);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
||||
});
|
||||
|
||||
it('Should duplicate a library panel', () => {
|
||||
const libraryPanel = ((scene.state.body as SceneGridLayout).state.children[4] as SceneGridItem).state.body;
|
||||
const libraryPanel = ((scene.state.body as SceneGridLayout).state.children[4] as DashboardGridItem).state.body;
|
||||
const vizPanel = (libraryPanel as LibraryVizPanel).state.panel;
|
||||
scene.duplicatePanel(vizPanel as VizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[5] as SceneGridItem;
|
||||
const gridItem = body.state.children[5] as DashboardGridItem;
|
||||
|
||||
const libVizPanel = gridItem.state.body as LibraryVizPanel;
|
||||
|
||||
@ -590,7 +591,7 @@ describe('DashboardScene', () => {
|
||||
const scene = buildTestScene({
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new PanelRepeaterGridItem({
|
||||
new DashboardGridItem({
|
||||
key: `grid-item-1`,
|
||||
width: 24,
|
||||
height: 8,
|
||||
@ -601,7 +602,7 @@ describe('DashboardScene', () => {
|
||||
pluginId: 'table',
|
||||
}),
|
||||
],
|
||||
source: new VizPanel({
|
||||
body: new VizPanel({
|
||||
title: 'Library Panel',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
@ -612,13 +613,13 @@ describe('DashboardScene', () => {
|
||||
}),
|
||||
});
|
||||
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as PanelRepeaterGridItem).state
|
||||
const vizPanel = ((scene.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state
|
||||
.repeatedPanels![0];
|
||||
|
||||
scene.duplicatePanel(vizPanel as VizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[1] as SceneGridItem;
|
||||
const gridItem = body.state.children[1] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(2);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-2');
|
||||
@ -626,13 +627,14 @@ describe('DashboardScene', () => {
|
||||
|
||||
it('Should duplicate a panel in a row', () => {
|
||||
const vizPanel = (
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state.children[0] as SceneGridItem
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state
|
||||
.children[0] as DashboardGridItem
|
||||
).state.body;
|
||||
scene.duplicatePanel(vizPanel as VizPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridRow = body.state.children[2] as SceneGridRow;
|
||||
const gridItem = gridRow.state.children[2] as SceneGridItem;
|
||||
const gridItem = gridRow.state.children[2] as DashboardGridItem;
|
||||
|
||||
expect(gridRow.state.children.length).toBe(3);
|
||||
expect(gridItem.state.body!.state.key).toBe('panel-7');
|
||||
@ -640,7 +642,8 @@ describe('DashboardScene', () => {
|
||||
|
||||
it('Should duplicate a library panel in a row', () => {
|
||||
const libraryPanel = (
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state.children[1] as SceneGridItem
|
||||
((scene.state.body as SceneGridLayout).state.children[2] as SceneGridRow).state
|
||||
.children[1] as DashboardGridItem
|
||||
).state.body;
|
||||
const vizPanel = (libraryPanel as LibraryVizPanel).state.panel;
|
||||
|
||||
@ -648,7 +651,7 @@ describe('DashboardScene', () => {
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridRow = body.state.children[2] as SceneGridRow;
|
||||
const gridItem = gridRow.state.children[2] as SceneGridItem;
|
||||
const gridItem = gridRow.state.children[2] as DashboardGridItem;
|
||||
|
||||
const libVizPanel = gridItem.state.body as LibraryVizPanel;
|
||||
|
||||
@ -688,7 +691,7 @@ describe('DashboardScene', () => {
|
||||
const scene = buildTestScene({
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
body: libPanel,
|
||||
}),
|
||||
@ -699,7 +702,7 @@ describe('DashboardScene', () => {
|
||||
scene.unlinkLibraryPanel(libPanel);
|
||||
|
||||
const body = scene.state.body as SceneGridLayout;
|
||||
const gridItem = body.state.children[0] as SceneGridItem;
|
||||
const gridItem = body.state.children[0] as DashboardGridItem;
|
||||
|
||||
expect(body.state.children.length).toBe(1);
|
||||
expect(gridItem.state.body).toBeInstanceOf(VizPanel);
|
||||
@ -865,7 +868,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$behaviors: [new behaviors.CursorSync({})],
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -875,7 +878,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-2',
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
@ -886,14 +889,14 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
new SceneGridRow({
|
||||
key: 'panel-3',
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel C',
|
||||
key: 'panel-4',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'libraryPanel',
|
||||
@ -908,7 +911,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
}),
|
||||
],
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
key: 'panel-2-clone-1',
|
||||
@ -916,7 +919,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner2', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'libraryPanel',
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
getUrlSyncManager,
|
||||
SceneFlexLayout,
|
||||
sceneGraph,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObject,
|
||||
@ -59,10 +58,10 @@ import {
|
||||
|
||||
import { AddLibraryPanelWidget } from './AddLibraryPanelWidget';
|
||||
import { DashboardControls } from './DashboardControls';
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardSceneRenderer } from './DashboardSceneRenderer';
|
||||
import { DashboardSceneUrlSync } from './DashboardSceneUrlSync';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from './PanelRepeaterGridItem';
|
||||
import { ScopesScene } from './ScopesScene';
|
||||
import { ViewPanelScene } from './ViewPanelScene';
|
||||
import { setupKeyboardShortcuts } from './keyboardShortcuts';
|
||||
@ -464,7 +463,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
const sceneGridLayout = this.state.body;
|
||||
|
||||
const panelId = getPanelIdForVizPanel(vizPanel);
|
||||
const newGridItem = new SceneGridItem({
|
||||
const newGridItem = new DashboardGridItem({
|
||||
height: NEW_PANEL_HEIGHT,
|
||||
width: NEW_PANEL_WIDTH,
|
||||
x: 0,
|
||||
@ -487,8 +486,8 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
|
||||
const gridItem = libraryPanel ? libraryPanel.parent : vizPanel.parent;
|
||||
|
||||
if (!(gridItem instanceof SceneGridItem || gridItem instanceof PanelRepeaterGridItem)) {
|
||||
console.error('Trying to duplicate a panel in a layout that is not SceneGridItem or PanelRepeaterGridItem');
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
console.error('Trying to duplicate a panel in a layout that is not DashboardGridItem');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -500,7 +499,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
if (libraryPanel) {
|
||||
const gridItemToDuplicateState = sceneUtils.cloneSceneObjectState(gridItem.state);
|
||||
|
||||
newGridItem = new SceneGridItem({
|
||||
newGridItem = new DashboardGridItem({
|
||||
x: gridItemToDuplicateState.x,
|
||||
y: gridItemToDuplicateState.y,
|
||||
width: gridItemToDuplicateState.width,
|
||||
@ -513,9 +512,9 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
panelState = sceneUtils.cloneSceneObjectState(gridItem.state.source.state);
|
||||
panelData = sceneGraph.getData(gridItem.state.source).clone();
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
panelState = sceneUtils.cloneSceneObjectState(gridItem.state.body.state);
|
||||
panelData = sceneGraph.getData(gridItem.state.body).clone();
|
||||
} else {
|
||||
panelState = sceneUtils.cloneSceneObjectState(vizPanel.state);
|
||||
panelData = sceneGraph.getData(vizPanel).clone();
|
||||
@ -524,7 +523,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
// when we duplicate a panel we don't want to clone the alert state
|
||||
delete panelData.state.data?.alertState;
|
||||
|
||||
newGridItem = new SceneGridItem({
|
||||
newGridItem = new DashboardGridItem({
|
||||
x: gridItem.state.x,
|
||||
y: gridItem.state.y,
|
||||
height: NEW_PANEL_HEIGHT,
|
||||
@ -574,6 +573,11 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
gridItem = libraryVizPanel.parent;
|
||||
}
|
||||
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
console.error('Trying to copy a panel that is not DashboardGridItem child');
|
||||
throw new Error('Trying to copy a panel that is not DashboardGridItem child');
|
||||
}
|
||||
|
||||
const jsonData = gridItemToPanel(gridItem);
|
||||
|
||||
store.set(LS_PANEL_COPY_KEY, JSON.stringify(jsonData));
|
||||
@ -595,13 +599,13 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
|
||||
const sceneGridLayout = this.state.body;
|
||||
|
||||
if (!(gridItem instanceof SceneGridItem) && !(gridItem instanceof PanelRepeaterGridItem)) {
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
throw new Error('Cannot paste invalid grid item');
|
||||
}
|
||||
|
||||
const panelId = dashboardSceneGraph.getNextPanelId(this);
|
||||
|
||||
if (gridItem instanceof SceneGridItem && gridItem.state.body instanceof LibraryVizPanel) {
|
||||
if (gridItem instanceof DashboardGridItem && gridItem.state.body instanceof LibraryVizPanel) {
|
||||
const panelKey = getVizPanelKeyForPanelId(panelId);
|
||||
|
||||
gridItem.state.body.setState({ panelKey });
|
||||
@ -611,12 +615,12 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
if (vizPanel instanceof VizPanel) {
|
||||
vizPanel.setState({ key: panelKey });
|
||||
}
|
||||
} else if (gridItem instanceof SceneGridItem && gridItem.state.body) {
|
||||
} else if (gridItem instanceof DashboardGridItem && gridItem.state.body) {
|
||||
gridItem.state.body.setState({
|
||||
key: getVizPanelKeyForPanelId(panelId),
|
||||
});
|
||||
} else if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
gridItem.state.source.setState({
|
||||
} else if (gridItem instanceof DashboardGridItem) {
|
||||
gridItem.state.body.setState({
|
||||
key: getVizPanelKeyForPanelId(panelId),
|
||||
});
|
||||
}
|
||||
@ -687,8 +691,8 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
|
||||
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');
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
console.error('Trying to unlinka a lib panel in a layout that is not DashboardGridItem');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -737,7 +741,7 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
|
||||
|
||||
const panelId = dashboardSceneGraph.getNextPanelId(this);
|
||||
|
||||
const newGridItem = new SceneGridItem({
|
||||
const newGridItem = new DashboardGridItem({
|
||||
height: NEW_PANEL_HEIGHT,
|
||||
width: NEW_PANEL_WIDTH,
|
||||
x: 0,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { AppEvents } from '@grafana/data';
|
||||
import { SceneGridItem, SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes';
|
||||
import appEvents from 'app/core/app_events';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { DashboardRepeatsProcessedEvent } from './types';
|
||||
|
||||
@ -42,7 +43,7 @@ describe('DashboardSceneUrlSync', () => {
|
||||
const layout = scene.state.body as SceneGridLayout;
|
||||
layout.setState({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -66,7 +67,7 @@ function buildTestScene() {
|
||||
uid: 'dash-1',
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -76,7 +77,7 @@ function buildTestScene() {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
key: 'panel-2',
|
||||
|
@ -5,12 +5,12 @@ import { http, HttpResponse } from 'msw';
|
||||
import { setupServer, SetupServerApi } from 'msw/node';
|
||||
|
||||
import { setBackendSrv } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, VizPanel } from '@grafana/scenes';
|
||||
import { LibraryPanel } from '@grafana/schema';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { LibraryVizPanel } from './LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from './PanelRepeaterGridItem';
|
||||
|
||||
describe('LibraryVizPanel', () => {
|
||||
const server = setupServer();
|
||||
@ -42,7 +42,7 @@ describe('LibraryVizPanel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should change parent from SceneGridItem to PanelRepeaterGridItem if repeat is set', async () => {
|
||||
it('should configure repeat options of DashboardGridIem if repeat is set', async () => {
|
||||
setUpApiMock(server, { model: { repeat: 'query0', repeatDirection: 'h' } });
|
||||
const libVizPanel = new LibraryVizPanel({
|
||||
name: 'My Library Panel',
|
||||
@ -52,12 +52,17 @@ describe('LibraryVizPanel', () => {
|
||||
});
|
||||
|
||||
const layout = new SceneGridLayout({
|
||||
children: [new SceneGridItem({ body: libVizPanel })],
|
||||
children: [new DashboardGridItem({ body: libVizPanel })],
|
||||
});
|
||||
|
||||
layout.activate();
|
||||
libVizPanel.activate();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(layout.state.children[0]).toBeInstanceOf(PanelRepeaterGridItem);
|
||||
expect(layout.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||
expect((layout.state.children[0] as DashboardGridItem).state.variableName).toBe('query0');
|
||||
expect((layout.state.children[0] as DashboardGridItem).state.repeatDirection).toBe('h');
|
||||
expect((layout.state.children[0] as DashboardGridItem).state.maxPerRow).toBe(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -2,7 +2,6 @@ import React from 'react';
|
||||
|
||||
import {
|
||||
SceneComponentProps,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneObjectBase,
|
||||
SceneObjectState,
|
||||
@ -16,10 +15,10 @@ import { getLibraryPanel } from 'app/features/library-panels/state/api';
|
||||
|
||||
import { createPanelDataProvider } from '../utils/createPanelDataProvider';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from './PanelLinks';
|
||||
import { panelLinksBehavior, panelMenuBehavior } from './PanelMenuBehavior';
|
||||
import { PanelNotices } from './PanelNotices';
|
||||
import { PanelRepeaterGridItem } from './PanelRepeaterGridItem';
|
||||
|
||||
interface LibraryVizPanelState extends SceneObjectState {
|
||||
// Library panels use title from dashboard JSON's panel model, not from library panel definition, hence we pass it.
|
||||
@ -81,16 +80,16 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
|
||||
const panel = new VizPanel(vizPanelState);
|
||||
const gridItem = this.parent;
|
||||
|
||||
if (libPanelModel.repeat && gridItem instanceof SceneGridItem && gridItem.parent instanceof SceneGridLayout) {
|
||||
if (libPanelModel.repeat && gridItem instanceof DashboardGridItem && gridItem.parent instanceof SceneGridLayout) {
|
||||
this._parent = undefined;
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
const repeater = new DashboardGridItem({
|
||||
key: gridItem.state.key,
|
||||
x: gridItem.state.x,
|
||||
y: gridItem.state.y,
|
||||
width: libPanelModel.repeatDirection === 'h' ? 24 : gridItem.state.width,
|
||||
height: gridItem.state.height,
|
||||
itemHeight: gridItem.state.height,
|
||||
source: this,
|
||||
body: this,
|
||||
variableName: libPanelModel.repeat,
|
||||
repeatedPanels: [],
|
||||
repeatDirection: libPanelModel.repeatDirection === 'h' ? 'h' : 'v',
|
||||
@ -112,6 +111,13 @@ export class LibraryVizPanel extends SceneObjectBase<LibraryVizPanelState> {
|
||||
try {
|
||||
const libPanel = await getLibraryPanel(this.state.uid, true);
|
||||
this.setPanelFromLibPanel(libPanel);
|
||||
if (this.parent instanceof DashboardGridItem) {
|
||||
this.parent.setState({
|
||||
variableName: libPanel.model.repeat,
|
||||
repeatDirection: libPanel.model.repeatDirection === 'h' ? 'h' : 'v',
|
||||
maxPerRow: libPanel.model.maxPerRow,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
vizPanel.setState({
|
||||
_pluginLoadError: `Unable to load library panel: ${this.state.uid}`,
|
||||
|
@ -11,7 +11,6 @@ import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { getPluginLinkExtensions, locationService } from '@grafana/runtime';
|
||||
import {
|
||||
LocalValueVariable,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneQueryRunner,
|
||||
SceneTimeRange,
|
||||
@ -24,6 +23,7 @@ import { GetExploreUrlArguments } from 'app/core/utils/explore';
|
||||
|
||||
import { buildPanelEditScene } from '../panel-edit/PanelEditor';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from './PanelLinks';
|
||||
import { panelMenuBehavior } from './PanelMenuBehavior';
|
||||
@ -590,7 +590,7 @@ async function buildTestScene(options: SceneOptions) {
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import {
|
||||
EmbeddedScene,
|
||||
SceneCanvasText,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneGridItem,
|
||||
SceneTimeRange,
|
||||
SceneVariableSet,
|
||||
TestVariable,
|
||||
@ -12,7 +12,7 @@ import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/co
|
||||
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
import { RepeatDirection } from './PanelRepeaterGridItem';
|
||||
import { RepeatDirection } from './DashboardGridItem';
|
||||
import { RowRepeaterBehavior } from './RowRepeaterBehavior';
|
||||
|
||||
describe('RowRepeaterBehavior', () => {
|
||||
|
@ -1,12 +1,6 @@
|
||||
import {
|
||||
LocalValueVariable,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneVariableSet,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { LocalValueVariable, SceneGridLayout, SceneGridRow, SceneVariableSet, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from './DashboardGridItem';
|
||||
import { DashboardScene } from './DashboardScene';
|
||||
import { ViewPanelScene } from './ViewPanelScene';
|
||||
|
||||
@ -56,7 +50,7 @@ function buildScene(options?: SceneOptions) {
|
||||
: undefined,
|
||||
height: 1,
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: panel,
|
||||
}),
|
||||
],
|
||||
|
@ -4,12 +4,10 @@ import React from 'react';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import {
|
||||
SceneComponentProps,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObjectBase,
|
||||
SceneObjectState,
|
||||
SceneQueryRunner,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { Icon, TextLink, useStyles2 } from '@grafana/ui';
|
||||
@ -17,7 +15,8 @@ import appEvents from 'app/core/app_events';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
import { ShowConfirmModalEvent } from 'app/types/events';
|
||||
|
||||
import { getDashboardSceneFor } from '../../utils/utils';
|
||||
import { getDashboardSceneFor, getQueryRunnerFor } from '../../utils/utils';
|
||||
import { DashboardGridItem } from '../DashboardGridItem';
|
||||
import { DashboardScene } from '../DashboardScene';
|
||||
import { RowRepeaterBehavior } from '../RowRepeaterBehavior';
|
||||
|
||||
@ -122,12 +121,14 @@ export class RowActions extends SceneObjectBase<RowActionsState> {
|
||||
const gridItems = row.state.children;
|
||||
|
||||
const isAnyPanelUsingDashboardDS = gridItems.some((gridItem) => {
|
||||
if (!(gridItem instanceof SceneGridItem)) {
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gridItem.state.body instanceof VizPanel && gridItem.state.body.state.$data instanceof SceneQueryRunner) {
|
||||
return gridItem.state.body.state.$data?.state.datasource?.uid === SHARED_DASHBOARD_QUERY;
|
||||
const vizPanel = gridItem.state.body;
|
||||
if (vizPanel instanceof VizPanel) {
|
||||
const runner = getQueryRunnerFor(vizPanel);
|
||||
return runner?.state.datasource?.uid === SHARED_DASHBOARD_QUERY;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -22,7 +22,6 @@ import {
|
||||
SceneDataLayerControls,
|
||||
SceneDataLayers,
|
||||
SceneDataTransformer,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneQueryRunner,
|
||||
@ -43,8 +42,8 @@ import { DASHBOARD_DATASOURCE_PLUGIN_ID } from 'app/plugins/datasource/dashboard
|
||||
import { DashboardDataDTO } from 'app/types';
|
||||
|
||||
import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { NEW_LINK } from '../settings/links/utils';
|
||||
@ -224,11 +223,11 @@ describe('transformSaveModelToScene', () => {
|
||||
expect(rowScene.state.y).toEqual(row.gridPos!.y);
|
||||
expect(rowScene.state.isCollapsed).toEqual(row.collapsed);
|
||||
expect(rowScene.state.children).toHaveLength(3);
|
||||
expect(rowScene.state.children[0]).toBeInstanceOf(SceneGridItem);
|
||||
expect(rowScene.state.children[1]).toBeInstanceOf(SceneGridItem);
|
||||
expect(rowScene.state.children[2]).toBeInstanceOf(SceneGridItem);
|
||||
expect((rowScene.state.children[1] as SceneGridItem).state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
||||
expect((rowScene.state.children[2] as SceneGridItem).state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||
expect(rowScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||
expect(rowScene.state.children[1]).toBeInstanceOf(DashboardGridItem);
|
||||
expect(rowScene.state.children[2]).toBeInstanceOf(DashboardGridItem);
|
||||
expect((rowScene.state.children[1] as DashboardGridItem).state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
||||
expect((rowScene.state.children[2] as DashboardGridItem).state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||
});
|
||||
|
||||
it('should create panels within expanded row', () => {
|
||||
@ -335,16 +334,16 @@ describe('transformSaveModelToScene', () => {
|
||||
expect(body.state.children).toHaveLength(5);
|
||||
expect(body).toBeInstanceOf(SceneGridLayout);
|
||||
// Panel out of row
|
||||
expect(body.state.children[0]).toBeInstanceOf(SceneGridItem);
|
||||
const panelOutOfRowVizPanel = body.state.children[0] as SceneGridItem;
|
||||
expect(body.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||
const panelOutOfRowVizPanel = body.state.children[0] as DashboardGridItem;
|
||||
expect((panelOutOfRowVizPanel.state.body as VizPanel)?.state.title).toBe(panelOutOfRow.title);
|
||||
// widget lib panel out of row
|
||||
expect(body.state.children[1]).toBeInstanceOf(SceneGridItem);
|
||||
const panelOutOfRowWidget = body.state.children[1] as SceneGridItem;
|
||||
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
|
||||
expect(body.state.children[2]).toBeInstanceOf(SceneGridItem);
|
||||
const panelOutOfRowLibVizPanel = body.state.children[2] as SceneGridItem;
|
||||
expect(body.state.children[2]).toBeInstanceOf(DashboardGridItem);
|
||||
const panelOutOfRowLibVizPanel = body.state.children[2] as DashboardGridItem;
|
||||
expect(panelOutOfRowLibVizPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||
// Row with panels
|
||||
expect(body.state.children[3]).toBeInstanceOf(SceneGridRow);
|
||||
@ -352,13 +351,13 @@ describe('transformSaveModelToScene', () => {
|
||||
expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title);
|
||||
expect(rowWithPanelsScene.state.key).toBe('panel-10');
|
||||
expect(rowWithPanelsScene.state.children).toHaveLength(3);
|
||||
const widget = rowWithPanelsScene.state.children[1] as SceneGridItem;
|
||||
const widget = rowWithPanelsScene.state.children[1] as DashboardGridItem;
|
||||
expect(widget.state.body!).toBeInstanceOf(AddLibraryPanelWidget);
|
||||
const libPanel = rowWithPanelsScene.state.children[2] as SceneGridItem;
|
||||
const libPanel = rowWithPanelsScene.state.children[2] as DashboardGridItem;
|
||||
expect(libPanel.state.body!).toBeInstanceOf(LibraryVizPanel);
|
||||
// Panel within row
|
||||
expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(SceneGridItem);
|
||||
const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as SceneGridItem;
|
||||
expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(DashboardGridItem);
|
||||
const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as DashboardGridItem;
|
||||
expect((panelInRowVizPanel.state.body as VizPanel).state.title).toBe(panelInRow.title);
|
||||
// Empty row
|
||||
expect(body.state.children[4]).toBeInstanceOf(SceneGridRow);
|
||||
@ -506,7 +505,7 @@ describe('transformSaveModelToScene', () => {
|
||||
};
|
||||
|
||||
const gridItem = buildGridItemForPanel(new PanelModel(panel));
|
||||
const repeater = gridItem as PanelRepeaterGridItem;
|
||||
const repeater = gridItem as DashboardGridItem;
|
||||
|
||||
expect(repeater.state.maxPerRow).toBe(8);
|
||||
expect(repeater.state.variableName).toBe('server');
|
||||
@ -1321,11 +1320,11 @@ describe('transformSaveModelToScene', () => {
|
||||
});
|
||||
});
|
||||
|
||||
function buildGridItemForTest(saveModel: Partial<Panel>): { gridItem: SceneGridItem; vizPanel: VizPanel } {
|
||||
function buildGridItemForTest(saveModel: Partial<Panel>): { gridItem: DashboardGridItem; vizPanel: VizPanel } {
|
||||
const gridItem = buildGridItemForPanel(new PanelModel(saveModel));
|
||||
if (gridItem instanceof SceneGridItem) {
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
return { gridItem, vizPanel: gridItem.state.body as VizPanel };
|
||||
}
|
||||
|
||||
throw new Error('buildGridItemForPanel to return SceneGridItem');
|
||||
throw new Error('buildGridItemForPanel to return DashboardGridItem');
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
ConstantVariable,
|
||||
IntervalVariable,
|
||||
SceneRefreshPicker,
|
||||
SceneGridItem,
|
||||
SceneObject,
|
||||
VizPanelMenu,
|
||||
behaviors,
|
||||
@ -38,13 +37,13 @@ import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardGridItem, RepeatDirection } from '../scene/DashboardGridItem';
|
||||
import { registerDashboardMacro } from '../scene/DashboardMacro';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
||||
import { panelLinksBehavior, panelMenuBehavior } from '../scene/PanelMenuBehavior';
|
||||
import { PanelNotices } from '../scene/PanelNotices';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { RowActions } from '../scene/row-actions/RowActions';
|
||||
@ -447,7 +446,7 @@ export function buildGridItemForLibraryPanelWidget(panel: PanelModel) {
|
||||
key: getVizPanelKeyForPanelId(panel.id),
|
||||
});
|
||||
|
||||
return new SceneGridItem({
|
||||
return new DashboardGridItem({
|
||||
body,
|
||||
y: panel.gridPos.y,
|
||||
x: panel.gridPos.x,
|
||||
@ -468,16 +467,26 @@ export function buildGridItemForLibPanel(panel: PanelModel) {
|
||||
panelKey: getVizPanelKeyForPanelId(panel.id),
|
||||
});
|
||||
|
||||
return new SceneGridItem({
|
||||
body,
|
||||
return new DashboardGridItem({
|
||||
key: `grid-item-${panel.id}`,
|
||||
y: panel.gridPos.y,
|
||||
x: panel.gridPos.x,
|
||||
width: panel.gridPos.w,
|
||||
height: panel.gridPos.h,
|
||||
itemHeight: panel.gridPos.h,
|
||||
body,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike {
|
||||
export function buildGridItemForPanel(panel: PanelModel): DashboardGridItem {
|
||||
const repeatDirection: RepeatDirection = panel.repeatDirection === 'h' ? 'h' : 'v';
|
||||
const repeatOptions = panel.repeat
|
||||
? {
|
||||
variableName: panel.repeat,
|
||||
repeatDirection,
|
||||
}
|
||||
: {};
|
||||
|
||||
const titleItems: SceneObject[] = [];
|
||||
|
||||
titleItems.push(
|
||||
@ -518,33 +527,18 @@ export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike {
|
||||
});
|
||||
}
|
||||
|
||||
if (panel.repeat) {
|
||||
const repeatDirection = panel.repeatDirection === 'h' ? 'h' : 'v';
|
||||
|
||||
return new PanelRepeaterGridItem({
|
||||
key: `grid-item-${panel.id}`,
|
||||
x: panel.gridPos.x,
|
||||
y: panel.gridPos.y,
|
||||
width: repeatDirection === 'h' ? 24 : panel.gridPos.w,
|
||||
height: panel.gridPos.h,
|
||||
itemHeight: panel.gridPos.h,
|
||||
source: new VizPanel(vizPanelState),
|
||||
variableName: panel.repeat,
|
||||
repeatedPanels: [],
|
||||
repeatDirection: repeatDirection,
|
||||
maxPerRow: panel.maxPerRow,
|
||||
});
|
||||
}
|
||||
|
||||
const body = new VizPanel(vizPanelState);
|
||||
|
||||
return new SceneGridItem({
|
||||
return new DashboardGridItem({
|
||||
key: `grid-item-${panel.id}`,
|
||||
x: panel.gridPos.x,
|
||||
y: panel.gridPos.y,
|
||||
width: panel.gridPos.w,
|
||||
width: repeatDirection === 'h' ? 24 : panel.gridPos.w,
|
||||
height: panel.gridPos.h,
|
||||
itemHeight: panel.gridPos.h,
|
||||
body,
|
||||
maxPerRow: panel.maxPerRow,
|
||||
...repeatOptions,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -16,21 +16,14 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { getPluginLinkExtensions, setPluginImportUtils } from '@grafana/runtime';
|
||||
import {
|
||||
MultiValueVariable,
|
||||
SceneDataLayers,
|
||||
SceneGridItem,
|
||||
SceneGridItemLike,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
import { MultiValueVariable, SceneDataLayers, SceneGridLayout, SceneGridRow, VizPanel } from '@grafana/scenes';
|
||||
import { Dashboard, LoadingState, Panel, RowPanel, VariableRefresh } from '@grafana/schema';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { getTimeRange } from 'app/features/dashboard/utils/timeRange';
|
||||
import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor';
|
||||
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { NEW_LINK } from '../settings/links/utils';
|
||||
@ -210,7 +203,9 @@ describe('transformSceneToSaveModel', () => {
|
||||
describe('Given a scene with rows', () => {
|
||||
it('Should transform back to persisted model', () => {
|
||||
const scene = transformSaveModelToScene({ dashboard: repeatingRowsAndPanelsDashboardJson as any, meta: {} });
|
||||
|
||||
const saveModel = transformSceneToSaveModel(scene);
|
||||
|
||||
const row2: RowPanel = saveModel.panels![2] as RowPanel;
|
||||
|
||||
expect(row2.type).toBe('row');
|
||||
@ -347,7 +342,7 @@ describe('transformSceneToSaveModel', () => {
|
||||
}),
|
||||
});
|
||||
|
||||
const panel = new SceneGridItem({
|
||||
const panel = new DashboardGridItem({
|
||||
body: libVizPanel,
|
||||
y: 0,
|
||||
x: 0,
|
||||
@ -987,7 +982,7 @@ describe('transformSceneToSaveModel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
export function buildGridItemFromPanelSchema(panel: Partial<Panel>): SceneGridItemLike {
|
||||
export function buildGridItemFromPanelSchema(panel: Partial<Panel>) {
|
||||
if (panel.libraryPanel) {
|
||||
return buildGridItemForLibPanel(new PanelModel(panel))!;
|
||||
} else if (panel.type === 'add-library-panel') {
|
||||
|
@ -4,7 +4,6 @@ import { isEmptyObject, ScopedVars, TimeRange } from '@grafana/data';
|
||||
import {
|
||||
behaviors,
|
||||
SceneDataLayers,
|
||||
SceneGridItem,
|
||||
SceneGridItemLike,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
@ -34,9 +33,9 @@ import { DASHBOARD_SCHEMA_VERSION } from 'app/features/dashboard/state/Dashboard
|
||||
import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types';
|
||||
|
||||
import { AddLibraryPanelWidget } from '../scene/AddLibraryPanelWidget';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||
@ -59,12 +58,13 @@ export function transformSceneToSaveModel(scene: DashboardScene, isSnapshot = fa
|
||||
|
||||
if (body instanceof SceneGridLayout) {
|
||||
for (const child of body.state.children) {
|
||||
if (child instanceof SceneGridItem) {
|
||||
panels.push(gridItemToPanel(child, isSnapshot));
|
||||
}
|
||||
|
||||
if (child instanceof PanelRepeaterGridItem) {
|
||||
panels = panels.concat(panelRepeaterToPanels(child, isSnapshot));
|
||||
if (child instanceof DashboardGridItem) {
|
||||
// handle panel repeater scenatio
|
||||
if (child.state.variableName) {
|
||||
panels = panels.concat(panelRepeaterToPanels(child, isSnapshot));
|
||||
} else {
|
||||
panels.push(gridItemToPanel(child, isSnapshot));
|
||||
}
|
||||
}
|
||||
|
||||
if (child instanceof SceneGridRow) {
|
||||
@ -155,62 +155,47 @@ export function libraryVizPanelToPanel(libPanel: LibraryVizPanel, gridPos: GridP
|
||||
} as Panel;
|
||||
}
|
||||
|
||||
export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false): Panel {
|
||||
export function gridItemToPanel(gridItem: DashboardGridItem, isSnapshot = false): Panel {
|
||||
let vizPanel: VizPanel | undefined;
|
||||
let x = 0,
|
||||
y = 0,
|
||||
w = 0,
|
||||
h = 0;
|
||||
|
||||
if (gridItem instanceof SceneGridItem) {
|
||||
// Handle library panels, early exit
|
||||
if (gridItem.state.body instanceof LibraryVizPanel) {
|
||||
x = gridItem.state.x ?? 0;
|
||||
y = gridItem.state.y ?? 0;
|
||||
w = gridItem.state.width ?? 0;
|
||||
h = gridItem.state.height ?? 0;
|
||||
|
||||
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)) {
|
||||
throw new Error('SceneGridItem body expected to be VizPanel');
|
||||
}
|
||||
|
||||
vizPanel = gridItem.state.body;
|
||||
x = gridItem.state.x ?? 0;
|
||||
y = gridItem.state.y ?? 0;
|
||||
w = gridItem.state.width ?? 0;
|
||||
h = gridItem.state.height ?? 0;
|
||||
}
|
||||
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
// Handle library panels, early exit
|
||||
if (gridItem.state.body instanceof LibraryVizPanel) {
|
||||
x = gridItem.state.x ?? 0;
|
||||
y = gridItem.state.y ?? 0;
|
||||
w = gridItem.state.width ?? 0;
|
||||
h = gridItem.state.height ?? 0;
|
||||
|
||||
if (gridItem.state.source instanceof LibraryVizPanel) {
|
||||
return libraryVizPanelToPanel(gridItem.state.source, { x, y, w, h });
|
||||
} else {
|
||||
vizPanel = gridItem.state.source;
|
||||
}
|
||||
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)) {
|
||||
throw new Error('DashboardGridItem body expected to be VizPanel');
|
||||
}
|
||||
|
||||
vizPanel = gridItem.state.body;
|
||||
x = gridItem.state.x ?? 0;
|
||||
y = gridItem.state.y ?? 0;
|
||||
w = gridItem.state.width ?? 0;
|
||||
h = gridItem.state.height ?? 0;
|
||||
|
||||
if (!vizPanel) {
|
||||
throw new Error('Unsupported grid item type');
|
||||
}
|
||||
@ -247,10 +232,17 @@ export function vizPanelToPanel(
|
||||
panel.hideTimeOverride = panelTime.state.hideTimeOverride;
|
||||
}
|
||||
|
||||
if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
panel.repeat = gridItem.state.variableName;
|
||||
panel.maxPerRow = gridItem.state.maxPerRow;
|
||||
panel.repeatDirection = gridItem.getRepeatDirection();
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
if (gridItem.state.variableName) {
|
||||
panel.repeat = gridItem.state.variableName;
|
||||
}
|
||||
|
||||
if (gridItem.state.maxPerRow) {
|
||||
panel.maxPerRow = gridItem.state.maxPerRow;
|
||||
}
|
||||
if (gridItem.state.repeatDirection) {
|
||||
panel.repeatDirection = gridItem.getRepeatDirection();
|
||||
}
|
||||
}
|
||||
|
||||
const panelLinks = dashboardSceneGraph.getPanelLinks(vizPanel);
|
||||
@ -322,15 +314,16 @@ function vizPanelDataToPanel(
|
||||
return panel;
|
||||
}
|
||||
|
||||
export function panelRepeaterToPanels(repeater: PanelRepeaterGridItem, isSnapshot = false): Panel[] {
|
||||
export function panelRepeaterToPanels(repeater: DashboardGridItem, isSnapshot = false): Panel[] {
|
||||
if (!isSnapshot) {
|
||||
return [gridItemToPanel(repeater)];
|
||||
} else {
|
||||
if (repeater.state.source instanceof LibraryVizPanel) {
|
||||
if (repeater.state.body instanceof LibraryVizPanel) {
|
||||
const { x = 0, y = 0, width: w = 0, height: h = 0 } = repeater.state;
|
||||
return [libraryVizPanelToPanel(repeater.state.source, { x, y, w, h })];
|
||||
return [libraryVizPanelToPanel(repeater.state.body, { x, y, w, h })];
|
||||
}
|
||||
|
||||
// console.log('repeater.state', repeater.state);
|
||||
if (repeater.state.repeatedPanels) {
|
||||
const itemHeight = repeater.state.itemHeight ?? 10;
|
||||
const rowCount = Math.ceil(repeater.state.repeatedPanels!.length / repeater.getMaxPerRow());
|
||||
@ -427,16 +420,23 @@ export function gridRowToSaveModel(gridRow: SceneGridRow, panelsArray: Array<Pan
|
||||
|
||||
if (isSnapshot) {
|
||||
gridRow.state.children.forEach((c) => {
|
||||
if (c instanceof PanelRepeaterGridItem) {
|
||||
// Perform snapshot only for uncollapsed rows
|
||||
panelsInsideRow = panelsInsideRow.concat(panelRepeaterToPanels(c, !collapsed));
|
||||
} else {
|
||||
// Perform snapshot only for uncollapsed panels
|
||||
panelsInsideRow.push(gridItemToPanel(c, !collapsed));
|
||||
if (c instanceof DashboardGridItem) {
|
||||
if (c.state.variableName) {
|
||||
// Perform snapshot only for uncollapsed rows
|
||||
panelsInsideRow = panelsInsideRow.concat(panelRepeaterToPanels(c, !collapsed));
|
||||
} else {
|
||||
// Perform snapshot only for uncollapsed panels
|
||||
panelsInsideRow.push(gridItemToPanel(c, !collapsed));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
panelsInsideRow = gridRow.state.children.map((c) => gridItemToPanel(c));
|
||||
panelsInsideRow = gridRow.state.children.map((c) => {
|
||||
if (!(c instanceof DashboardGridItem)) {
|
||||
throw new Error('Row child expected to be DashboardGridItem');
|
||||
}
|
||||
return gridItemToPanel(c);
|
||||
});
|
||||
}
|
||||
|
||||
if (gridRow.state.isCollapsed) {
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { map, of } from 'rxjs';
|
||||
|
||||
import { AnnotationQuery, DataQueryRequest, DataSourceApi, LoadingState, PanelData } from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import { SceneDataLayers, SceneGridItem, SceneGridLayout, SceneTimeRange, VizPanel, dataLayers } from '@grafana/scenes';
|
||||
import { SceneDataLayers, SceneGridLayout, SceneTimeRange, dataLayers } from '@grafana/scenes';
|
||||
|
||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
@ -47,11 +45,6 @@ jest.mock('@grafana/runtime', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
getPanelPluginFromCache: (id: string) => undefined,
|
||||
});
|
||||
|
||||
describe('AnnotationsEditView', () => {
|
||||
describe('Dashboard annotations state', () => {
|
||||
let annotationsView: AnnotationsEditView;
|
||||
@ -189,20 +182,7 @@ async function buildTestScene() {
|
||||
],
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
children: [],
|
||||
}),
|
||||
editview: annotationsView,
|
||||
});
|
||||
|
@ -2,9 +2,7 @@ import { render as RTLRender } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, SceneTimeRange, VizPanel, behaviors } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneTimeRange, behaviors } from '@grafana/scenes';
|
||||
import { DashboardCursorSync } from '@grafana/schema';
|
||||
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
@ -25,11 +23,6 @@ jest.mock('react-router-dom', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
getPanelPluginFromCache: (id: string) => undefined,
|
||||
});
|
||||
|
||||
function render(component: React.ReactNode) {
|
||||
return RTLRender(<TestProvider>{component}</TestProvider>);
|
||||
}
|
||||
@ -231,20 +224,7 @@ async function buildTestScene() {
|
||||
canEdit: true,
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
children: [],
|
||||
}),
|
||||
editview: settings,
|
||||
});
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import { behaviors, SceneGridLayout, SceneGridItem, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { behaviors, SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
|
||||
import { DashboardCursorSync } from '@grafana/schema';
|
||||
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
@ -9,11 +7,6 @@ import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
import { GeneralSettingsEditView } from './GeneralSettingsEditView';
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
getPanelPluginFromCache: (id: string) => undefined,
|
||||
});
|
||||
|
||||
describe('GeneralSettingsEditView', () => {
|
||||
describe('Dashboard state', () => {
|
||||
let dashboard: DashboardScene;
|
||||
@ -129,20 +122,7 @@ async function buildTestScene() {
|
||||
canEdit: true,
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
children: [],
|
||||
}),
|
||||
editview: settings,
|
||||
});
|
||||
|
@ -1,17 +1,10 @@
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
import { PermissionsEditView } from './PermissionsEditView';
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
getPanelPluginFromCache: (id: string) => undefined,
|
||||
});
|
||||
|
||||
describe('PermissionsEditView', () => {
|
||||
describe('Dashboard permissions state', () => {
|
||||
let dashboard: DashboardScene;
|
||||
@ -44,20 +37,7 @@ async function buildTestScene() {
|
||||
canEdit: true,
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
children: [],
|
||||
}),
|
||||
editview: permissionsView,
|
||||
});
|
||||
|
@ -13,7 +13,6 @@ import { setPluginImportUtils, setRunRequest } from '@grafana/runtime';
|
||||
import {
|
||||
SceneVariableSet,
|
||||
CustomVariable,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
VizPanel,
|
||||
AdHocFiltersVariable,
|
||||
@ -23,6 +22,7 @@ import {
|
||||
import { mockDataSource } from 'app/features/alerting/unified/mocks';
|
||||
import { LegacyVariableQueryEditor } from 'app/features/variables/editor/LegacyVariableQueryEditor';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
|
||||
@ -289,7 +289,7 @@ describe('VariablesEditView', () => {
|
||||
// Uses function to avoid store reference to previous existing variables
|
||||
const getSourceVariable = () => variableView.getVariables()[0] as CustomVariable;
|
||||
const getDependantPanel = () =>
|
||||
((dashboard.state.body as SceneGridLayout).state.children[0] as SceneGridItem).state.body as VizPanel;
|
||||
((dashboard.state.body as SceneGridLayout).state.children[0] as DashboardGridItem).state.body as VizPanel;
|
||||
|
||||
expect(getSourceVariable().getValue()).toBe('test');
|
||||
// Using description to get the interpolated value
|
||||
@ -344,7 +344,7 @@ async function buildTestScene() {
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { activateFullSceneTree } from '../utils/test-utils';
|
||||
@ -10,11 +8,6 @@ import { historySrv } from './version-history';
|
||||
|
||||
jest.mock('./version-history/HistorySrv');
|
||||
|
||||
setPluginImportUtils({
|
||||
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
|
||||
getPanelPluginFromCache: (id: string) => undefined,
|
||||
});
|
||||
|
||||
describe('VersionsEditView', () => {
|
||||
describe('Dashboard versions state', () => {
|
||||
let dashboard: DashboardScene;
|
||||
@ -170,20 +163,7 @@ async function buildTestScene() {
|
||||
canEdit: true,
|
||||
},
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 12,
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
children: [],
|
||||
}),
|
||||
editview: versionsView,
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
import { SceneComponentProps, SceneGridItem, SceneObjectBase, SceneObjectRef, VizPanel } from '@grafana/scenes';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectRef, VizPanel } from '@grafana/scenes';
|
||||
import { t } from 'app/core/internationalization';
|
||||
import { ShareLibraryPanel } from 'app/features/dashboard/components/ShareModal/ShareLibraryPanel';
|
||||
import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { gridItemToPanel, transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel';
|
||||
|
||||
import { SceneShareTabState } from './types';
|
||||
@ -35,7 +35,7 @@ function ShareLibraryPanelTabRenderer({ model }: SceneComponentProps<ShareLibrar
|
||||
|
||||
const vizPanel = panelRef.resolve();
|
||||
|
||||
if (vizPanel.parent instanceof SceneGridItem || vizPanel.parent instanceof PanelRepeaterGridItem) {
|
||||
if (vizPanel.parent instanceof DashboardGridItem) {
|
||||
const dashboardScene = dashboardRef.resolve();
|
||||
const panelJson = gridItemToPanel(vizPanel.parent);
|
||||
const panelModel = new PanelModel(panelJson);
|
||||
|
@ -6,8 +6,9 @@ import React from 'react';
|
||||
import { dateTime } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { SceneGridItem, SceneGridLayout, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridLayout, SceneTimeRange, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
|
||||
import { ShareLinkTab } from './ShareLinkTab';
|
||||
@ -105,7 +106,7 @@ function buildAndRenderScenario(options: ScenarioOptions) {
|
||||
$timeRange: new SceneTimeRange({}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -8,6 +8,7 @@ import { t } from 'app/core/internationalization';
|
||||
import { isPublicDashboardsEnabled } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { DashboardInteractions } from '../utils/interactions';
|
||||
import { getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
@ -56,9 +57,12 @@ export class ShareModal extends SceneObjectBase<ShareModalState> implements Moda
|
||||
|
||||
if (panelRef) {
|
||||
tabs.push(new SharePanelEmbedTab({ panelRef, dashboardRef }));
|
||||
|
||||
if (panelRef.resolve() instanceof VizPanel) {
|
||||
tabs.push(new ShareLibraryPanelTab({ panelRef, dashboardRef, modalRef: this.getRef() }));
|
||||
const panel = panelRef.resolve();
|
||||
const isLibraryPanel = panel.parent instanceof LibraryVizPanel;
|
||||
if (panel instanceof VizPanel) {
|
||||
if (!isLibraryPanel) {
|
||||
tabs.push(new ShareLibraryPanelTab({ panelRef, dashboardRef, modalRef: this.getRef() }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ import { DataSourceWithBackend } from '@grafana/runtime';
|
||||
import {
|
||||
SceneGridItemLike,
|
||||
VizPanel,
|
||||
SceneGridItem,
|
||||
SceneQueryRunner,
|
||||
SceneDataTransformer,
|
||||
SceneGridLayout,
|
||||
@ -11,9 +10,9 @@ import {
|
||||
import { supportedDatasources } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SupportedPubdashDatasources';
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
|
||||
import { DashboardGridItem } from '../../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../../scene/LibraryVizPanel';
|
||||
import { PanelRepeaterGridItem } from '../../scene/PanelRepeaterGridItem';
|
||||
|
||||
export const getUnsupportedDashboardDatasources = async (types: string[]): Promise<string[]> => {
|
||||
let unsupportedDS = new Set<string>();
|
||||
@ -41,7 +40,7 @@ export function getPanelDatasourceTypes(scene: DashboardScene): string[] {
|
||||
}
|
||||
|
||||
for (const child of body.state.children) {
|
||||
if (child instanceof SceneGridItem) {
|
||||
if (child instanceof DashboardGridItem) {
|
||||
const ts = panelDatasourceTypes(child);
|
||||
for (const t of ts) {
|
||||
types.add(t);
|
||||
@ -66,16 +65,15 @@ function rowTypes(gridRow: SceneGridRow) {
|
||||
|
||||
function panelDatasourceTypes(gridItem: SceneGridItemLike) {
|
||||
let vizPanel: VizPanel | LibraryVizPanel | undefined;
|
||||
if (gridItem instanceof SceneGridItem) {
|
||||
|
||||
if (gridItem instanceof DashboardGridItem) {
|
||||
if (gridItem.state.body instanceof LibraryVizPanel) {
|
||||
vizPanel = gridItem.state.body.state.panel;
|
||||
} else if (gridItem.state.body instanceof VizPanel) {
|
||||
vizPanel = gridItem.state.body;
|
||||
} else {
|
||||
throw new Error('SceneGridItem body expected to be VizPanel');
|
||||
throw new Error('DashboardGridItem body expected to be VizPanel');
|
||||
}
|
||||
} else if (gridItem instanceof PanelRepeaterGridItem) {
|
||||
vizPanel = gridItem.state.source;
|
||||
}
|
||||
|
||||
if (!vizPanel) {
|
||||
|
@ -2,8 +2,8 @@ import { useState, useEffect } from 'react';
|
||||
|
||||
import { VizPanel, SceneObject, SceneGridRow, getUrlSyncManager } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
import { DashboardRepeatsProcessedEvent } from '../scene/types';
|
||||
import { findVizPanelByKey, isPanelClone } from '../utils/utils';
|
||||
@ -64,7 +64,7 @@ function findRepeatClone(dashboard: DashboardScene, panelId: string): Promise<Vi
|
||||
|
||||
function activateAllRepeaters(layout: SceneObject) {
|
||||
layout.forEachChild((child) => {
|
||||
if (child instanceof PanelRepeaterGridItem && !child.isActive) {
|
||||
if (child instanceof DashboardGridItem && !child.isActive) {
|
||||
child.activate();
|
||||
return;
|
||||
}
|
||||
@ -77,7 +77,7 @@ function activateAllRepeaters(layout: SceneObject) {
|
||||
}
|
||||
}
|
||||
|
||||
// Activate any panel PanelRepeaterGridItem inside the row
|
||||
// Activate any panel DashboardGridItem inside the row
|
||||
activateAllRepeaters(child);
|
||||
}
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { TimeRangeUpdatedEvent } from '@grafana/runtime';
|
||||
import {
|
||||
behaviors,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneQueryRunner,
|
||||
SceneTimeRange,
|
||||
@ -15,6 +14,7 @@ import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
|
||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { NEW_LINK } from '../settings/links/utils';
|
||||
|
||||
@ -175,7 +175,7 @@ function setup() {
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -189,7 +189,7 @@ function setup() {
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel with no queries',
|
||||
key: 'panel-2',
|
||||
@ -197,7 +197,7 @@ function setup() {
|
||||
}),
|
||||
}),
|
||||
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel with a shared query',
|
||||
key: 'panel-3',
|
||||
@ -210,7 +210,7 @@ function setup() {
|
||||
}),
|
||||
}),
|
||||
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel with a regular data source query and transformations',
|
||||
key: 'panel-4',
|
||||
@ -225,7 +225,7 @@ function setup() {
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel with a shared query and transformations',
|
||||
key: 'panel-4',
|
||||
|
@ -6,13 +6,13 @@ import {
|
||||
behaviors,
|
||||
SceneDataLayers,
|
||||
sceneGraph,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObject,
|
||||
VizPanel,
|
||||
} from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { dataLayersToAnnotations } from '../serialization/dataLayersToAnnotations';
|
||||
|
||||
@ -176,8 +176,8 @@ export class DashboardModelCompatibilityWrapper {
|
||||
}
|
||||
|
||||
const gridItem = vizPanel.parent;
|
||||
if (!(gridItem instanceof SceneGridItem)) {
|
||||
console.error('Trying to remove a panel that is not wrapped in SceneGridItem');
|
||||
if (!(gridItem instanceof DashboardGridItem)) {
|
||||
console.error('Trying to remove a panel that is not wrapped in DashboardGridItem');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import {
|
||||
SceneDataLayers,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneQueryRunner,
|
||||
@ -13,10 +12,10 @@ import { DashboardCursorSync } from '@grafana/schema';
|
||||
import { AlertStatesDataLayer } from '../scene/AlertStatesDataLayer';
|
||||
import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer';
|
||||
import { DashboardControls } from '../scene/DashboardControls';
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
|
||||
import { dashboardSceneGraph, getNextPanelId } from './dashboardSceneGraph';
|
||||
import { findVizPanelByKey } from './utils';
|
||||
@ -94,21 +93,21 @@ describe('dashboardSceneGraph', () => {
|
||||
const scene = buildTestScene({
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel A',
|
||||
key: 'panel-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
key: 'panel-2',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel C',
|
||||
key: 'panel-3',
|
||||
@ -128,7 +127,7 @@ describe('dashboardSceneGraph', () => {
|
||||
const scene = buildTestScene({
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -137,7 +136,7 @@ describe('dashboardSceneGraph', () => {
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'LibPanel',
|
||||
@ -145,15 +144,15 @@ describe('dashboardSceneGraph', () => {
|
||||
panelKey: 'panel-2',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel C',
|
||||
key: 'panel-2-clone-1',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new PanelRepeaterGridItem({
|
||||
source: new VizPanel({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel C',
|
||||
key: 'panel-4',
|
||||
pluginId: 'table',
|
||||
@ -167,14 +166,14 @@ describe('dashboardSceneGraph', () => {
|
||||
key: 'key',
|
||||
title: 'row',
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel E',
|
||||
key: 'panel-2-clone-2',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new LibraryVizPanel({
|
||||
uid: 'uid',
|
||||
name: 'LibPanel',
|
||||
@ -264,7 +263,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
}),
|
||||
body: new SceneGridLayout({
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
key: 'griditem-1',
|
||||
x: 0,
|
||||
body: new VizPanel({
|
||||
@ -274,14 +273,14 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel B',
|
||||
key: 'panel-2',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel C',
|
||||
key: 'panel-2-clone-1',
|
||||
@ -289,7 +288,7 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
$data: new SceneQueryRunner({ key: 'data-query-runner2', queries: [{ refId: 'A' }] }),
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel D',
|
||||
key: 'panel-with-links',
|
||||
@ -302,14 +301,14 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
|
||||
key: 'key',
|
||||
title: 'row',
|
||||
children: [
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel E',
|
||||
key: 'panel-2-clone-2',
|
||||
pluginId: 'table',
|
||||
}),
|
||||
}),
|
||||
new SceneGridItem({
|
||||
new DashboardGridItem({
|
||||
body: new VizPanel({
|
||||
title: 'Panel F',
|
||||
key: 'panel-2-clone-2',
|
||||
|
@ -1,17 +1,9 @@
|
||||
import {
|
||||
VizPanel,
|
||||
SceneGridItem,
|
||||
SceneGridRow,
|
||||
SceneDataLayers,
|
||||
sceneGraph,
|
||||
SceneGridLayout,
|
||||
behaviors,
|
||||
} from '@grafana/scenes';
|
||||
import { VizPanel, SceneGridRow, SceneDataLayers, sceneGraph, SceneGridLayout, behaviors } from '@grafana/scenes';
|
||||
|
||||
import { DashboardGridItem } from '../scene/DashboardGridItem';
|
||||
import { DashboardScene } from '../scene/DashboardScene';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { VizPanelLinks } from '../scene/PanelLinks';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
|
||||
import { getPanelIdForLibraryVizPanel, getPanelIdForVizPanel } from './utils';
|
||||
|
||||
@ -39,13 +31,17 @@ function getVizPanels(scene: DashboardScene): VizPanel[] {
|
||||
const panels: VizPanel[] = [];
|
||||
|
||||
scene.state.body.forEachChild((child) => {
|
||||
if (child instanceof SceneGridItem) {
|
||||
if (!(child instanceof DashboardGridItem) && !(child instanceof SceneGridRow)) {
|
||||
throw new Error('Child is not a DashboardGridItem or SceneGridRow, invalid scene');
|
||||
}
|
||||
|
||||
if (child instanceof DashboardGridItem) {
|
||||
if (child.state.body instanceof VizPanel) {
|
||||
panels.push(child.state.body);
|
||||
}
|
||||
} else if (child instanceof SceneGridRow) {
|
||||
child.forEachChild((child) => {
|
||||
if (child instanceof SceneGridItem) {
|
||||
if (child instanceof DashboardGridItem) {
|
||||
if (child.state.body instanceof VizPanel) {
|
||||
panels.push(child.state.body);
|
||||
}
|
||||
@ -86,22 +82,7 @@ export function getNextPanelId(dashboard: DashboardScene): number {
|
||||
}
|
||||
|
||||
for (const child of body.state.children) {
|
||||
if (child instanceof PanelRepeaterGridItem) {
|
||||
const vizPanel = child.state.source;
|
||||
|
||||
if (vizPanel) {
|
||||
const panelId =
|
||||
vizPanel instanceof LibraryVizPanel
|
||||
? getPanelIdForLibraryVizPanel(vizPanel)
|
||||
: getPanelIdForVizPanel(vizPanel);
|
||||
|
||||
if (panelId > max) {
|
||||
max = panelId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (child instanceof SceneGridItem) {
|
||||
if (child instanceof DashboardGridItem) {
|
||||
const vizPanel = child.state.body;
|
||||
|
||||
if (vizPanel) {
|
||||
@ -125,7 +106,7 @@ export function getNextPanelId(dashboard: DashboardScene): number {
|
||||
}
|
||||
|
||||
for (const rowChild of child.state.children) {
|
||||
if (rowChild instanceof SceneGridItem) {
|
||||
if (rowChild instanceof DashboardGridItem) {
|
||||
const vizPanel = rowChild.state.body;
|
||||
|
||||
if (vizPanel) {
|
||||
@ -152,8 +133,8 @@ export const getLibraryVizPanelFromVizPanel = (vizPanel: VizPanel): LibraryVizPa
|
||||
return vizPanel.parent;
|
||||
}
|
||||
|
||||
if (vizPanel.parent instanceof PanelRepeaterGridItem && vizPanel.parent.state.source instanceof LibraryVizPanel) {
|
||||
return vizPanel.parent.state.source;
|
||||
if (vizPanel.parent instanceof DashboardGridItem && vizPanel.parent.state.body instanceof LibraryVizPanel) {
|
||||
return vizPanel.parent.state.body;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -2,7 +2,6 @@ import {
|
||||
DeepPartial,
|
||||
EmbeddedScene,
|
||||
SceneDeactivationHandler,
|
||||
SceneGridItem,
|
||||
SceneGridLayout,
|
||||
SceneGridRow,
|
||||
SceneObject,
|
||||
@ -15,9 +14,9 @@ import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboar
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
import { DashboardGridItem, RepeatDirection } from '../scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
|
||||
import { PanelRepeaterGridItem, RepeatDirection } from '../scene/PanelRepeaterGridItem';
|
||||
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
||||
|
||||
export function setupLoadDashboardMock(rsp: DeepPartial<DashboardDTO>, spy?: jest.Mock) {
|
||||
@ -103,13 +102,13 @@ interface SceneOptions {
|
||||
export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel | LibraryVizPanel) {
|
||||
const defaults = { usePanelRepeater: true, ...options };
|
||||
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
const withRepeat = new DashboardGridItem({
|
||||
variableName: 'server',
|
||||
repeatedPanels: [],
|
||||
repeatDirection: options.repeatDirection,
|
||||
maxPerRow: options.maxPerRow,
|
||||
itemHeight: options.itemHeight,
|
||||
source:
|
||||
body:
|
||||
source ??
|
||||
new VizPanel({
|
||||
title: 'Panel $server',
|
||||
@ -119,7 +118,7 @@ export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel
|
||||
y: options.y || 0,
|
||||
});
|
||||
|
||||
const gridItem = new SceneGridItem({
|
||||
const withoutRepeat = new DashboardGridItem({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
@ -131,7 +130,7 @@ export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel
|
||||
}),
|
||||
});
|
||||
|
||||
const rowChildren = defaults.usePanelRepeater ? repeater : gridItem;
|
||||
const rowChildren = defaults.usePanelRepeater ? withRepeat : withoutRepeat;
|
||||
|
||||
const row = new SceneGridRow({
|
||||
$behaviors: defaults.useRowRepeater
|
||||
@ -189,5 +188,5 @@ export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel
|
||||
}),
|
||||
});
|
||||
|
||||
return { scene, repeater, row, variable: panelRepeatVariable };
|
||||
return { scene, repeater: withRepeat, row, variable: panelRepeatVariable };
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import { defaultDashboard } from '@grafana/schema';
|
||||
import { DashboardModel } from 'app/features/dashboard/state';
|
||||
import { DashboardGridItem } from 'app/features/dashboard-scene/scene/DashboardGridItem';
|
||||
import { LibraryVizPanel } from 'app/features/dashboard-scene/scene/LibraryVizPanel';
|
||||
import { vizPanelToPanel } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModel';
|
||||
|
||||
@ -138,12 +139,29 @@ export async function getConnectedDashboards(uid: string): Promise<DashboardSear
|
||||
|
||||
export function libraryVizPanelToSaveModel(libraryPanel: LibraryVizPanel) {
|
||||
const { panel, uid, name, _loadedPanel } = libraryPanel.state;
|
||||
|
||||
const gridItem = libraryPanel.parent;
|
||||
|
||||
if (!gridItem || !(gridItem instanceof DashboardGridItem)) {
|
||||
throw new Error('LibraryVizPanel must be a child of DashboardGridItem');
|
||||
}
|
||||
|
||||
const saveModel = {
|
||||
uid,
|
||||
folderUID: _loadedPanel?.folderUid,
|
||||
name,
|
||||
version: _loadedPanel?.version || 0,
|
||||
model: vizPanelToPanel(panel!),
|
||||
model: vizPanelToPanel(
|
||||
panel!,
|
||||
{
|
||||
x: gridItem.state.x ?? 0,
|
||||
y: gridItem.state.y ?? 0,
|
||||
w: gridItem.state.width ?? 0,
|
||||
h: gridItem.state.height ?? 0,
|
||||
},
|
||||
false,
|
||||
gridItem
|
||||
),
|
||||
kind: LibraryElementKind.Panel,
|
||||
};
|
||||
return saveModel;
|
||||
@ -151,6 +169,8 @@ export function libraryVizPanelToSaveModel(libraryPanel: LibraryVizPanel) {
|
||||
|
||||
export async function updateLibraryVizPanel(libraryPanel: LibraryVizPanel): Promise<LibraryElementDTO> {
|
||||
const { uid, folderUID, name, model, version, kind } = libraryVizPanelToSaveModel(libraryPanel);
|
||||
|
||||
console.log('updateLibraryVizPanel', model);
|
||||
const { result } = await getBackendSrv().patch(`/api/library-elements/${uid}`, {
|
||||
folderUID,
|
||||
name,
|
||||
|
Loading…
Reference in New Issue
Block a user