Geomap: update dashboard variable with view data

This commit is contained in:
dashie
2026-01-13 08:02:52 -08:00
committed by Drew Slobodnjak
parent 1d3f09d519
commit 5c30bcccc7
6 changed files with 58 additions and 1 deletions
@@ -177,6 +177,16 @@ Default Views are also available including:
| South Asia | South-East Asia | East Asia | Australia | Oceania |
<!-- prettier-ignore-end -->
#### Enable dashboard variable (Experimental)
If toggled the Geomap panel update, if exists, the dashboard's variable named `mapViewData` with the bounding box of the current view.
The variable can be a `Custom` variable type and can be hidden on the dashbaord (Show on dashboard: Nothing).
You can use then the variable inside your query to receive on the server side a string like this:
4.102646520428928,44.489253792751214,12.793524298588558,46.4346026776777
#### Share view
The **Share view** option allows you to link the movement and zoom actions of multiple map visualizations within the same dashboard. The map visualizations that have this option enabled act in tandem when one of them is moved or zoomed, leaving the other ones independent.
@@ -26,6 +26,7 @@ export const defaultOptions: Partial<Options> = {
export interface MapViewConfig {
allLayers?: boolean;
dashboardVariable?: boolean;
id: string;
lastOnly?: boolean;
lat?: number;
@@ -7,6 +7,7 @@ import Attribution from 'ol/control/Attribution';
import ScaleLine from 'ol/control/ScaleLine';
import Zoom from 'ol/control/Zoom';
import { Coordinate } from 'ol/coordinate';
import { EventsKey } from 'ol/events';
import { isEmpty } from 'ol/extent';
import MouseWheelZoom from 'ol/interaction/MouseWheelZoom';
import { fromLonLat, transformExtent } from 'ol/proj';
@@ -16,7 +17,7 @@ import { Subscription } from 'rxjs';
import { DataHoverEvent, PanelData, PanelProps } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { config, locationService } from '@grafana/runtime';
import { PanelContext, PanelContextRoot } from '@grafana/ui';
import { appEvents } from 'app/core/app_events';
import { VariablesChanged } from 'app/features/variables/types';
@@ -73,6 +74,8 @@ export class GeomapPanel extends Component<Props, State> {
layers: MapLayerState[] = [];
readonly byName = new Map<string, MapLayerState>();
mapViewData?: string;
constructor(props: Props) {
super(props);
this.state = { ttipOpen: false, legends: [] };
@@ -125,6 +128,9 @@ export class GeomapPanel extends Component<Props, State> {
// Check for resize
if (this.props.height !== nextProps.height || this.props.width !== nextProps.width) {
this.map.updateSize();
if (this.props.options?.view?.dashboardVariable) {
this.updateGeoVariables(this.map.getView());
}
}
// External data changed
@@ -331,7 +337,37 @@ export class GeomapPanel extends Component<Props, State> {
return view;
};
/**
* Updates the dashboard variable `mapViewData` with the view extent value.
* Use a debounce strategy to wait the user stop dragging or zooming the map.
*/
private timeoutId: NodeJS.Timeout | null = null; // for debounce
updateGeoVariables = (view: View) => {
const bounds = view.calculateExtent();
const bounds4326 = transformExtent(bounds, 'EPSG:3857', 'EPSG:4326');
console.log('GeomapPanel.updateGeoVariables', bounds4326);
if (this.timeoutId) {
clearTimeout(this.timeoutId);
}
this.timeoutId = setTimeout(() => {
locationService.partial({ 'var-mapViewData': `${bounds4326}` }, true);
}, 500);
};
private viewListernerKey: EventsKey | null = null;
initViewExtent(view: View, config: MapViewConfig) {
if (config.dashboardVariable) {
if (this.viewListernerKey != null) {
view.un('change', this.viewListernerKey.listener);
}
this.viewListernerKey = view.on('change', () => {
this.updateGeoVariables(view);
});
this.updateGeoVariables(view);
}
const v = centerPointRegistry.getIfExists(config.id);
if (v) {
let coord: Coordinate | undefined = undefined;
@@ -32,6 +32,14 @@ export const plugin = new PanelPlugin<Options>(GeomapPanel)
defaultValue: defaultMapViewConfig,
});
builder.addBooleanSwitch({
category,
path: 'view.dashboardVariable',
description: 'Store view bounds into the "mapViewData" dashboard variable.',
name: 'Enable dashboard variable (Experimental)',
defaultValue: false,
});
builder.addBooleanSwitch({
category,
path: 'view.shared',
@@ -46,6 +46,7 @@ composableKinds: PanelCfg: {
layer?: string
shared?: bool
noRepeat?: bool | *false
dashboardVariable?: bool
} @cuetsy(kind="interface")
ControlsOptions: {
+1
View File
@@ -24,6 +24,7 @@ export const defaultOptions: Partial<Options> = {
export interface MapViewConfig {
allLayers?: boolean;
dashboardVariable?: boolean;
id: string;
lastOnly?: boolean;
lat?: number;