From a7012a3c1f4f9cb492f857f23d745b52c4852553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20M=C3=BCller?= Date: Mon, 27 May 2024 16:34:52 +0200 Subject: [PATCH] fix(geomappanel.tsx): fix 'No map visible because the map container's width or height are 0' warning When panel was in full width it was not rendered. Adding the componentDidUpdate lifecycle method where initMapRef was called makes the panel render with width and height. --- src/GeomapPanel.tsx | 137 ++++++++++++++++++++++++++++++++------------ src/globalStyles.ts | 68 +++++++++++----------- 2 files changed, 134 insertions(+), 71 deletions(-) diff --git a/src/GeomapPanel.tsx b/src/GeomapPanel.tsx index 1d219a1..a89cc59 100644 --- a/src/GeomapPanel.tsx +++ b/src/GeomapPanel.tsx @@ -13,6 +13,7 @@ import { Vector } from 'ol/source'; import LayerSwitcher from 'ol-layerswitcher'; import { isArray, isEqual } from 'lodash'; import './GeomapPanel.css'; + // import WKT from 'ol/format/WKT.js'; // import Polygon from 'ol/geom/Polygon.js'; // import { /*locationService,*/ getTemplateSrv } from '@grafana/runtime'; @@ -21,14 +22,16 @@ import { PanelData, MapLayerHandler, PanelProps, - GrafanaTheme, + // GrafanaTheme, DataHoverClearEvent, DataHoverEvent, DataFrame, DataSelectEvent, // getFieldDisplayName, getFieldDisplayValuesProxy, - ScopedVars + ScopedVars, + BusEventWithPayload, + // GrafanaTheme2 } from '@grafana/data'; import { /*getTemplateSrv,*/ config,/*, RefreshEvent, TimeRangeUpdatedEvent*/ /*RefreshEvent,*/ locationService} from '@grafana/runtime'; @@ -38,7 +41,7 @@ import { centerPointRegistry, MapCenterID } from './view'; import { fromLonLat, toLonLat } from 'ol/proj'; import { Coordinate } from 'ol/coordinate'; import { css } from '@emotion/css'; -import { Portal, stylesFactory, VizTooltipContainer } from '@grafana/ui'; +import { Portal ,/* stylesFactory, useStyles2, */ VizTooltipContainer } from '@grafana/ui'; import { GeomapOverlay, OverlayProps } from './GeomapOverlay'; import { DebugOverlay } from './components/DebugOverlay'; import { getGlobalStyles } from './globalStyles'; @@ -48,6 +51,7 @@ import { ExtendMapLayerOptions } from './extension'; import SpatialFilterControl from './mapcontrols/SpatialFilter'; import { testIds } from 'e2eTestIds'; import { Global } from '@emotion/react'; +// import { Subscription } from 'rxjs'; // import { VariablesChangedEvent } from // import {getBottomLeft, getBottomRight, getTopLeft, getTopRight} from 'ol/extent'; @@ -83,6 +87,11 @@ interface State extends OverlayProps { // } // }; +// As stated here: https://grafana.com/developers/plugin-tools/create-a-plugin/develop-a-plugin/subscribe-events#what-events-are-supported +class MyPanelEditExitedEvent extends BusEventWithPayload { + static type = 'panel-edit-finished'; +} + export class GeomapPanel extends Component { globalCSS = getGlobalStyles(config.theme2); @@ -91,15 +100,23 @@ export class GeomapPanel extends Component { basemap?: BaseLayer; layers: MapLayerState[] = []; mouseWheelZoom?: MouseWheelZoom; - style = getStyles(config.theme); + // style = getStyles(config.theme2); hoverPayload: GeomapHoverPayload = { point: {}, pageX: -1, pageY: -1 }; readonly hoverEvent = new DataHoverEvent(this.hoverPayload); + // private subs = new Subscription(); + mapDiv?: HTMLDivElement; constructor(props: Props/*, state: State*/) { super(props); // this.state = {}; this.state = { ttipOpen: false }; + this.props.eventBus.getStream(MyPanelEditExitedEvent).subscribe((evt) => { + if (this.mapDiv && this.props.id === evt.payload) { + this.initMapRef(this.mapDiv); + } + }) + // this.props.eventBus.getStream(DataSelectEvent).subscribe((event) => { // }); @@ -145,7 +162,8 @@ export class GeomapPanel extends Component { // console.log(urlString); } catch (error) { // console.log("Might have no links defined."); - console.error(error); + // console.error(error); + return; } try { @@ -160,13 +178,35 @@ export class GeomapPanel extends Component { // Update url locationService.partial({ ...updateVars }, true); } catch (error) { - console.error(error); + // console.error(error); + return; } }); } componentDidMount() { lastGeomapPanelInstance = this; + this.initMapRef(this.mapDiv!); + } + + // https://github.com/grafana/grafana/blob/aac6e6dfd94c78b250e796dbff9422d202cb54e8/public/app/plugins/panel/geomap/GeomapPanel.tsx#L112C3-L120 + componentDidUpdate(prevProps: Props) { + if (this.map && (this.props.height !== prevProps.height || this.props.width !== prevProps.width)) { + this.map.updateSize(); + } + // Check for a difference between previous data and component data + if (this.map && this.props.data !== prevProps.data) { + this.dataChanged(this.props.data); + } + } + + componentWillUnmount() { + // this.subs.unsubscribe(); + for (const lyr of this.layers) { + lyr.handler.dispose?.(); + } + // Ensure map is disposed + this.map?.dispose(); } shouldComponentUpdate(nextProps: Props) { @@ -259,21 +299,24 @@ export class GeomapPanel extends Component { } initMapRef = async (div: HTMLDivElement) => { - if (this.map) { - this.map.dispose(); - } - if (!div) { this.map = undefined as unknown as Map; return; } + + this.mapDiv = div; + if (this.map) { + this.map.dispose(); + } + + const { options } = this.props; this.map = new Map({ view: this.initMapView(options.view), pixelRatio: 1, // or zoom? layers: [], // loaded explicitly below controls: [], - target: div, + target: this.mapDiv, interactions: interactionDefaults({ mouseWheelZoom: false, // managed by initControls }), @@ -602,39 +645,57 @@ export class GeomapPanel extends Component { { } -
-
+
+
- {ttip && ttip.data && ( - - - + + + + + )} - + ); } } -const getStyles = stylesFactory((theme: GrafanaTheme) => ({ - wrap: css` - position: relative; - width: 100%; - height: 100%; - `, - map: css` - position: absolute; - z-index: 0; - width: 100%; - height: 100%; - `, - viz: css` - border-radius: 10px; - `, -})); +// const getStyles = stylesFactory((theme: GrafanaTheme2) => ({ +// wrap: css` +// position: relative; +// width: 100%; +// height: 100%; +// `, +// map: css` +// position: absolute; +// z-index: 0; +// width: 100%; +// height: 100%; +// `, +// viz: css` +// border-radius: 10px; +// `, +// })); + +const styles = { + wrap: css({ + position: "relative", + width: "100%", + height: "100%", + }), + map: css({ + position: "absolute", + zIndex: "0", + width: "100%", + height: "100%", + }), + viz: css({ + borderRadius: "10px", + }), +}; diff --git a/src/globalStyles.ts b/src/globalStyles.ts index 2eae745..7fff02f 100644 --- a/src/globalStyles.ts +++ b/src/globalStyles.ts @@ -44,37 +44,39 @@ export function getGlobalStyles(theme: GrafanaTheme2) { // border: 2px dotted rgba(0,60,136,0.7); // } - return css` - .ol-scale-line { - background: ${theme.colors.border.weak}; // rgba(0,60,136,0.3); - } - .ol-scale-line-inner { - border: 1px solid ${theme.colors.text.primary}; // #eee; - border-top: 0px; - color: ${theme.colors.text.primary}; // #eee; - } - .ol-control { - background-color: ${theme.colors.background.secondary}; //rgba(255,255,255,0.4); - } - .ol-control:hover { - background-color: ${theme.colors.action.hover}; // rgba(255,255,255,0.6); - } - .ol-control button { - color: ${theme.colors.secondary.text}; // white; - background-color: ${theme.colors.secondary.main}; // rgba(0,60,136,0.5); - } - .ol-control button:hover { - background-color: ${theme.colors.secondary.shade}; // rgba(0,60,136,0.5); - } - .ol-control button:focus { - background-color: ${theme.colors.secondary.main}; // rgba(0,60,136,0.5); - } - .ol-attribution ul { - color: ${theme.colors.text.primary}; // #000; - text-shadow: none; - } - .ol-attribution:not(.ol-collapsed) { - background-color: ${theme.colors.background.secondary}; // rgba(255,255,255,0.8); - } - `; + return css({ + '.ol-scale-line': { + background: theme.colors.border.weak, // rgba(0,60,136,0.3); + }, + '.ol-scale-line-inner': { + border: `1px solid ${theme.colors.text.primary}`, // #eee; + borderTop: 0, // 0px; + color: theme.colors.text.primary, // #eee; + }, + '.ol-control': { + backgroundColor: theme.colors.background.primary, // rgba(255,255,255,0.4); + }, + '.ol-control:hover': { + backgroundColor: theme.colors.background.secondary, // rgba(255,255,255,0.6); + }, + '.ol-control button': { + color: theme.colors.secondary.text, // white; + backgroundColor: theme.colors.secondary.main, // rgba(0,60,136,0.5); + }, + '.ol-control button:hover': { + color: theme.colors.secondary.text, + backgroundColor: theme.colors.secondary.shade, // rgba(0,60,136,0.5); + }, + '.ol-control button:focus': { + color: theme.colors.secondary.text, + backgroundColor: theme.colors.secondary.main, // rgba(0,60,136,0.5); + }, + '.ol-attribution ul': { + color: theme.colors.text.primary, // #000; + textShadow: 'none', + }, + '.ol-attribution:not(.ol-collapsed)': { + backgroundColor: theme.colors.background.secondary, // rgba(255,255,255,0.8); + }, + }); }