mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user