grafana/public/app/plugins/panel/geomap/migrations.ts

148 lines
4.3 KiB
TypeScript

import { cloneDeep } from 'lodash';
import { FieldConfigSource, PanelModel, PanelTypeChangedHandler, Threshold, ThresholdsMode } from '@grafana/data';
import { ResourceDimensionMode } from 'app/features/dimensions';
import { MarkersConfig } from './layers/data/markersLayer';
import { getMarkerAsPath } from './style/markers';
import { defaultStyleConfig } from './style/types';
import { GeomapPanelOptions, TooltipMode } from './types';
import { MapCenterID } from './view';
/**
* This is called when the panel changes from another panel
*/
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({
...prevOptions.angular,
fieldConfig: prevFieldConfig,
});
panel.fieldConfig = fieldConfig; // Mutates the incoming panel
return options;
}
return {};
};
export function worldmapToGeomapOptions(angular: any): { fieldConfig: FieldConfigSource; options: GeomapPanelOptions } {
const fieldConfig: FieldConfigSource = {
defaults: {},
overrides: [],
};
const options: GeomapPanelOptions = {
view: {
id: MapCenterID.Zero,
},
controls: {
showZoom: true,
mouseWheelZoom: Boolean(angular.mouseWheelZoom),
},
basemap: {
type: 'default', // was carto
name: 'Basemap',
},
layers: [
// TODO? depends on current configs
],
tooltip: { mode: TooltipMode.Details },
};
let v = asNumber(angular.decimals);
if (v) {
fieldConfig.defaults.decimals = v;
}
// Convert thresholds and color values
if (angular.thresholds && angular.colors) {
const levels = angular.thresholds.split(',').map((strVale: string) => {
return Number(strVale.trim());
});
// One more color than threshold
const thresholds: Threshold[] = [];
for (const color of angular.colors) {
const idx = thresholds.length - 1;
if (idx >= 0) {
thresholds.push({ value: levels[idx], color });
} else {
thresholds.push({ value: -Infinity, color });
}
}
fieldConfig.defaults.thresholds = {
mode: ThresholdsMode.Absolute,
steps: thresholds,
};
}
v = asNumber(angular.initialZoom);
if (v) {
options.view.zoom = v;
}
// mapCenter: 'Europe',
// mapCenterLatitude: 46,
// mapCenterLongitude: 14,
//
// Map center (from worldmap)
const mapCenters: any = {
'(0°, 0°)': MapCenterID.Zero,
'North America': 'north-america',
Europe: 'europe',
'West Asia': 'west-asia',
'SE Asia': 'se-asia',
'Last GeoHash': MapCenterID.Coordinates, // MapCenterID.LastPoint,
};
options.view.id = mapCenters[angular.mapCenter as any];
options.view.lat = asNumber(angular.mapCenterLatitude);
options.view.lon = asNumber(angular.mapCenterLongitude);
return { fieldConfig, options };
}
function asNumber(v: any): number | undefined {
const num = +v;
return isNaN(num) ? undefined : num;
}
export const mapMigrationHandler = (panel: PanelModel): Partial<GeomapPanelOptions> => {
const pluginVersion = panel?.pluginVersion ?? '';
// before 8.3, only one layer was supported!
if (pluginVersion.startsWith('8.1') || pluginVersion.startsWith('8.2')) {
const layers = panel.options?.layers;
if (layers?.length === 1) {
const layer = panel.options.layers[0];
if (layer?.type === 'markers' && layer.config) {
// Moving style to child object
const oldConfig = layer.config;
const config: MarkersConfig = {
style: cloneDeep(defaultStyleConfig),
showLegend: Boolean(oldConfig.showLegend),
};
if (oldConfig.size) {
config.style.size = oldConfig.size;
}
if (oldConfig.color) {
config.style.color = oldConfig.color;
}
if (oldConfig.fillOpacity) {
config.style.opacity = oldConfig.fillOpacity;
}
const symbol = getMarkerAsPath(oldConfig.shape);
if (symbol) {
config.style.symbol = {
fixed: symbol,
mode: ResourceDimensionMode.Fixed,
};
}
return { ...panel.options, layers: [{ ...layer, config }] };
}
}
}
return panel.options;
};