mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Geomap: Add dynamic initial view options * Add control options for dynamic initial view * Add handling for last only scope * Remove stale todos * Only reinitialize map view during data if fit * Add options for data fit In map init, remove dependency on layers input. Add a boolean to map view config to handle all layers, with default set to true. Also, add layer string to handle currently selected layer. Change some verbage. In map view editor, add controls for data extent options. Only display layer selection when all layers is not selected. Update layer extent function to handle all options permutations. When all layers is selected, return all data for extent calculation. When last only is selected, only return last data point in matching layer for extent calculation. Otherwise, return all data points in matching layer for extent calculation. * Change padding tooltip and hide for last only * Simplify getLayersExtent call * Add enums for data scope options * Update GeomapPanel for refactor merge * Move view init functions back into geomap class Re-apply data change handling and extent calculation handling. * Update padding tooltip verbage * Ensure geomap panel options layers are initialized * Clean up GeomapPanel file (betterer) * refactors / clean up * more cleanup Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
119 lines
4.0 KiB
TypeScript
119 lines
4.0 KiB
TypeScript
import { Map as OpenLayersMap } from 'ol';
|
|
import { defaults as interactionDefaults } from 'ol/interaction';
|
|
|
|
import { SelectableValue } from '@grafana/data';
|
|
import { DataFrame, GrafanaTheme2 } from '@grafana/data/src';
|
|
import { getColorDimension, getScalarDimension, getScaledDimension, getTextDimension } from 'app/features/dimensions';
|
|
import { getGrafanaDatasource } from 'app/plugins/datasource/grafana/datasource';
|
|
|
|
import { GeomapPanel } from '../GeomapPanel';
|
|
import { defaultStyleConfig, StyleConfig, StyleConfigState, StyleDimensions } from '../style/types';
|
|
import { GeomapPanelOptions, MapLayerState } from '../types';
|
|
|
|
export function getStyleDimension(
|
|
frame: DataFrame | undefined,
|
|
style: StyleConfigState,
|
|
theme: GrafanaTheme2,
|
|
customStyleConfig?: StyleConfig
|
|
) {
|
|
const dims: StyleDimensions = {};
|
|
if (customStyleConfig && Object.keys(customStyleConfig).length) {
|
|
dims.color = getColorDimension(frame, customStyleConfig.color ?? defaultStyleConfig.color, theme);
|
|
dims.size = getScaledDimension(frame, customStyleConfig.size ?? defaultStyleConfig.size);
|
|
dims.rotation = getScalarDimension(frame, customStyleConfig.rotation ?? defaultStyleConfig.rotation);
|
|
if (customStyleConfig.text && (customStyleConfig.text.field || customStyleConfig.text.fixed)) {
|
|
dims.text = getTextDimension(frame, customStyleConfig.text!);
|
|
}
|
|
} else {
|
|
if (style.fields) {
|
|
if (style.fields.color) {
|
|
dims.color = getColorDimension(frame, style.config.color ?? defaultStyleConfig.color, theme);
|
|
}
|
|
if (style.fields.size) {
|
|
dims.size = getScaledDimension(frame, style.config.size ?? defaultStyleConfig.size);
|
|
}
|
|
if (style.fields.text) {
|
|
dims.text = getTextDimension(frame, style.config.text!);
|
|
}
|
|
if (style.fields.rotation) {
|
|
dims.rotation = getScalarDimension(frame, style.config.rotation ?? defaultStyleConfig.rotation);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dims;
|
|
}
|
|
|
|
let publicGeoJSONFiles: Array<SelectableValue<string>> | undefined = undefined;
|
|
|
|
export function getPublicGeoJSONFiles(): Array<SelectableValue<string>> {
|
|
if (!publicGeoJSONFiles) {
|
|
publicGeoJSONFiles = [];
|
|
initGeojsonFiles(); // async
|
|
}
|
|
return publicGeoJSONFiles;
|
|
}
|
|
|
|
// This will find all geojson files in the maps and gazetteer folders
|
|
async function initGeojsonFiles() {
|
|
const ds = await getGrafanaDatasource();
|
|
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,
|
|
});
|
|
}
|
|
});
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
export const getNewOpenLayersMap = (panel: GeomapPanel, options: GeomapPanelOptions, div: HTMLDivElement) => {
|
|
const [view] = panel.initMapView(options.view, undefined);
|
|
return (panel.map = new OpenLayersMap({
|
|
view: view,
|
|
pixelRatio: 1, // or zoom?
|
|
layers: [], // loaded explicitly below
|
|
controls: [],
|
|
target: div,
|
|
interactions: interactionDefaults({
|
|
mouseWheelZoom: false, // managed by initControls
|
|
}),
|
|
}));
|
|
};
|
|
|
|
export const updateMap = (panel: GeomapPanel, options: GeomapPanelOptions) => {
|
|
panel.initControls(options.controls);
|
|
panel.forceUpdate(); // first render
|
|
};
|
|
|
|
export const notifyPanelEditor = (geomapPanel: GeomapPanel, layers: MapLayerState[], selected: number) => {
|
|
// Notify the panel editor
|
|
if (geomapPanel.panelContext && geomapPanel.panelContext.onInstanceStateChange) {
|
|
geomapPanel.panelContext.onInstanceStateChange({
|
|
map: geomapPanel.map,
|
|
layers: layers,
|
|
selected: selected,
|
|
actions: geomapPanel.actions,
|
|
});
|
|
}
|
|
};
|
|
|
|
export const getNextLayerName = (panel: GeomapPanel) => {
|
|
let idx = panel.layers.length; // since basemap is 0, this looks right
|
|
while (true && idx < 100) {
|
|
const name = `Layer ${idx++}`;
|
|
if (!panel.byName.has(name)) {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
return `Layer ${Date.now()}`;
|
|
};
|