Geomap: initialization fixes (#44745)

This commit is contained in:
Ryan McKinley 2022-02-01 22:08:07 -08:00 committed by GitHub
parent d8df08ce5d
commit ac90c8d68d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 18 deletions

View File

@ -62,7 +62,7 @@ export interface MapLayerOptions<TConfig = any> {
// Layer opacity (0-1)
opacity?: number;
// Check tooltip
// Check tooltip (defaults to true)
tooltip?: boolean;
}

View File

@ -51,6 +51,7 @@ func newService(cfg *setting.Cfg) *Service {
"img/icons",
"img/bg",
"gazetteer",
"maps",
"upload", // does not exist yet
},
}

View File

@ -15,6 +15,7 @@ import {
DataSourceInstanceSettings,
DataSourceRef,
isValidLiveChannelAddress,
MutableDataFrame,
parseLiveChannelAddress,
toDataFrame,
} from '@grafana/data';
@ -149,7 +150,7 @@ export class GrafanaDatasource extends DataSourceWithBackend<GrafanaQuery> {
],
} as any).pipe(
map((v) => {
const frame = v.data[0] ?? toDataFrame({});
const frame = v.data[0] ?? new MutableDataFrame();
return new DataFrameView<FileElement>(frame);
})
);

View File

@ -15,6 +15,7 @@ import {
DataHoverClearEvent,
DataHoverEvent,
DataFrame,
FrameGeometrySourceMode,
} from '@grafana/data';
import { config } from '@grafana/runtime';
@ -180,6 +181,7 @@ export class GeomapPanel extends Component<Props, State> {
type: item.id,
name: this.getNextLayerName(),
config: cloneDeep(item.defaultOptions),
location: item.showLocation ? { mode: FrameGeometrySourceMode.Auto } : undefined,
tooltip: true,
},
false
@ -266,10 +268,7 @@ export class GeomapPanel extends Component<Props, State> {
layers.push(await this.initLayer(map, options.basemap ?? DEFAULT_BASEMAP_CONFIG, true));
// Default layer values
let layerOptions = options.layers;
if (!layerOptions) {
layerOptions = [defaultMarkersConfig];
}
const layerOptions = options.layers ?? [defaultMarkersConfig];
for (const lyr of layerOptions) {
layers.push(await this.initLayer(map, lyr, false));
@ -278,10 +277,11 @@ export class GeomapPanel extends Component<Props, State> {
console.error('error loading layers', ex);
}
this.layers = layers;
for (const lyr of layers) {
this.map.addLayer(lyr.layer);
map.addLayer(lyr.layer);
}
this.layers = layers;
this.map = map; // redundant
this.mouseWheelZoom = new MouseWheelZoom();
this.map.addInteraction(this.mouseWheelZoom);

View File

@ -1,4 +1,4 @@
import { MapLayerOptions, MapLayerRegistryItem, PluginState } from '@grafana/data';
import { FrameGeometrySourceMode, MapLayerOptions, MapLayerRegistryItem, PluginState } from '@grafana/data';
import { DEFAULT_BASEMAP_CONFIG, geomapLayerRegistry } from '../layers/registry';
import { NestedPanelOptions, NestedValueAccess } from '@grafana/data/src/utils/OptionsUIBuilders';
import { defaultMarkersConfig } from '../layers/data/markersLayer';
@ -31,11 +31,19 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
const layer = geomapLayerRegistry.getIfExists(value);
if (layer) {
console.log('Change layer type:', value, state);
state.onChange({
const opts = {
...options, // keep current shared options
type: layer.id,
config: { ...layer.defaultOptions }, // clone?
});
};
if (layer.showLocation) {
if (!opts.location?.mode) {
opts.location = { mode: FrameGeometrySourceMode.Auto };
} else {
delete opts.location;
}
}
state.onChange(opts);
return;
}
}
@ -76,7 +84,7 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions<Map
}
if (layer.showLocation) {
addLocationFields('Location', 'location', builder, options.location);
addLocationFields('Location', 'location.', builder, options.location);
}
if (handler.registerOptionsUI) {
handler.registerOptionsUI(builder);

View File

@ -1,4 +1,11 @@
import { MapLayerRegistryItem, MapLayerOptions, PanelData, GrafanaTheme2, PluginState } from '@grafana/data';
import {
MapLayerRegistryItem,
MapLayerOptions,
PanelData,
GrafanaTheme2,
PluginState,
SelectableValue,
} from '@grafana/data';
import Map from 'ol/Map';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
@ -16,6 +23,8 @@ import { StyleEditor } from './StyleEditor';
import { ReplaySubject } from 'rxjs';
import { map as rxjsmap, first } from 'rxjs/operators';
import { getLayerPropertyInfo } from '../../utils/getFeatures';
import { GrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
import { getDataSourceSrv } from '@grafana/runtime';
export interface GeoJSONMapperConfig {
// URL for a geojson file
@ -50,6 +59,8 @@ export const DEFAULT_STYLE_RULE: FeatureStyleConfig = {
},
};
let publicGeoJSONFiles: Array<SelectableValue<string>> | undefined = undefined;
export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
id: 'geojson',
name: 'GeoJSON',
@ -151,16 +162,16 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
rxjsmap((v) => getLayerPropertyInfo(v))
);
if (!publicGeoJSONFiles) {
initGeojsonFiles();
}
builder
.addSelect({
path: 'config.src',
name: 'GeoJSON URL',
settings: {
options: [
{ label: 'public/maps/countries.geojson', value: 'public/maps/countries.geojson' },
{ label: 'public/maps/usa-states.geojson', value: 'public/maps/usa-states.geojson' },
{ label: 'public/gazetteer/airports.geojson', value: 'public/gazetteer/airports.geojson' },
],
options: publicGeoJSONFiles ?? [],
allowCustomValue: true,
},
defaultValue: defaultOptions.src,
@ -194,3 +205,28 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
},
defaultOptions,
};
// This will find all geojson files in the maps and gazetteer folders
async function initGeojsonFiles() {
if (publicGeoJSONFiles) {
return;
}
publicGeoJSONFiles = [];
const ds = (await getDataSourceSrv().get('-- Grafana --')) as GrafanaDatasource;
for (let folder of ['maps', 'gazetteer']) {
ds.listFiles(folder).subscribe({
next: (frame) => {
frame.forEach((item) => {
if (item.name.endsWith('.geojson')) {
const value = `public/${folder}/${item.name}`;
publicGeoJSONFiles!.push({
value,
label: value,
});
}
});
},
});
}
}