-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WMS popup functionality #173
Changes from 14 commits
447082d
7c4018a
e618c0c
fe105db
75e0a2d
434bf4e
480a555
917c9da
a385448
f4b9979
075838b
b1d8b95
e9b782b
77b11ce
f37d4fe
4972eb3
ca25a0d
30953dd
73987d1
c55874f
edf0c32
20f56b2
d6c3797
1d5057e
e8d0e89
25c2bd7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,10 @@ | ||
import React, { ComponentType, createElement, useEffect, useMemo } from 'react'; | ||
import React, { | ||
ComponentType, | ||
createElement, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
} from 'react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { | ||
CircularProgress, | ||
|
@@ -11,6 +17,7 @@ import { countBy, pickBy } from 'lodash'; | |
import moment from 'moment'; | ||
// map | ||
import ReactMapboxGl from 'react-mapbox-gl'; | ||
import DatePicker from 'react-datepicker'; | ||
import { Map } from 'mapbox-gl'; | ||
import MapTooltip from './MapTooltip'; | ||
import Legends from './Legends'; | ||
|
@@ -36,7 +43,11 @@ import { | |
layersSelector, | ||
} from '../../context/mapStateSlice/selectors'; | ||
import { addLayer, setMap, updateDateRange } from '../../context/mapStateSlice'; | ||
import { hidePopup } from '../../context/tooltipStateSlice'; | ||
import { | ||
showPopup, | ||
hidePopup, | ||
addPopupData, | ||
} from '../../context/tooltipStateSlice'; | ||
import { | ||
availableDatesSelector, | ||
isLoading as areDatesLoading, | ||
|
@@ -50,8 +61,10 @@ import AnalysisLayer from './Layers/AnalysisLayer'; | |
import { | ||
DateCompatibleLayer, | ||
getPossibleDatesForLayer, | ||
makeFeatureInfoRequest, | ||
} from '../../utils/server-utils'; | ||
import { addNotification } from '../../context/notificationStateSlice'; | ||
import { getActiveFeatureInfoLayers, getFeatureInfoParams } from './utils'; | ||
import AlertForm from './AlertForm'; | ||
|
||
const MapboxMap = ReactMapboxGl({ | ||
|
@@ -86,6 +99,8 @@ function MapView({ classes }: MapViewProps) { | |
|
||
const dispatch = useDispatch(); | ||
|
||
const selectedDateRef = useRef<DatePicker>(null); | ||
|
||
const { startDate: selectedDate } = useSelector(dateRangeSelector); | ||
const serverAvailableDates = useSelector(availableDatesSelector); | ||
const selectedLayersWithDateSupport = selectedLayers | ||
|
@@ -212,8 +227,43 @@ function MapView({ classes }: MapViewProps) { | |
containerStyle={{ | ||
height: '100%', | ||
}} | ||
onClick={() => { | ||
onClick={(map: Map, evt: any) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any chance the library comes with a type for this? Would be nice to not use any. If it doesn't we could make an alias to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to use the |
||
dispatch(hidePopup()); | ||
// Get layers that have getFeatureInfo option. | ||
const featureInfoLayers = getActiveFeatureInfoLayers(map); | ||
if (featureInfoLayers.length === 0) { | ||
return; | ||
} | ||
|
||
const dateFromRef = (selectedDateRef.current?.props.selected as Date) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we use moment.format for this? Also, I thought we were storing the date in a redux slice. Is the dateRangeSelector not up to date? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Included in c55874f |
||
.toISOString() | ||
.split('T')[0]; | ||
|
||
const params = getFeatureInfoParams(map, evt, dateFromRef); | ||
makeFeatureInfoRequest(featureInfoLayers, params).then( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that there's a delay to add the popup data. Maybe to address this delay, you can add
turns to
|
||
(result: any) => { | ||
if (result === null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. falsey check instead just in case the value is undefined? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Included in 30953dd |
||
return; | ||
} | ||
Object.keys(result).forEach(k => { | ||
dispatch( | ||
addPopupData({ | ||
[k]: { | ||
data: result[k], | ||
coordinates: evt.lngLat, | ||
}, | ||
}), | ||
); | ||
}); | ||
|
||
dispatch( | ||
showPopup({ | ||
coordinates: evt.lngLat, | ||
locationName: '', | ||
}), | ||
); | ||
}, | ||
); | ||
}} | ||
> | ||
<> | ||
|
@@ -247,7 +297,10 @@ function MapView({ classes }: MapViewProps) { | |
</Grid> | ||
</Grid> | ||
{selectedLayerDates.length > 0 && ( | ||
<DateSelector availableDates={selectedLayerDates} /> | ||
<DateSelector | ||
availableDates={selectedLayerDates} | ||
selectedDateRef={selectedDateRef} | ||
/> | ||
)} | ||
</Grid> | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Map } from 'mapbox-gl'; | ||
import { LayerDefinitions } from '../../config/utils'; | ||
import { getExtent } from './Layers/raster-utils'; | ||
import { WMSLayerProps, FeatureInfoType } from '../../config/types'; | ||
|
||
export const getActiveFeatureInfoLayers = (map: Map): WMSLayerProps[] => { | ||
const matchStr = 'layer-'; | ||
const layerIds = | ||
map | ||
.getStyle() | ||
.layers?.filter(l => l.id.startsWith(matchStr)) | ||
.map(l => l.id.split(matchStr)[1]) ?? []; | ||
|
||
if (layerIds.length === 0) { | ||
return []; | ||
} | ||
|
||
const featureInfoLayers = Object.values(LayerDefinitions).filter( | ||
l => layerIds.includes(l.id) && l.type === 'wms' && l.featureInfoProps, | ||
); | ||
|
||
if (featureInfoLayers.length === 0) { | ||
return []; | ||
} | ||
|
||
return featureInfoLayers as WMSLayerProps[]; | ||
}; | ||
|
||
export const getFeatureInfoParams = ( | ||
map: Map, | ||
evt: any, | ||
date: string, | ||
): FeatureInfoType => { | ||
const { x, y } = evt.point; | ||
const bbox = getExtent(map); | ||
const { clientWidth, clientHeight } = map.getContainer(); | ||
|
||
const params = { | ||
bbox, | ||
x: Math.floor(x), | ||
y: Math.floor(y), | ||
width: clientWidth, | ||
height: clientHeight, | ||
time: date, | ||
}; | ||
|
||
return params; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use React.forwardRef, but in the future if we need a ref to the selector we'll run into issues. Up to you 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a ref just to know current value from DateSelector. In both cases we would need to create the ref within the Mapview component and pass it to the DateSelector one.
Another option would be to use Localstorage, but some additional change will be needed within the addLayer reducer function