Dynamic dashboards: Persist library panels in responsive grid (#101802)

* persist library panels in responsive grid

* small refactoring of old grid

* remove unused imports
pull/102016/head
Oscar Kilhed 2 months ago committed by GitHub
parent ee23a7a7d9
commit 8de665cbeb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 99
      public/app/features/dashboard-scene/serialization/layoutSerializers/DefaultGridLayoutSerializer.ts
  2. 7
      public/app/features/dashboard-scene/serialization/layoutSerializers/ResponsiveGridLayoutSerializer.ts
  3. 52
      public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts

@ -1,13 +1,4 @@
import { config } from '@grafana/runtime';
import {
SceneGridItemLike,
SceneGridLayout,
SceneGridRow,
SceneObject,
VizPanel,
VizPanelMenu,
VizPanelState,
} from '@grafana/scenes';
import { SceneGridItemLike, SceneGridLayout, SceneGridRow, SceneObject, VizPanel } from '@grafana/scenes';
import {
DashboardV2Spec,
GridLayoutItemKind,
@ -21,23 +12,17 @@ import {
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
import { contextSrv } from 'app/core/core';
import { LibraryPanelBehavior } from '../../scene/LibraryPanelBehavior';
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
import { panelLinksBehavior, panelMenuBehavior } from '../../scene/PanelMenuBehavior';
import { PanelNotices } from '../../scene/PanelNotices';
import { AngularDeprecation } from '../../scene/angular/AngularDeprecation';
import { DashboardGridItem } from '../../scene/layout-default/DashboardGridItem';
import { DefaultGridLayoutManager } from '../../scene/layout-default/DefaultGridLayoutManager';
import { RowRepeaterBehavior } from '../../scene/layout-default/RowRepeaterBehavior';
import { RowActions } from '../../scene/layout-default/row-actions/RowActions';
import { setDashboardPanelContext } from '../../scene/setDashboardPanelContext';
import { DashboardLayoutManager, LayoutManagerSerializer } from '../../scene/types/DashboardLayoutManager';
import { getOriginalKey, isClonedKey } from '../../utils/clone';
import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph';
import { calculateGridItemDimensions, getVizPanelKeyForPanelId, isLibraryPanel } from '../../utils/utils';
import { calculateGridItemDimensions, isLibraryPanel } from '../../utils/utils';
import { GRID_ROW_HEIGHT } from '../const';
import { buildVizPanel } from './utils';
import { buildLibraryPanel, buildVizPanel } from './utils';
export class DefaultGridLayoutManagerSerializer implements LayoutManagerSerializer {
serialize(layoutManager: DefaultGridLayoutManager, isSnapshot?: boolean): DashboardV2Spec['layout'] {
@ -248,28 +233,11 @@ function createSceneGridLayoutForItems(layout: GridLayoutKind, elements: Record<
if (!panel) {
throw new Error(`Panel with uid ${element.spec.element.name} not found in the dashboard elements`);
}
if (panel.kind === 'Panel') {
return buildGridItem(element.spec, panel);
} else if (panel.kind === 'LibraryPanel') {
const libraryPanel = buildLibraryPanel(panel);
return new DashboardGridItem({
key: `grid-item-${panel.spec.id}`,
x: element.spec.x,
y: element.spec.y,
width: element.spec.width,
height: element.spec.height,
itemHeight: element.spec.height,
body: libraryPanel,
});
} else {
throw new Error(`Unknown element kind: ${element.kind}`);
}
return buildGridItem(element.spec, panel);
} else if (element.kind === 'GridLayoutRow') {
const children = element.spec.elements.map((gridElement) => {
const panel = elements[getOriginalKey(gridElement.spec.element.name)];
if (panel.kind === 'Panel') {
if (panel.kind === 'Panel' || panel.kind === 'LibraryPanel') {
return buildGridItem(gridElement.spec, panel, element.spec.y + GRID_ROW_HEIGHT + gridElement.spec.y);
} else {
throw new Error(`Unknown element kind: ${gridElement.kind}`);
@ -295,8 +263,17 @@ function createSceneGridLayoutForItems(layout: GridLayoutKind, elements: Record<
});
}
function buildGridItem(gridItem: GridLayoutItemSpec, panel: PanelKind, yOverride?: number): DashboardGridItem {
const vizPanel = buildVizPanel(panel);
function buildGridItem(
gridItem: GridLayoutItemSpec,
panel: PanelKind | LibraryPanelKind,
yOverride?: number
): DashboardGridItem {
let vizPanel: VizPanel;
if (panel.kind === 'Panel') {
vizPanel = buildVizPanel(panel);
} else {
vizPanel = buildLibraryPanel(panel);
}
return new DashboardGridItem({
key: `grid-item-${panel.spec.id}`,
x: gridItem.x,
@ -310,47 +287,3 @@ function buildGridItem(gridItem: GridLayoutItemSpec, panel: PanelKind, yOverride
maxPerRow: gridItem.repeat?.maxPerRow,
});
}
function buildLibraryPanel(panel: LibraryPanelKind): VizPanel {
const titleItems: SceneObject[] = [];
if (config.featureToggles.angularDeprecationUI) {
titleItems.push(new AngularDeprecation());
}
titleItems.push(
new VizPanelLinks({
rawLinks: [],
menu: new VizPanelLinksMenu({ $behaviors: [panelLinksBehavior] }),
})
);
titleItems.push(new PanelNotices());
const vizPanelState: VizPanelState = {
key: getVizPanelKeyForPanelId(panel.spec.id),
titleItems,
$behaviors: [
new LibraryPanelBehavior({
uid: panel.spec.libraryPanel.uid,
name: panel.spec.libraryPanel.name,
}),
],
extendPanelContext: setDashboardPanelContext,
pluginId: LibraryPanelBehavior.LOADING_VIZ_PANEL_PLUGIN_ID,
title: panel.spec.title,
options: {},
fieldConfig: {
defaults: {},
overrides: [],
},
};
if (!config.publicDashboardAccessToken) {
vizPanelState.menu = new VizPanelMenu({
$behaviors: [panelMenuBehavior],
});
}
return new VizPanel(vizPanelState);
}

@ -7,7 +7,7 @@ import { DashboardLayoutManager, LayoutManagerSerializer } from '../../scene/typ
import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph';
import { getGridItemKeyForPanelId } from '../../utils/utils';
import { buildVizPanel } from './utils';
import { buildLibraryPanel, buildVizPanel } from './utils';
export class ResponsiveGridLayoutSerializer implements LayoutManagerSerializer {
serialize(layoutManager: ResponsiveGridLayoutManager): DashboardV2Spec['layout'] {
@ -58,12 +58,9 @@ export class ResponsiveGridLayoutSerializer implements LayoutManagerSerializer {
if (!panel) {
throw new Error(`Panel with uid ${item.spec.element.name} not found in the dashboard elements`);
}
if (panel.kind !== 'Panel') {
throw new Error(`Unsupported element kind: ${panel.kind}`);
}
return new ResponsiveGridItem({
key: getGridItemKeyForPanelId(panel.spec.id),
body: buildVizPanel(panel),
body: panel.kind === 'LibraryPanel' ? buildLibraryPanel(panel) : buildVizPanel(panel),
variableName: item.spec.repeat?.value,
});
});

@ -10,10 +10,16 @@ import {
VizPanelState,
} from '@grafana/scenes';
import { DataSourceRef } from '@grafana/schema/dist/esm/index.gen';
import { DashboardV2Spec, PanelKind, PanelQueryKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
import {
DashboardV2Spec,
LibraryPanelKind,
PanelKind,
PanelQueryKind,
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
import { DashboardDatasourceBehaviour } from '../../scene/DashboardDatasourceBehaviour';
import { LibraryPanelBehavior } from '../../scene/LibraryPanelBehavior';
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
import { panelLinksBehavior, panelMenuBehavior } from '../../scene/PanelMenuBehavior';
import { PanelNotices } from '../../scene/PanelNotices';
@ -80,6 +86,50 @@ export function buildVizPanel(panel: PanelKind): VizPanel {
return new VizPanel(vizPanelState);
}
export function buildLibraryPanel(panel: LibraryPanelKind): VizPanel {
const titleItems: SceneObject[] = [];
if (config.featureToggles.angularDeprecationUI) {
titleItems.push(new AngularDeprecation());
}
titleItems.push(
new VizPanelLinks({
rawLinks: [],
menu: new VizPanelLinksMenu({ $behaviors: [panelLinksBehavior] }),
})
);
titleItems.push(new PanelNotices());
const vizPanelState: VizPanelState = {
key: getVizPanelKeyForPanelId(panel.spec.id),
titleItems,
$behaviors: [
new LibraryPanelBehavior({
uid: panel.spec.libraryPanel.uid,
name: panel.spec.libraryPanel.name,
}),
],
extendPanelContext: setDashboardPanelContext,
pluginId: LibraryPanelBehavior.LOADING_VIZ_PANEL_PLUGIN_ID,
title: panel.spec.title,
options: {},
fieldConfig: {
defaults: {},
overrides: [],
},
};
if (!config.publicDashboardAccessToken) {
vizPanelState.menu = new VizPanelMenu({
$behaviors: [panelMenuBehavior],
});
}
return new VizPanel(vizPanelState);
}
export function createPanelDataProvider(panelKind: PanelKind): SceneDataProvider | undefined {
const panel = panelKind.spec;
const targets = panel.data?.spec.queries ?? [];

Loading…
Cancel
Save