Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into nextjs
Browse files Browse the repository at this point in the history
  • Loading branch information
K-Markopoulos committed Jan 23, 2025
2 parents fb2bdf1 + a3cb1ef commit 8bf40e3
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,6 @@ exports[`MultipleSensorsCharts should render with given state from Redux store 1
type="button"
>
Download
<span
class="MuiTouchRipple-root css-r3djoj-MuiTouchRipple-root"
/>
</button>
</mock-dialogactions>
</mock-dialog>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ describe('ReefCheckSurveyCard', () => {
);
}

it('should render date', () => {
it('should render correctly', () => {
const { getByText } = renderReefCheckSurveyCard();

expect(
getByText(`Date: ${new Date(mockReefCheckSurvey.date).toLocaleString()}`),
).toBeInTheDocument();
expect(
getByText(`Depth: ${mockReefCheckSurvey.depth}m`),
).toBeInTheDocument();
expect(getByText('User: Reef Check')).toBeInTheDocument();
});

it('should render user if submittedBy is present', () => {
Expand All @@ -48,7 +52,7 @@ describe('ReefCheckSurveyCard', () => {
'Count',
'INVERTEBRATES (2)',
'Count',
'BLEACHING AND CORAL DIDEASES',
'BLEACHING AND CORAL DISEASES',
'YES/NO',
'IMPACT',
'YES/NO',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ const ReefCheckSurveyCardComponent = ({
return (
<Paper className={classes.paper}>
<Box display="flex" justifyContent="space-between">
<Typography>Date: {new Date(survey.date).toLocaleString()}</Typography>
{survey.submittedBy && (
<Typography>User: {survey.submittedBy}</Typography>
)}
<Box display="flex" gap={2}>
<Typography>
Date: {new Date(survey.date).toLocaleString()}
</Typography>
<Typography>Depth: {survey.depth}m</Typography>
</Box>
<Typography>User: {survey.submittedBy ?? 'Reef Check'}</Typography>
</Box>
<TableContainer className={classes.tableRoot}>
<Table size="small">
Expand All @@ -75,7 +78,7 @@ const ReefCheckSurveyCardComponent = ({
</TableCell>
<TableCell>Count</TableCell>
<TableCell className={classes.label}>
BLEACHING AND CORAL DIDEASES
BLEACHING AND CORAL DISEASES
</TableCell>
<TableCell>YES/NO</TableCell>
<TableCell className={classes.label}>IMPACT</TableCell>
Expand Down
5 changes: 0 additions & 5 deletions packages/website/src/helpers/bleachingAlertIntervals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ export const findIntervalByLevel = (
}
};

export const findMaxLevel = (intervals: Interval[]): number => {
const levels = intervals.map((item) => item.level);
return Math.max(...levels);
};

export const getColorByLevel = (level: number): string => {
return findIntervalByLevel(level).color;
};
Expand Down
91 changes: 62 additions & 29 deletions packages/website/src/routes/HomeMap/Map/Markers/SiteMarker.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Marker, useMap } from 'react-leaflet';
import React from 'react';
import { CircleMarker, Marker } from 'react-leaflet';
import { useDispatch, useSelector } from 'react-redux';
import { Site } from 'store/Sites/types';
import {
siteOnMapSelector,
setSiteOnMap,
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 @@ -20,48 +21,80 @@ const LNG_OFFSETS = [-360, 0, 360];

interface SiteMarkerProps {
site: Site;
setCenter: (inputMap: L.Map, latLng: [number, number], zoom: number) => void;
}

/**
* All in one site marker with icon, offset duplicates, and popup built in.
*/
export default function SiteMarker({ site, setCenter }: SiteMarkerProps) {
const siteOnMap = useSelector(siteOnMapSelector);
const map = useMap();
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
eventHandlers={{
click: () => {
dispatch(setSearchResult());
dispatch(setSiteOnMap(site));
},
}}
key={`${site.id}-${offset}`}
center={[lat, lng + offset]}
radius={5}
fillColor={alertColorFinder(tempWeeklyAlert)}
fillOpacity={1}
color="black"
weight={1}
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 || {};
const markerIcon = useMarkerIcon(
hasDeployedSpotter(site),
site.hasHobo,
siteOnMap?.id === site.id,
isSelected,
alertColorFinder(tempWeeklyAlert),
alertIconFinder(tempWeeklyAlert),
);

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

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

return (
<>
{LNG_OFFSETS.map((offset) => {
return (
<Marker
eventHandlers={{
click: () => {
if (map) setCenter(map, [lat, lng], 6);
dispatch(setSearchResult());
dispatch(setSiteOnMap(site));
},
}}
key={`${site.id}-${offset}`}
icon={markerIcon}
position={[lat, lng + offset]}
>
<Popup site={site} autoOpen={offset === 0} />
</Marker>
);
})}
{LNG_OFFSETS.map((offset) => (
<Marker
eventHandlers={{
click: () => {
dispatch(setSearchResult());
dispatch(setSiteOnMap(site));
},
}}
key={`${site.id}-${offset}`}
icon={markerIcon}
position={[lat, lng + offset]}
data-alert={tempWeeklyAlert}
>
{isSelected && <Popup site={site} autoOpen={offset === 0} />}
</Marker>
))}
</>
);
}
});
96 changes: 13 additions & 83 deletions packages/website/src/routes/HomeMap/Map/Markers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,101 +1,31 @@
import { useSelector } from 'react-redux';
import { LayerGroup, useMap } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import { useCallback, useEffect, useState, useMemo } from 'react';
import L from 'leaflet';
import { useMemo } from 'react';
import { sitesToDisplayListSelector } from 'store/Sites/sitesListSlice';
import { Site } from 'store/Sites/types';
import { siteOnMapSelector } from 'store/Homepage/homepageSlice';
import 'leaflet/dist/leaflet.css';
import { CollectionDetails } from 'store/Collection/types';
import {
findIntervalByLevel,
findMaxLevel,
getColorByLevel,
Interval,
} from 'helpers/bleachingAlertIntervals';
import SiteMarker from './SiteMarker';
import { hasDeployedSpotter } from 'helpers/siteUtils';
import { CircleSiteMarker, SensorSiteMarker } from './SiteMarker';

const clusterIcon = (cluster: any) => {
const alerts: Interval[] = cluster.getAllChildMarkers().map((marker: any) => {
const { site } = marker?.options?.children?.[0]?.props || {};
const { tempWeeklyAlert } = site?.collectionData || {};
return findIntervalByLevel(tempWeeklyAlert);
});
const color = getColorByLevel(findMaxLevel(alerts));
const count = cluster.getChildCount();
return L.divIcon({
html: `<div style="background-color: ${color}"><span>${count}</span></div>`,
className: `leaflet-marker-icon marker-cluster custom-cluster-icon marker-cluster-small leaflet-zoom-animated leaflet-interactive`,
iconSize: L.point(40, 40, true),
});
};
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 siteOnMap = useSelector(siteOnMapSelector);
const map = useMap();
const [visibleSites, setVisibleSites] = useState(sitesList);

const setCenter = useCallback(
(inputMap: L.Map, latLng: [number, number], zoom: number) => {
const maxZoom = Math.max(inputMap.getZoom() || 6, zoom);
const pointBounds = L.latLngBounds(latLng, latLng);
inputMap.flyToBounds(pointBounds, {
duration: 2,
maxZoom,
paddingTopLeft: L.point(0, 200),
});
},
[],
);

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;
setCenter(map, [lat, lng], 6);
}
}, [map, siteOnMap, setCenter]);

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

Expand Down
20 changes: 19 additions & 1 deletion packages/website/src/routes/HomeMap/Map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import withStyles, {
} from '@mui/styles/withStyles';
import MyLocationIcon from '@mui/icons-material/MyLocation';
import { sitesListLoadingSelector } from 'store/Sites/sitesListSlice';
import { searchResultSelector } from 'store/Homepage/homepageSlice';
import {
searchResultSelector,
siteOnMapSelector,
} from 'store/Homepage/homepageSlice';
import { CollectionDetails } from 'store/Collection/types';
import { MapLayerName } from 'store/Homepage/types';
import { mapConstants } from 'constants/maps';
Expand Down Expand Up @@ -69,6 +72,7 @@ const HomepageMap = ({
const loading = useSelector(sitesListLoadingSelector);
const searchResult = useSelector(searchResultSelector);
const ref = useRef<LeafletMap>(null);
const siteOnMap = useSelector(siteOnMapSelector);

const onLocationSearch = () => {
if (navigator.geolocation) {
Expand Down Expand Up @@ -119,6 +123,20 @@ const HomepageMap = ({
// const onBaseLayerChange = ({ name }: LayersControlEvent) => {
// setLegendName(name);
// };
useEffect(() => {
const map = ref.current?.leafletElement;
if (map && siteOnMap?.polygon.type === 'Point') {
const [lng, lat] = siteOnMap.polygon.coordinates;
const latLng = [lat, lng] as [number, number];
const pointBounds = L.latLngBounds(latLng, latLng);
const maxZoom = Math.max(map.getZoom() || 6);
map.flyToBounds(pointBounds, {
duration: 2,
maxZoom,
paddingTopLeft: L.point(0, 200),
});
}
}, [siteOnMap]);

const ExpandIcon = showSiteTable ? FullscreenIcon : FullscreenExitIcon;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ const surveyFields = [
// eslint-disable-next-line prettier/prettier
] satisfies Array<NonNullable<SurveyFields[keyof SurveyFields]>>;

const formatFieldValue = (value: any, formatter?: (v: any) => string) => {
if (value != null && formatter) return formatter(value);
return value ?? '';
};

const ReefCheckSurveyDetailsComponent = ({
classes,
}: ReefCheckSurveyDetailsProps) => {
Expand All @@ -89,7 +94,7 @@ const ReefCheckSurveyDetailsComponent = ({
className={classes.skeleton}
/>
) : (
formatter?.(survey[field]) ?? survey[field] ?? ''
formatFieldValue(survey[field], formatter)
)}
</Typography>
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ exports[`renders as expected 1`] = `
<textarea
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline Form-textField-6 css-s43td4-MuiInputBase-input-MuiOutlinedInput-input"
id=":r6:"
id=":r3:"
name="installationResources"
placeholder="Please provide a description of the people that will be able to conduct periodic surveys and maintenance of the buoy. Please also include a description of the equipment (e.g. a boat, cameras) that are available."
style="height: 0px; overflow: hidden;"
Expand Down
Loading

0 comments on commit 8bf40e3

Please sign in to comment.