Skip to content

Commit

Permalink
DBC22-1935: advisories only show on map if in view extent
Browse files Browse the repository at this point in the history
  • Loading branch information
ray-oxd authored and fatbird committed Apr 3, 2024
1 parent 4251cf9 commit b141458
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 35 deletions.
60 changes: 58 additions & 2 deletions src/frontend/src/Components/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
updateRestStops,
} from '../slices/feedsSlice';
import { updateMapState } from '../slices/mapSlice';
import { updateAdvisories } from '../slices/cmsSlice';

// External Components
import Button from 'react-bootstrap/Button';
Expand All @@ -40,6 +41,7 @@ import {
getRegionalPopup,
getRestStopPopup,
} from './map/mapPopup.js';
import { getAdvisories } from './data/advisories.js';
import { getEvents } from './data/events.js';
import { getWeather, getRegional } from './data/weather.js';
import { getRestStops } from './data/restStops.js';
Expand Down Expand Up @@ -69,17 +71,19 @@ import CurrentCameraIcon from './CurrentCameraIcon';
import Filters from './Filters.js';
import RouteSearch from './map/RouteSearch.js';

// OpenLayers
// OpenLayers & turf
import { applyStyle } from 'ol-mapbox-style';
import { fromLonLat, toLonLat, transformExtent } from 'ol/proj';
import { ScaleLine } from 'ol/control.js';
import { getBottomLeft, getTopRight } from 'ol/extent';
import Map from 'ol/Map';
import Overlay from 'ol/Overlay.js';
import Geolocation from 'ol/Geolocation.js';
import MVT from 'ol/format/MVT.js';
import VectorTileLayer from 'ol/layer/VectorTile.js';
import VectorTileSource from 'ol/source/VectorTile.js';
import View from 'ol/View';
import { booleanIntersects, polygon } from '@turf/turf';

// Styling
import {
Expand Down Expand Up @@ -211,6 +215,8 @@ export default function MapWrapper({
setClickedRestStop(feature);
}

const [advisoriesInView, setAdvisoriesInView] = useState([]);

// Define the function to be executed after the delay
function resetCameraPopupRef() {
cameraPopupRef.current = null;
Expand Down Expand Up @@ -806,7 +812,51 @@ export default function MapWrapper({
}
};

// Advisories helper functions
function wrapLon(value) {
const worlds = Math.floor((value + 180) / 360);
return value - worlds * 360;
}

function onMoveEnd(evt) {
// calculate polygon based on map extent
const map = evt.map;
const extent = map.getView().calculateExtent(map.getSize());
const bottomLeft = toLonLat(getBottomLeft(extent));
const topRight = toLonLat(getTopRight(extent));

const mapPoly = polygon([[
[wrapLon(bottomLeft[0]), topRight[1]], // Top left
[wrapLon(bottomLeft[0]), bottomLeft[1]], // Bottom left
[wrapLon(topRight[0]), bottomLeft[1]], // Bottom right
[wrapLon(topRight[0]), topRight[1]], // Top right
[wrapLon(bottomLeft[0]), topRight[1]], // Top left
]]);

// Update state with advisories that intersect with map extent
const resAdvisories = [];
if (advisories && advisories.length > 0) {
advisories.forEach(advisory => {
const advPoly = polygon(advisory.geometry.coordinates);
if (booleanIntersects(mapPoly, advPoly)) {
resAdvisories.push(advisory);
}
});
}
setAdvisoriesInView(resAdvisories);
}

// Advisories layer
const loadAdvisories = async () => {
// Fetch data if it doesn't already exist
if (!advisories) {
dispatch(updateAdvisories({
list: await getAdvisories(),
timeStamp: new Date().getTime()
}));
}
};

useEffect(() => {
// Remove layer if it already exists
if (mapLayers.current['advisoriesLayer']) {
Expand All @@ -824,6 +874,10 @@ export default function MapWrapper({

mapRef.current.addLayer(mapLayers.current['advisoriesLayer']);
mapLayers.current['advisoriesLayer'].setZIndex(55);

if (mapRef.current) {
mapRef.current.on('moveend', onMoveEnd);
}
}
}, [advisories]);

Expand Down Expand Up @@ -874,6 +928,7 @@ export default function MapWrapper({
loadWeather();
loadRegional();
loadRestStops();
loadAdvisories();

// Zoom/pan to route on route updates
if (!isInitialMount) {
Expand All @@ -887,6 +942,7 @@ export default function MapWrapper({
loadWeather();
loadRegional();
loadRestStops();
loadAdvisories();
}
};

Expand Down Expand Up @@ -1135,7 +1191,7 @@ export default function MapWrapper({
{!isPreview && (
<div className="routing-outer-container">
<RouteSearch routeEdit={true} />
<AdvisoriesOnMap />
<AdvisoriesOnMap advisories={advisoriesInView} />
</div>
)}

Expand Down
36 changes: 3 additions & 33 deletions src/frontend/src/Components/advisories/AdvisoriesOnMap.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
// React
import React, { useCallback, useEffect, useRef, useState } from 'react';

// Redux
import { useSelector, useDispatch } from 'react-redux'
import { memoize } from 'proxy-memoize'
import { updateAdvisories } from '../../slices/cmsSlice';
import React, { useState } from 'react';

// Components and functions
import { getAdvisories } from '../data/advisories.js';
import AdvisoriesList from './AdvisoriesList';

// Third party packages
Expand All @@ -21,33 +15,9 @@ import Button from 'react-bootstrap/Button';
// Styling
import './AdvisoriesOnMap.scss';

export default function AdvisoriesOnMap() {
// Redux
const dispatch = useDispatch();
const { advisories } = useSelector(useCallback(memoize(state => ({
advisories: state.cms.advisories.list,
}))));

// Refs
const isInitialMount = useRef(true);

// Data loading
const loadAdvisories = async () => {
if (!advisories) {
dispatch(updateAdvisories({
list: await getAdvisories(),
timeStamp: new Date().getTime()
}));
}
}
export default function AdvisoriesOnMap(props) {
const { advisories } = props;

useEffect(() => {
if (isInitialMount.current) { // Only run on initial load
loadAdvisories();
isInitialMount.current = false;
}
});

// States
const [open, setOpen] = useState(false);

Expand Down

0 comments on commit b141458

Please sign in to comment.