155 lines
5.5 KiB
TypeScript
155 lines
5.5 KiB
TypeScript
import { config } from '@grafana/runtime';
|
|
import {
|
|
SceneDataProvider,
|
|
SceneDataQuery,
|
|
SceneDataTransformer,
|
|
SceneObject,
|
|
SceneQueryRunner,
|
|
VizPanel,
|
|
VizPanelMenu,
|
|
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 { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
|
|
|
import { DashboardDatasourceBehaviour } from '../../scene/DashboardDatasourceBehaviour';
|
|
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
|
|
import { panelLinksBehavior, panelMenuBehavior } from '../../scene/PanelMenuBehavior';
|
|
import { PanelNotices } from '../../scene/PanelNotices';
|
|
import { PanelTimeRange } from '../../scene/PanelTimeRange';
|
|
import { AngularDeprecation } from '../../scene/angular/AngularDeprecation';
|
|
import { setDashboardPanelContext } from '../../scene/setDashboardPanelContext';
|
|
import { DashboardLayoutManager } from '../../scene/types/DashboardLayoutManager';
|
|
import { getVizPanelKeyForPanelId } from '../../utils/utils';
|
|
import { transformMappingsToV1 } from '../transformToV1TypesUtils';
|
|
|
|
import { layoutSerializerRegistry } from './layoutSerializerRegistry';
|
|
|
|
export function buildVizPanel(panel: PanelKind): VizPanel {
|
|
const titleItems: SceneObject[] = [];
|
|
|
|
if (config.featureToggles.angularDeprecationUI) {
|
|
titleItems.push(new AngularDeprecation());
|
|
}
|
|
|
|
titleItems.push(
|
|
new VizPanelLinks({
|
|
rawLinks: panel.spec.links,
|
|
menu: new VizPanelLinksMenu({ $behaviors: [panelLinksBehavior] }),
|
|
})
|
|
);
|
|
|
|
titleItems.push(new PanelNotices());
|
|
|
|
const queryOptions = panel.spec.data.spec.queryOptions;
|
|
const timeOverrideShown = (queryOptions.timeFrom || queryOptions.timeShift) && !queryOptions.hideTimeOverride;
|
|
|
|
const vizPanelState: VizPanelState = {
|
|
key: getVizPanelKeyForPanelId(panel.spec.id),
|
|
title: panel.spec.title,
|
|
description: panel.spec.description,
|
|
pluginId: panel.spec.vizConfig.kind,
|
|
options: panel.spec.vizConfig.spec.options,
|
|
fieldConfig: transformMappingsToV1(panel.spec.vizConfig.spec.fieldConfig),
|
|
pluginVersion: panel.spec.vizConfig.spec.pluginVersion,
|
|
displayMode: panel.spec.transparent ? 'transparent' : 'default',
|
|
hoverHeader: !panel.spec.title && !timeOverrideShown,
|
|
hoverHeaderOffset: 0,
|
|
$data: createPanelDataProvider(panel),
|
|
titleItems,
|
|
$behaviors: [],
|
|
extendPanelContext: setDashboardPanelContext,
|
|
// _UNSAFE_customMigrationHandler: getAngularPanelMigrationHandler(panel), //FIXME: Angular Migration
|
|
};
|
|
|
|
if (!config.publicDashboardAccessToken) {
|
|
vizPanelState.menu = new VizPanelMenu({
|
|
$behaviors: [panelMenuBehavior],
|
|
});
|
|
}
|
|
|
|
if (queryOptions.timeFrom || queryOptions.timeShift) {
|
|
vizPanelState.$timeRange = new PanelTimeRange({
|
|
timeFrom: queryOptions.timeFrom,
|
|
timeShift: queryOptions.timeShift,
|
|
hideTimeOverride: queryOptions.hideTimeOverride,
|
|
});
|
|
}
|
|
|
|
return new VizPanel(vizPanelState);
|
|
}
|
|
|
|
export function createPanelDataProvider(panelKind: PanelKind): SceneDataProvider | undefined {
|
|
const panel = panelKind.spec;
|
|
const targets = panel.data?.spec.queries ?? [];
|
|
// Skip setting query runner for panels without queries
|
|
if (!targets?.length) {
|
|
return undefined;
|
|
}
|
|
|
|
// Skip setting query runner for panel plugins with skipDataQuery
|
|
if (config.panels[panel.vizConfig.kind]?.skipDataQuery) {
|
|
return undefined;
|
|
}
|
|
|
|
let dataProvider: SceneDataProvider | undefined = undefined;
|
|
const datasource = getPanelDataSource(panelKind);
|
|
|
|
dataProvider = new SceneQueryRunner({
|
|
datasource,
|
|
queries: targets.map(panelQueryKindToSceneQuery),
|
|
maxDataPoints: panel.data.spec.queryOptions.maxDataPoints ?? undefined,
|
|
maxDataPointsFromWidth: true,
|
|
cacheTimeout: panel.data.spec.queryOptions.cacheTimeout,
|
|
queryCachingTTL: panel.data.spec.queryOptions.queryCachingTTL,
|
|
minInterval: panel.data.spec.queryOptions.interval ?? undefined,
|
|
dataLayerFilter: {
|
|
panelId: panel.id,
|
|
},
|
|
$behaviors: [new DashboardDatasourceBehaviour({})],
|
|
});
|
|
|
|
// Wrap inner data provider in a data transformer
|
|
return new SceneDataTransformer({
|
|
$data: dataProvider,
|
|
transformations: panel.data.spec.transformations.map((transformation) => transformation.spec),
|
|
});
|
|
}
|
|
|
|
function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined {
|
|
if (!panel.spec.data?.spec.queries?.length) {
|
|
return undefined;
|
|
}
|
|
|
|
let datasource: DataSourceRef | undefined = undefined;
|
|
let isMixedDatasource = false;
|
|
|
|
panel.spec.data.spec.queries.forEach((query) => {
|
|
if (!datasource) {
|
|
datasource = query.spec.datasource;
|
|
} else if (datasource.uid !== query.spec.datasource?.uid || datasource.type !== query.spec.datasource?.type) {
|
|
isMixedDatasource = true;
|
|
}
|
|
});
|
|
|
|
return isMixedDatasource ? { type: 'mixed', uid: MIXED_DATASOURCE_NAME } : undefined;
|
|
}
|
|
|
|
function panelQueryKindToSceneQuery(query: PanelQueryKind): SceneDataQuery {
|
|
return {
|
|
refId: query.spec.refId,
|
|
datasource: query.spec.datasource,
|
|
hide: query.spec.hidden,
|
|
...query.spec.query.spec,
|
|
};
|
|
}
|
|
|
|
export function getLayout(sceneState: DashboardLayoutManager): DashboardV2Spec['layout'] {
|
|
const registryItem = layoutSerializerRegistry.get(sceneState.descriptor.kind ?? '');
|
|
if (!registryItem) {
|
|
throw new Error(`Layout serializer not found for kind: ${sceneState.descriptor.kind}`);
|
|
}
|
|
return registryItem.serializer.serialize(sceneState);
|
|
}
|