Geomap: Improve migration logic (#65500)

This commit is contained in:
Ryan McKinley 2023-04-28 12:20:10 -07:00 committed by GitHub
parent b1b6d9e2db
commit e493bec3a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 128 additions and 15 deletions

View File

@ -1,3 +1,5 @@
import { DataTransformerConfig } from '@grafana/schema';
import { FieldConfigSource } from './fieldOverrides';
import { DataQuery, DataSourceRef } from './query';
@ -38,6 +40,9 @@ export interface PanelModel<TOptions = any, TCustomFieldConfig = any> {
/** The queries in a panel */
targets?: DataQuery[];
/** Optionally process data after query */
transformations?: DataTransformerConfig[];
/** alerting v1 object */
alert?: any;
}

View File

@ -487,7 +487,7 @@ export class PanelModel implements DataConfigSource, IPanelModel {
const oldOptions: any = this.getOptionsToRemember();
const prevFieldConfig = this.fieldConfig;
const oldPluginId = this.type;
const wasAngular = this.isAngularPlugin();
const wasAngular = this.isAngularPlugin() || Boolean(autoMigrateAngular[oldPluginId]);
this.cachedPluginOptions[oldPluginId] = {
properties: oldOptions,
fieldConfig: prevFieldConfig,

View File

@ -82,11 +82,10 @@ export async function getLocationMatchers(src?: FrameGeometrySource): Promise<Lo
}
break;
case FrameGeometrySourceMode.Lookup:
if (src?.lookup) {
info.lookup = getFieldFinder(getFieldMatcher({ id: FieldMatcherID.byName, options: src.lookup }));
} else {
info.lookup = () => undefined; // In manual mode, don't automatically find field
}
const m = src?.lookup?.length
? getFieldMatcher({ id: FieldMatcherID.byName, options: src.lookup })
: getFieldMatcher({ id: FieldMatcherID.byType, options: FieldType.string });
info.lookup = getFieldFinder(m);
break;
case FrameGeometrySourceMode.Coords:
if (src?.latitude) {

View File

@ -55,7 +55,49 @@ describe('Worldmap Migrations', () => {
"mouseWheelZoom": true,
"showZoom": true,
},
"layers": [],
"layers": [
{
"config": {
"showLegend": true,
"style": {
"color": {
"fixed": "dark-green",
},
"opacity": 0.4,
"rotation": {
"fixed": 0,
"max": 360,
"min": -360,
"mode": "mod",
},
"size": {
"fixed": 5,
"max": 30,
"min": 2,
},
"symbol": {
"fixed": "img/icons/marker/circle.svg",
"mode": "fixed",
},
"textConfig": {
"fontSize": 12,
"offsetX": 0,
"offsetY": 0,
"textAlign": "center",
"textBaseline": "middle",
},
},
},
"location": {
"gazetteer": "public/gazetteer/countries.json",
"lookup": undefined,
"mode": "lookup",
},
"name": "",
"tooltip": true,
"type": "markers",
},
],
"tooltip": {
"mode": "details",
},
@ -66,6 +108,16 @@ describe('Worldmap Migrations', () => {
"zoom": 6,
},
},
"transformations": [
{
"id": "reduce",
"options": {
"reducers": [
"sum",
],
},
},
],
}
`);
});

View File

@ -1,9 +1,19 @@
import { cloneDeep } from 'lodash';
import { FieldConfigSource, PanelModel, PanelTypeChangedHandler, Threshold, ThresholdsMode } from '@grafana/data';
import {
FieldConfigSource,
PanelModel,
PanelTypeChangedHandler,
Threshold,
ThresholdsMode,
fieldReducers,
FrameGeometrySourceMode,
DataTransformerConfig,
DataTransformerID,
} from '@grafana/data';
import { ResourceDimensionMode } from 'app/features/dimensions';
import { MarkersConfig } from './layers/data/markersLayer';
import { defaultMarkersConfig, MarkersConfig } from './layers/data/markersLayer';
import { getMarkerAsPath } from './style/markers';
import { defaultStyleConfig } from './style/types';
import { PanelOptions, TooltipMode } from './types';
@ -15,10 +25,13 @@ import { MapCenterID } from './view';
export const mapPanelChangedHandler: PanelTypeChangedHandler = (panel, prevPluginId, prevOptions, prevFieldConfig) => {
// Changing from angular/worldmap panel to react/openlayers
if (prevPluginId === 'grafana-worldmap-panel' && prevOptions.angular) {
const { fieldConfig, options } = worldmapToGeomapOptions({
const { fieldConfig, options, xform } = worldmapToGeomapOptions({
...prevOptions.angular,
fieldConfig: prevFieldConfig,
});
if (xform?.id?.length) {
panel.transformations = panel.transformations ? [...panel.transformations, xform] : [xform];
}
panel.fieldConfig = fieldConfig; // Mutates the incoming panel
return options;
}
@ -26,12 +39,17 @@ export const mapPanelChangedHandler: PanelTypeChangedHandler = (panel, prevPlugi
return {};
};
export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfigSource; options: PanelOptions } {
export function worldmapToGeomapOptions(angular: any): {
fieldConfig: FieldConfigSource;
options: PanelOptions;
xform?: DataTransformerConfig;
} {
const fieldConfig: FieldConfigSource = {
defaults: {},
overrides: [],
};
const markersLayer = cloneDeep(defaultMarkersConfig);
const options: PanelOptions = {
view: {
id: MapCenterID.Zero,
@ -44,9 +62,7 @@ export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfi
type: 'default', // was carto
name: 'Basemap',
},
layers: [
// TODO? depends on current configs
],
layers: [markersLayer],
tooltip: { mode: TooltipMode.Details },
};
@ -55,6 +71,47 @@ export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfi
fieldConfig.defaults.decimals = v;
}
// Set the markers range
const style = markersLayer.config!.style;
v = asNumber(angular.circleMaxSize);
if (v) {
style.size!.max = v;
}
v = asNumber(angular.circleMinSize);
if (v) {
style.size!.min = v;
}
let xform: DataTransformerConfig | undefined = undefined;
const reducer = fieldReducers.getIfExists(angular.valueName);
if (reducer && angular.locationData?.length) {
xform = {
id: DataTransformerID.reduce,
options: {
reducers: [reducer.id],
},
};
switch (angular.locationData) {
case 'countries':
case 'countries_3letter':
markersLayer.location = {
mode: FrameGeometrySourceMode.Lookup,
gazetteer: 'public/gazetteer/countries.json',
lookup: undefined, // will default to first string field from reducer
};
break;
case 'states':
markersLayer.location = {
mode: FrameGeometrySourceMode.Lookup,
gazetteer: 'public/gazetteer/usa-states.json',
lookup: undefined, // will default to first string field from reducer
};
break;
}
}
// Convert thresholds and color values
if (angular.thresholds && angular.colors) {
const levels = angular.thresholds.split(',').map((strVale: string) => {
@ -99,7 +156,7 @@ export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfi
options.view.id = mapCenters[angular.mapCenter as any];
options.view.lat = asNumber(angular.mapCenterLatitude);
options.view.lon = asNumber(angular.mapCenterLongitude);
return { fieldConfig, options };
return { fieldConfig, options, xform };
}
function asNumber(v: any): number | undefined {