Skip to content

Commit

Permalink
Merge branch 'master' into reef-check-data
Browse files Browse the repository at this point in the history
  • Loading branch information
ericboucher authored Dec 2, 2024
2 parents 9260084 + 728e660 commit 5a58d06
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 99 deletions.
4 changes: 2 additions & 2 deletions packages/website/src/helpers/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ export const useSensorIcon = (
color: string,
) => {
const classes = useMarkerStyles();
const iconWidth = sensor === 'spotter' ? 20 : 25;
const iconHeight = sensor === 'spotter' ? 20 : 25;
const iconWidth = sensor === 'spotter' ? 15 : 20;
const iconHeight = sensor === 'spotter' ? 15 : 20;
return L.divIcon({
iconSize: [iconWidth, iconHeight],
iconAnchor: [iconWidth / 2, 0],
Expand Down
36 changes: 32 additions & 4 deletions packages/website/src/routes/HomeMap/Map/Markers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSelector } from 'react-redux';
import { LayerGroup, useLeaflet } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import React, { useCallback, useEffect } from 'react';
import React, { useCallback, useEffect, useState, useMemo } from 'react';
import L from 'leaflet';
import { sitesToDisplayListSelector } from 'store/Sites/sitesListSlice';
import { Site } from 'store/Sites/types';
Expand Down Expand Up @@ -34,9 +34,13 @@ const clusterIcon = (cluster: any) => {

export const SiteMarkers = ({ collection }: SiteMarkersProps) => {
const storedSites = useSelector(sitesToDisplayListSelector);
const sitesList = collection?.sites || storedSites || [];
const sitesList = useMemo(
() => collection?.sites || storedSites || [],
[collection?.sites, storedSites],
);
const siteOnMap = useSelector(siteOnMapSelector);
const { map } = useLeaflet();
const [visibleSites, setVisibleSites] = useState(sitesList);

const setCenter = useCallback(
(inputMap: L.Map, latLng: [number, number], zoom: number) => {
Expand All @@ -50,7 +54,31 @@ export const SiteMarkers = ({ collection }: SiteMarkersProps) => {
},
[],
);
// zoom in and center on site marker when it's clicked

const filterSitesByViewport = useCallback(() => {
if (!map) return;

const bounds = map.getBounds();
const filtered = sitesList.filter((site: Site) => {
if (!site.polygon || site.polygon.type !== 'Point') return false;
const [lng, lat] = site.polygon.coordinates;
return bounds.contains([lat, lng]);
});
setVisibleSites(filtered);
}, [map, sitesList]);

useEffect(() => {
if (!map) return undefined;

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

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

useEffect(() => {
if (map && siteOnMap?.polygon.type === 'Point') {
const [lng, lat] = siteOnMap.polygon.coordinates;
Expand All @@ -64,7 +92,7 @@ export const SiteMarkers = ({ collection }: SiteMarkersProps) => {
iconCreateFunction={clusterIcon}
disableClusteringAtZoom={1}
>
{sitesList.map((site: Site) => (
{visibleSites.map((site: Site) => (
<SiteMarker key={site.id} site={site} setCenter={setCenter} />
))}
</MarkerClusterGroup>
Expand Down
1 change: 1 addition & 0 deletions packages/website/src/routes/HomeMap/Map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ const HomepageMap = ({
id="sites-map"
ref={ref}
preferCanvas
renderer={L.canvas()}
maxBoundsViscosity={1.0}
className={classes.map}
center={initialCenter}
Expand Down
235 changes: 142 additions & 93 deletions packages/website/src/routes/HomeMap/SiteTable/body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
useTheme,
WithStyles,
withStyles,
TablePagination,
} from '@material-ui/core';
import ErrorIcon from '@material-ui/icons/Error';
import React, { useEffect, useMemo, useState } from 'react';
Expand All @@ -30,6 +31,7 @@ import { getComparator, Order, OrderKeys, stableSort } from './utils';
import { Collection } from '../../Dashboard/collection';

const SCROLLT_TIMEOUT = 500;
const ROWS_PER_PAGE = 200;

const RowNameCell = ({
site: { locationName, region },
Expand Down Expand Up @@ -133,16 +135,34 @@ const SiteTableBody = ({
);
const siteOnMap = useSelector(siteOnMapSelector);
const [selectedRow, setSelectedRow] = useState<number>();
const [page, setPage] = useState(0);

const theme = useTheme();
const isTablet = useMediaQuery(theme.breakpoints.down('sm'));

const mapElement = document.getElementById('sites-map');
const tableData = useMemo(
() =>
stableSort<Row>(
constructTableData(sitesList),
getComparator(order, orderBy),
),
[order, orderBy, sitesList],
);
const idToIndexMap = useMemo(
() =>
tableData.reduce((acc, item, index) => {
// eslint-disable-next-line fp/no-mutation
acc[item.tableData.id] = index;
return acc;
}, {} as Record<number, number>),
[tableData],
);

const handleClick = (event: unknown, site: Row) => {
setSelectedRow(site.tableData.id);
dispatch(setSearchResult());
dispatch(setSiteOnMap(sitesList[site.tableData.id]));
const mapElement = document.getElementById('sites-map');
if (scrollPageOnSelection && mapElement) {
mapElement.scrollIntoView({ block: 'center', behavior: 'smooth' });
}
Expand All @@ -155,102 +175,127 @@ const SiteTableBody = ({

// scroll to the relevant site row when site is selected.
useEffect(() => {
const child = document.getElementById(`homepage-table-row-${selectedRow}`);
if (selectedRow === undefined || idToIndexMap[selectedRow] === undefined)
return;
// Go to the page where the selected site is
setPage(Math.floor(idToIndexMap[selectedRow] / ROWS_PER_PAGE));
// only scroll if not on mobile (info at the top is more useful than the site row)
if (child && !isTablet && scrollTableOnSelection) {
setTimeout(
() => child.scrollIntoView({ block: 'center', behavior: 'smooth' }),
SCROLLT_TIMEOUT,
);
if (!isTablet && scrollTableOnSelection) {
setTimeout(() => {
const child = document.getElementById(
`homepage-table-row-${selectedRow}`,
);

child?.scrollIntoView({ block: 'center', behavior: 'smooth' });
}, SCROLLT_TIMEOUT);
}
}, [isTablet, scrollTableOnSelection, selectedRow]);
}, [idToIndexMap, isTablet, scrollTableOnSelection, selectedRow]);

// Handle page change
const handlePageChange = (event: unknown, newPage: number) => {
setPage(newPage);
};

return (
<TableBody>
{stableSort<Row>(
constructTableData(sitesList),
getComparator(order, orderBy),
).map((site) => {
return (
<TableRow
id={`homepage-table-row-${site.tableData.id}`}
hover
className={classes.tableRow}
style={{
backgroundColor:
site.tableData.id === selectedRow
? colors.lighterBlue
: 'white',
}}
onClick={(event) => handleClick(event, site)}
role="button"
tabIndex={-1}
key={site.tableData.id}
>
<RowNameCell
site={site}
classes={{
...classes,
nameCells: isExtended
? classes.extendedTableNameCells
: classes.nameCells,
}}
/>
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.sst}
color={isExtended ? colors.black : colors.lightBlue}
unit="°C"
/>
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.historicMax}
color={colors.black}
unit="°C"
/>
)}
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.sstAnomaly}
color={colors.black}
unit="°C"
/>
)}
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.dhw}
color={dhwColorFinder(site.dhw)}
unit="DHW"
/>
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.buoyTop}
color={colors.black}
unit="°C"
/>
)}
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.buoyBottom}
color={colors.black}
unit="°C"
/>
)}
<RowAlertCell site={site} classes={classes} />
</TableRow>
);
})}
</TableBody>
<>
<TableBody>
{stableSort<Row>(
constructTableData(sitesList),
getComparator(order, orderBy),
)
.slice(page * ROWS_PER_PAGE, page * ROWS_PER_PAGE + ROWS_PER_PAGE)
.map((site) => {
return (
<TableRow
id={`homepage-table-row-${site.tableData.id}`}
hover
className={classes.tableRow}
style={{
backgroundColor:
site.tableData.id === selectedRow
? colors.lighterBlue
: 'white',
}}
onClick={(event) => handleClick(event, site)}
role="button"
tabIndex={-1}
key={site.tableData.id}
>
<RowNameCell
site={site}
classes={{
...classes,
nameCells: isExtended
? classes.extendedTableNameCells
: classes.nameCells,
}}
/>
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.sst}
color={isExtended ? colors.black : colors.lightBlue}
unit="°C"
/>
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.historicMax}
color={colors.black}
unit="°C"
/>
)}
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.sstAnomaly}
color={colors.black}
unit="°C"
/>
)}
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.dhw}
color={dhwColorFinder(site.dhw)}
unit="DHW"
/>
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.buoyTop}
color={colors.black}
unit="°C"
/>
)}
{isExtended && (
<RowNumberCell
isExtended={isExtended}
classes={classes}
value={site.buoyBottom}
color={colors.black}
unit="°C"
/>
)}
<RowAlertCell site={site} classes={classes} />
</TableRow>
);
})}
</TableBody>
{sitesList.length > ROWS_PER_PAGE && (
<TablePagination
className={classes.stickyFooter}
count={sitesList.length}
rowsPerPage={ROWS_PER_PAGE}
rowsPerPageOptions={[ROWS_PER_PAGE]}
page={page}
onPageChange={handlePageChange}
/>
)}
</>
);
};

Expand Down Expand Up @@ -291,6 +336,10 @@ const styles = (theme: Theme) =>
cursor: 'pointer',
borderTop: `1px solid ${theme.palette.grey['300']}`,
},
stickyFooter: {
position: 'sticky',
bottom: 0,
},
});

type SiteTableBodyIncomingProps = {
Expand Down

0 comments on commit 5a58d06

Please sign in to comment.