2023-09-11 18:02:04 +08:00
|
|
|
import { SceneGridItem, SceneGridItemLike, SceneGridLayout, SceneGridRow, VizPanel } from '@grafana/scenes';
|
|
|
|
import { Dashboard, defaultDashboard, FieldConfigSource, Panel, RowPanel } from '@grafana/schema';
|
2023-08-29 20:17:55 +08:00
|
|
|
import { sortedDeepCloneWithoutNulls } from 'app/core/utils/object';
|
|
|
|
|
|
|
|
import { DashboardScene } from '../scene/DashboardScene';
|
2023-09-05 19:51:46 +08:00
|
|
|
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
2023-09-01 16:21:41 +08:00
|
|
|
import { PanelTimeRange } from '../scene/PanelTimeRange';
|
2023-09-11 18:02:04 +08:00
|
|
|
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
|
2023-08-30 16:09:47 +08:00
|
|
|
import { getPanelIdForVizPanel } from '../utils/utils';
|
2023-08-29 20:17:55 +08:00
|
|
|
|
|
|
|
export function transformSceneToSaveModel(scene: DashboardScene): Dashboard {
|
|
|
|
const state = scene.state;
|
|
|
|
const timeRange = state.$timeRange!.state;
|
|
|
|
const body = state.body;
|
|
|
|
const panels: Panel[] = [];
|
|
|
|
|
|
|
|
if (body instanceof SceneGridLayout) {
|
|
|
|
for (const child of body.state.children) {
|
|
|
|
if (child instanceof SceneGridItem) {
|
|
|
|
panels.push(gridItemToPanel(child));
|
|
|
|
}
|
2023-09-11 18:02:04 +08:00
|
|
|
|
|
|
|
if (child instanceof SceneGridRow) {
|
|
|
|
// Skip repeat clones
|
|
|
|
if (child.state.key!.indexOf('-clone-') > 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
gridRowToSaveModel(child, panels);
|
|
|
|
}
|
2023-08-29 20:17:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const dashboard: Dashboard = {
|
|
|
|
...defaultDashboard,
|
|
|
|
title: state.title,
|
|
|
|
uid: state.uid,
|
|
|
|
time: {
|
|
|
|
from: timeRange.from,
|
|
|
|
to: timeRange.to,
|
|
|
|
},
|
|
|
|
panels,
|
|
|
|
};
|
|
|
|
|
|
|
|
return sortedDeepCloneWithoutNulls(dashboard);
|
|
|
|
}
|
|
|
|
|
2023-09-05 19:51:46 +08:00
|
|
|
export function gridItemToPanel(gridItem: SceneGridItemLike): Panel {
|
|
|
|
let vizPanel: VizPanel | undefined;
|
|
|
|
let x = 0,
|
|
|
|
y = 0,
|
|
|
|
w = 0,
|
|
|
|
h = 0;
|
|
|
|
|
|
|
|
if (gridItem instanceof SceneGridItem) {
|
|
|
|
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) {
|
|
|
|
vizPanel = gridItem.state.source;
|
|
|
|
|
|
|
|
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');
|
2023-08-29 20:17:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const panel: Panel = {
|
2023-08-30 16:09:47 +08:00
|
|
|
id: getPanelIdForVizPanel(vizPanel),
|
2023-08-29 20:17:55 +08:00
|
|
|
type: vizPanel.state.pluginId,
|
|
|
|
title: vizPanel.state.title,
|
2023-09-05 19:51:46 +08:00
|
|
|
gridPos: { x, y, w, h },
|
2023-08-29 20:17:55 +08:00
|
|
|
options: vizPanel.state.options,
|
|
|
|
fieldConfig: (vizPanel.state.fieldConfig as FieldConfigSource) ?? { defaults: {}, overrides: [] },
|
|
|
|
transformations: [],
|
|
|
|
transparent: false,
|
|
|
|
};
|
|
|
|
|
2023-09-01 16:21:41 +08:00
|
|
|
const panelTime = vizPanel.state.$timeRange;
|
|
|
|
|
|
|
|
if (panelTime instanceof PanelTimeRange) {
|
|
|
|
panel.timeFrom = panelTime.state.timeFrom;
|
|
|
|
panel.timeShift = panelTime.state.timeShift;
|
|
|
|
panel.hideTimeOverride = panelTime.state.hideTimeOverride;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vizPanel.state.displayMode === 'transparent') {
|
|
|
|
panel.transparent = true;
|
|
|
|
}
|
|
|
|
|
2023-09-05 19:51:46 +08:00
|
|
|
if (gridItem instanceof PanelRepeaterGridItem) {
|
|
|
|
panel.repeat = gridItem.state.variableName;
|
|
|
|
panel.maxPerRow = gridItem.state.maxPerRow;
|
|
|
|
panel.repeatDirection = gridItem.getRepeatDirection();
|
|
|
|
}
|
|
|
|
|
2023-08-29 20:17:55 +08:00
|
|
|
return panel;
|
|
|
|
}
|
2023-09-11 18:02:04 +08:00
|
|
|
|
|
|
|
export function gridRowToSaveModel(gridRow: SceneGridRow, panelsArray: Array<Panel | RowPanel>) {
|
|
|
|
const rowPanel: RowPanel = {
|
|
|
|
type: 'row',
|
|
|
|
id: getPanelIdForVizPanel(gridRow),
|
|
|
|
title: gridRow.state.title,
|
|
|
|
gridPos: {
|
|
|
|
x: gridRow.state.x ?? 0,
|
|
|
|
y: gridRow.state.y ?? 0,
|
|
|
|
w: gridRow.state.width ?? 24,
|
|
|
|
h: gridRow.state.height ?? 1,
|
|
|
|
},
|
|
|
|
collapsed: Boolean(gridRow.state.isCollapsed),
|
|
|
|
panels: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
if (gridRow.state.$behaviors?.length) {
|
|
|
|
const behavior = gridRow.state.$behaviors[0];
|
|
|
|
|
|
|
|
if (behavior instanceof RowRepeaterBehavior) {
|
|
|
|
rowPanel.repeat = behavior.state.variableName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
panelsArray.push(rowPanel);
|
|
|
|
|
|
|
|
const panelsInsideRow = gridRow.state.children.map(gridItemToPanel);
|
|
|
|
|
|
|
|
if (gridRow.state.isCollapsed) {
|
|
|
|
rowPanel.panels = panelsInsideRow;
|
|
|
|
} else {
|
|
|
|
panelsArray.push(...panelsInsideRow);
|
|
|
|
}
|
|
|
|
}
|