LibraryPanels: Load library panels in the frontend rather than the backend (#50560)

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
This commit is contained in:
Ryan McKinley
2022-10-26 15:38:20 -07:00
committed by GitHub
parent 0db946977b
commit 7346280316
21 changed files with 191 additions and 952 deletions

View File

@@ -19,7 +19,6 @@ import {
LibraryPanelsSearchVariant,
} from '../../../library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch';
import { LibraryElementDTO } from '../../../library-panels/types';
import { toPanelModelLibraryPanel } from '../../../library-panels/utils';
import { DashboardModel, PanelModel } from '../../state';
export type PanelPluginInfo = { id: any; defaults: { gridPos: { w: any; h: any }; title: any } };
@@ -116,7 +115,7 @@ export const AddPanelWidgetUnconnected = ({ panel, dashboard }: Props) => {
const newPanel: PanelModel = {
...panelInfo.model,
gridPos,
libraryPanel: toPanelModelLibraryPanel(panelInfo),
libraryPanel: panelInfo,
};
dashboard.addPanel(newPanel);

View File

@@ -40,6 +40,20 @@ jest.mock('@grafana/runtime', () => ({
},
}));
jest.mock('app/features/library-panels/state/api', () => ({
getLibraryPanel: jest.fn().mockReturnValue(
Promise.resolve({
model: {
type: 'graph',
datasource: {
type: 'testdb',
uid: '${DS_GFDB}',
},
},
})
),
}));
variableAdapters.register(createQueryVariableAdapter());
variableAdapters.register(createConstantVariableAdapter());
variableAdapters.register(createDataSourceVariableAdapter());
@@ -146,8 +160,6 @@ describe('given dashboard with repeated panels', () => {
{ id: 9, datasource: { uid: '$ds', type: 'other2' } },
{
id: 17,
datasource: { uid: '$ds', type: 'other2' },
type: 'graph',
libraryPanel: {
name: 'Library Panel 2',
uid: 'ah8NqyDPs',
@@ -181,8 +193,8 @@ describe('given dashboard with repeated panels', () => {
{ id: 15, repeat: null, repeatPanelId: 14 },
{
id: 16,
datasource: { uid: 'gfdb', type: 'testdb' },
type: 'graph',
// datasource: { uid: 'gfdb', type: 'testdb' },
// type: 'graph',
libraryPanel: {
name: 'Library Panel',
uid: 'jL6MrxCMz',
@@ -218,6 +230,18 @@ describe('given dashboard with repeated panels', () => {
} as PanelPluginMeta;
dash = new DashboardModel(dash, {}, () => dash.templating.list);
// init library panels
dash.getPanelById(17).initLibraryPanel({
uid: 'ah8NqyDPs',
name: 'Library Panel 2',
model: {
datasource: { type: 'other2', uid: '$ds' },
targets: [{ refId: 'A', datasource: { type: 'other2', uid: '$ds' } }],
type: 'graph',
},
});
const exporter = new DashboardExporter();
exporter.makeExportable(dash).then((clean) => {
exported = clean;

View File

@@ -4,6 +4,7 @@ import { DataSourceRef, PanelPluginMeta } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import config from 'app/core/config';
import { PanelModel } from 'app/features/dashboard/state';
import { getLibraryPanel } from 'app/features/library-panels/state/api';
import { isPanelModelLibraryPanel } from '../../../library-panels/guard';
import { LibraryElementKind } from '../../../library-panels/types';
@@ -167,10 +168,15 @@ export class DashboardExporter {
}
};
const processLibraryPanels = (panel: any) => {
const processLibraryPanels = async (panel: PanelModel) => {
if (isPanelModelLibraryPanel(panel)) {
const { libraryPanel, ...model } = panel;
const { name, uid } = libraryPanel;
const { name, uid } = panel.libraryPanel;
let model = panel.libraryPanel.model;
if (!model) {
const libPanel = await getLibraryPanel(uid, true);
model = libPanel.model;
}
const { gridPos, id, ...rest } = model;
if (!libraryPanels.has(uid)) {
libraryPanels.set(uid, { name, uid, kind: LibraryElementKind.Panel, model: rest });
@@ -221,11 +227,11 @@ export class DashboardExporter {
// we need to process all panels again after all the promises are resolved
// so all data sources, variables and targets have been templateized when we process library panels
for (const panel of saveModel.panels) {
processLibraryPanels(panel);
for (const panel of dashboard.panels) {
await processLibraryPanels(panel);
if (panel.collapsed !== undefined && panel.collapsed === true && panel.panels) {
for (const rowPanel of panel.panels) {
processLibraryPanels(rowPanel);
await processLibraryPanels(rowPanel);
}
}
}

View File

@@ -165,7 +165,7 @@ export function ignoreChanges(current: DashboardModel, original: object | null)
/**
* Remove stuff that should not count in diff
*/
function cleanDashboardFromIgnoredChanges(dashData: any) {
function cleanDashboardFromIgnoredChanges(dashData: unknown) {
// need to new up the domain model class to get access to expand / collapse row logic
const model = new DashboardModel(dashData);
@@ -193,7 +193,7 @@ function cleanDashboardFromIgnoredChanges(dashData: any) {
return dash;
}
export function hasChanges(current: DashboardModel, original: any) {
export function hasChanges(current: DashboardModel, original: unknown) {
if (current.hasUnsavedChanges()) {
return true;
}