-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DRAFT]: Divided AA into drought and storm layers (#1370)
* Divided AA into drought and storm layers and panels * fix misspelling and try to fix url update AA selection change * updated switch AA layers in url * Fix tests * reset start date on switch AA action * do not show data in the timeline when layer anticipatory_action_storm is selected * isolate AA drought specific legen items, setup empty legend for AA storm * clean AAstormPanel * move AA drought specific components to AADroughtPanel folder * do not show elements on the map for storm AA * fix linting issues * fix tests * enable the display of 2 aa layers only for aa_drought * add json data in a temporary file --------- Co-authored-by: ericboucher <eric.p.boucher@gmail.com> Co-authored-by: Maxime Chaillet <maxime.chaillet@pathtech.fr>
- Loading branch information
1 parent
5cb263b
commit 2a64115
Showing
56 changed files
with
3,578 additions
and
2,181 deletions.
There are no files selected for viewing
2,039 changes: 2,039 additions & 0 deletions
2,039
frontend/public/data/mozambique/anticipatory-action/aa_storm_temporary.json
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
231 changes: 231 additions & 0 deletions
231
frontend/src/components/MapView/Layers/AnticipatoryActionDroughtLayer/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import React from 'react'; | ||
import { | ||
AdminLevelDataLayerProps, | ||
AnticipatoryActionLayerProps, | ||
BoundaryLayerProps, | ||
MapEventWrapFunctionProps, | ||
} from 'config/types'; | ||
import { useDefaultDate } from 'utils/useDefaultDate'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { | ||
layerDataSelector, | ||
mapSelector, | ||
} from 'context/mapStateSlice/selectors'; | ||
import { LayerData } from 'context/layers/layer-data'; | ||
import { | ||
Layer, | ||
MapLayerMouseEvent, | ||
Marker, | ||
Source, | ||
} from 'react-map-gl/maplibre'; | ||
import { | ||
AAFiltersSelector, | ||
AAMarkersSelector, | ||
AARenderedDistrictsSelector, | ||
AASelectedDistrictSelector, | ||
setAAMarkers, | ||
setAASelectedDistrict, | ||
setAAView, | ||
} from 'context/anticipatoryActionStateSlice'; | ||
import { getAAColor } from 'components/MapView/LeftPanel/AnticipatoryActionPanel/utils'; | ||
import { | ||
calculateCentroids, | ||
useAAMarkerScalePercent, | ||
useMapCallback, | ||
} from 'utils/map-utils'; | ||
import { getBoundaryLayersByAdminLevel } from 'config/utils'; | ||
import { | ||
calculateAAMarkers, | ||
calculateCombinedAAMapData, | ||
} from 'context/anticipatoryActionStateSlice/utils'; | ||
import { AAView } from 'context/anticipatoryActionStateSlice/types'; | ||
import { Tooltip } from '@material-ui/core'; | ||
|
||
// Use admin level 2 boundary layer for Anticipatory Action | ||
const boundaryLayer = getBoundaryLayersByAdminLevel(2); | ||
|
||
const onDistrictClick = | ||
({ dispatch }: MapEventWrapFunctionProps<AdminLevelDataLayerProps>) => | ||
(evt: MapLayerMouseEvent) => { | ||
const districtId = | ||
evt.features?.[0]?.properties?.[boundaryLayer.adminLevelLocalNames[1]]; | ||
if (districtId) { | ||
dispatch(setAASelectedDistrict(districtId)); | ||
dispatch(setAAView(AAView.District)); | ||
} | ||
}; | ||
|
||
const AnticipatoryActionDroughtLayer = React.memo( | ||
({ layer, before }: LayersProps) => { | ||
useDefaultDate(layer.id); | ||
const boundaryLayerState = useSelector( | ||
layerDataSelector(boundaryLayer.id), | ||
) as LayerData<BoundaryLayerProps> | undefined; | ||
const { data } = boundaryLayerState || {}; | ||
const map = useSelector(mapSelector); | ||
const dispatch = useDispatch(); | ||
const renderedDistricts = useSelector(AARenderedDistrictsSelector); | ||
const { selectedWindow } = useSelector(AAFiltersSelector); | ||
const selectedDistrict = useSelector(AASelectedDistrictSelector); | ||
const markers = useSelector(AAMarkersSelector); | ||
|
||
useMapCallback( | ||
'click', | ||
`anticipatory-action-fill`, | ||
layer as any, | ||
onDistrictClick, | ||
); | ||
|
||
const shouldRenderData = React.useMemo(() => { | ||
if (selectedWindow === 'All') { | ||
return calculateCombinedAAMapData(renderedDistricts); | ||
} | ||
if (selectedWindow) { | ||
return Object.fromEntries( | ||
Object.entries(renderedDistricts[selectedWindow]).map( | ||
([dist, values]) => [dist, values[0]], | ||
), | ||
); | ||
} | ||
return {}; | ||
}, [renderedDistricts, selectedWindow]); | ||
|
||
// Calculate centroids only once per data change | ||
React.useEffect(() => { | ||
const districtCentroids = calculateCentroids(data); | ||
const m = calculateAAMarkers({ | ||
renderedDistricts, | ||
selectedWindow, | ||
districtCentroids, | ||
}); | ||
dispatch(setAAMarkers(m)); | ||
}, [data, dispatch, renderedDistricts, selectedWindow]); | ||
|
||
const highlightDistrictLine = React.useMemo( | ||
() => ({ | ||
...data, | ||
features: [ | ||
data?.features.find( | ||
f => | ||
f.properties?.[boundaryLayer.adminLevelLocalNames[1]] === | ||
selectedDistrict, | ||
), | ||
].filter(x => x), | ||
}), | ||
[data, selectedDistrict], | ||
); | ||
|
||
const coloredDistrictsLayer = React.useMemo(() => { | ||
const districtEntries = Object.entries(shouldRenderData); | ||
if (!data || !districtEntries.length) { | ||
return null; | ||
} | ||
return { | ||
...data, | ||
features: Object.entries(shouldRenderData) | ||
.map(([districtId, { category, phase }]: [string, any]) => { | ||
const feature = data?.features.find( | ||
f => | ||
f.properties?.[boundaryLayer.adminLevelLocalNames[1]] === | ||
districtId, | ||
); | ||
|
||
if (!feature) { | ||
return null; | ||
} | ||
const color = getAAColor(category, phase, true); | ||
return { | ||
...feature, | ||
properties: { | ||
...feature.properties, | ||
fillColor: color || 'grey', | ||
}, | ||
}; | ||
}) | ||
.filter(f => f !== null), | ||
}; | ||
}, [data, shouldRenderData]); | ||
|
||
const scalePercent = useAAMarkerScalePercent(map); | ||
|
||
const mainLayerBefore = selectedDistrict | ||
? 'anticipatory-action-selected-line' | ||
: before; | ||
|
||
return ( | ||
<> | ||
{markers.map(marker => ( | ||
<Marker | ||
key={`marker-${marker.district}`} | ||
longitude={marker.longitude} | ||
latitude={marker.latitude} | ||
anchor="center" | ||
> | ||
<Tooltip title={marker.district} arrow> | ||
<div | ||
style={{ | ||
transform: `scale(${scalePercent})`, | ||
cursor: 'pointer', | ||
}} | ||
> | ||
{marker.icon} | ||
</div> | ||
</Tooltip> | ||
</Marker> | ||
))} | ||
<Source | ||
id="anticipatory-action-selected" | ||
type="geojson" | ||
data={highlightDistrictLine} | ||
> | ||
<Layer | ||
beforeId={before} | ||
id="anticipatory-action-selected-line" | ||
type="line" | ||
source="anticipatory-action-selected" | ||
paint={{ | ||
'line-color': 'red', | ||
'line-width': 4, | ||
'line-opacity': highlightDistrictLine.features.length > 0 ? 1 : 0, | ||
}} | ||
/> | ||
</Source> | ||
{coloredDistrictsLayer && ( | ||
<Source | ||
key="anticipatory-action" | ||
id="anticipatory-action-" | ||
type="geojson" | ||
data={coloredDistrictsLayer} | ||
> | ||
<Layer | ||
beforeId={mainLayerBefore} | ||
type="fill" | ||
id="anticipatory-action-fill" | ||
source="anticipatory-action" | ||
layout={{}} | ||
paint={{ | ||
'fill-color': ['get', 'fillColor'], | ||
'fill-opacity': 0.9, | ||
}} | ||
/> | ||
<Layer | ||
beforeId={mainLayerBefore} | ||
id="anticipatory-action-boundary" | ||
type="line" | ||
source="anticipatory-action" | ||
paint={{ | ||
'line-color': 'black', | ||
}} | ||
/> | ||
</Source> | ||
)} | ||
</> | ||
); | ||
}, | ||
); | ||
export interface LayersProps { | ||
layer: AnticipatoryActionLayerProps; | ||
before?: string; | ||
} | ||
|
||
export default AnticipatoryActionDroughtLayer; |
Oops, something went wrong.