Skip to content

Commit

Permalink
Use circle marker for buoys
Browse files Browse the repository at this point in the history
  • Loading branch information
K-Markopoulos committed Jan 17, 2025
1 parent 8c44c3f commit 919361f
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 77 deletions.
43 changes: 37 additions & 6 deletions packages/website/src/routes/HomeMap/Map/Markers/SiteMarker.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Marker } from 'react-leaflet';
import { CircleMarker, Marker } from 'react-leaflet';
import { useDispatch, useSelector } from 'react-redux';
import React from 'react';
import { Site } from 'store/Sites/types';
import {
setSiteOnMap,
setSearchResult,
isSelectedOnMapSelector,
setSearchResult,
setSiteOnMap,
} from 'store/Homepage/homepageSlice';
import { useMarkerIcon } from 'helpers/map';
import { hasDeployedSpotter } from 'helpers/siteUtils';
import {
alertColorFinder,
alertIconFinder,
} from 'helpers/bleachingAlertIntervals';
import { useMarkerIcon } from 'helpers/map';
import { hasDeployedSpotter } from 'helpers/siteUtils';
import Popup from '../Popup';

// To make sure we can see all the sites all the time, and especially
Expand All @@ -26,7 +26,38 @@ interface SiteMarkerProps {
/**
* All in one site marker with icon, offset duplicates, and popup built in.
*/
export const SiteMarker = React.memo(({ site }: SiteMarkerProps) => {
export const CircleSiteMarker = React.memo(({ site }: SiteMarkerProps) => {
const isSelected = useSelector(isSelectedOnMapSelector(site.id));
const dispatch = useDispatch();
const { tempWeeklyAlert } = site.collectionData || {};

if (site.polygon.type !== 'Point') return null;

const [lng, lat] = site.polygon.coordinates;

return (
<>
{LNG_OFFSETS.map((offset) => (
<CircleMarker
onclick={() => {
dispatch(setSearchResult());
dispatch(setSiteOnMap(site));
}}
key={`${site.id}-${offset}`}
color={alertColorFinder(tempWeeklyAlert)}
// icon={markerIcon}
center={[lat, lng + offset]}
radius={8}
data-alert={tempWeeklyAlert}
>
{isSelected && <Popup site={site} autoOpen={offset === 0} />}
</CircleMarker>
))}
</>
);
});

export const SensorSiteMarker = React.memo(({ site }: SiteMarkerProps) => {
const isSelected = useSelector(isSelectedOnMapSelector(site.id));
const dispatch = useDispatch();
const { tempWeeklyAlert } = site.collectionData || {};
Expand Down
74 changes: 12 additions & 62 deletions packages/website/src/routes/HomeMap/Map/Markers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,32 @@
import { useSelector } from 'react-redux';
import { useLeaflet } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import React, { useEffect, useState, useMemo } from 'react';
import L from 'leaflet';
import React, { useMemo } from 'react';
import { sitesToDisplayListSelector } from 'store/Sites/sitesListSlice';
import { Site } from 'store/Sites/types';
import 'leaflet/dist/leaflet.css';
import 'react-leaflet-markercluster/dist/styles.min.css';
import { CollectionDetails } from 'store/Collection/types';
import { getColorByLevel } from 'helpers/bleachingAlertIntervals';
import { countBy } from 'lodash';
import { createDonutChart } from 'helpers/map';
import { SiteMarker } from './SiteMarker';
import { hasDeployedSpotter } from 'helpers/siteUtils';
import { CircleSiteMarker, SensorSiteMarker } from './SiteMarker';

const clusterIcon = (cluster: any) => {
const alertLevels: number[] = cluster
.getAllChildMarkers()
.map((marker: any) => marker?.options?.['data-alert'] ?? 0);
const alertToCountMap = countBy(alertLevels);
const counts = Object.values(alertToCountMap);
const colors = Object.keys(alertToCountMap).map((level) =>
getColorByLevel(parseInt(level, 10)),
);
return L.divIcon({
html: createDonutChart(counts, colors),
});
};
const hasSpotter = (site: Site) => site.hasHobo || hasDeployedSpotter(site);

export const SiteMarkers = ({ collection }: SiteMarkersProps) => {
const storedSites = useSelector(sitesToDisplayListSelector);
const sitesList = useMemo(
() => collection?.sites || storedSites || [],
[collection?.sites, storedSites],
);
const { map } = useLeaflet();
const [visibleSitesMap, setVisibleSitesMap] = useState<
Record<string, boolean>
>({});

useEffect(() => {
// Incrementally mount visible site markers on map
// Avoid mounting all sites at once, mount only the visible ones and don't umount them

if (!map) return undefined;
const mountSitesInViewport = () => {
if (!map) return;
const bounds = map.getBounds();
const filtered: Record<string, boolean> = {};
sitesList.forEach((site: Site) => {
if (!site.polygon || site.polygon.type !== 'Point') return;
const [lng, lat] = site.polygon.coordinates;
if (bounds.contains([lat, lng])) {
// eslint-disable-next-line fp/no-mutation
filtered[site.id] = true;
}
});
// Keep the previous markers and add the new visible sites
setVisibleSitesMap((prev) => ({ ...prev, ...filtered }));
};

mountSitesInViewport();
map.on('moveend', mountSitesInViewport);

return () => {
map.off('moveend', mountSitesInViewport);
return undefined;
};
}, [map, sitesList]);

return (
<MarkerClusterGroup iconCreateFunction={clusterIcon}>
{sitesList.map(
(site: Site) =>
visibleSitesMap[site.id] && (
<SiteMarker key={`${site.id}`} site={site} />
),
<>
{sitesList.map((site: Site) =>
sitesList[site.id] && hasSpotter(site) ? (
<SensorSiteMarker key={`${site.id}`} site={site} />
) : (
<CircleSiteMarker key={`${site.id}`} site={site} />
),
)}
</MarkerClusterGroup>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,11 @@ exports[`renders as expected 1`] = `
</button>
<button
aria-colindex="4"
aria-current="date"
aria-selected="false"
class="MuiButtonBase-root MuiPickersDay-root MuiPickersDay-dayWithMargin MuiPickersDay-today css-qt9k9u-MuiButtonBase-root-MuiPickersDay-root"
class="MuiButtonBase-root MuiPickersDay-root MuiPickersDay-dayWithMargin css-wbk8ya-MuiButtonBase-root-MuiPickersDay-root"
data-timestamp="1736899200000"
role="gridcell"
tabindex="0"
tabindex="-1"
type="button"
>
15
Expand All @@ -563,11 +562,12 @@ exports[`renders as expected 1`] = `
</button>
<button
aria-colindex="6"
aria-current="date"
aria-selected="false"
class="MuiButtonBase-root MuiPickersDay-root MuiPickersDay-dayWithMargin css-wbk8ya-MuiButtonBase-root-MuiPickersDay-root"
class="MuiButtonBase-root MuiPickersDay-root MuiPickersDay-dayWithMargin MuiPickersDay-today css-qt9k9u-MuiButtonBase-root-MuiPickersDay-root"
data-timestamp="1737072000000"
role="gridcell"
tabindex="-1"
tabindex="0"
type="button"
>
17
Expand Down
33 changes: 29 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19702,7 +19702,16 @@ string-natural-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==

"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -19797,7 +19806,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand All @@ -19818,6 +19827,13 @@ strip-ansi@^5.1.0:
dependencies:
ansi-regex "^4.1.0"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
Expand Down Expand Up @@ -20776,7 +20792,7 @@ typeorm-seeding@^1.6.1:
reflect-metadata "0.1.13"
yargs "15.3.1"

typeorm@^0.3.18:
typeorm@^0.3.19:
version "0.3.20"
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.20.tgz#4b61d737c6fed4e9f63006f88d58a5e54816b7ab"
integrity sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==
Expand Down Expand Up @@ -21702,7 +21718,7 @@ [email protected]:
"@types/trusted-types" "^2.0.2"
workbox-core "6.5.4"

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -21720,6 +21736,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit 919361f

Please sign in to comment.