diff --git a/.gitignore b/.gitignore index b42ec396..21d3b519 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ dist node_modules .env* +.DS_Store +src/.DS_Store diff --git a/src/app.js b/src/app.js index fb5a61dd..0d0c9c20 100644 --- a/src/app.js +++ b/src/app.js @@ -1,6 +1,6 @@ import React, { Fragment } from 'react'; import { Map } from '@components/map'; -import ObservationDialog from "@components/map/observation-dialog"; +import { ObservationDialog } from "@components/map/observation-dialog"; import { useLayers } from '@context'; import { Sidebar } from '@components/sidebar'; diff --git a/src/components/map/default-layers.js b/src/components/map/default-layers.js index 53d987c1..99f46576 100644 --- a/src/components/map/default-layers.js +++ b/src/components/map/default-layers.js @@ -2,7 +2,7 @@ import React, { Fragment, useEffect, useState } from 'react'; import { WMSTileLayer, GeoJSON, useMap } from 'react-leaflet'; import { CircleMarker } from 'leaflet'; import { useLayers } from '@context'; -import { markClicked } from '@utils/map-utils'; +import { markClicked, markUnclicked } from '@utils/map-utils'; const newLayerDefaultState = layer => { const { product_type } = layer.properties; @@ -78,15 +78,14 @@ export const DefaultLayers = () => { this.closePopup(); }); layer.on("click", function (e) { - // Do stuff here for retrieving time series data, in csv fomat, - // from the feature.properties.csv_url and create a fancy plot - //console.log("Observation Station '" + feature.properties.location_name + "' clicked"); - markClicked(map, e); // add in a record id. // this is used to remove the selected observation from the selectedObservations list when the dialog is closed feature.properties.id = feature.properties.station_name; + // create a marker target icon around the observation clicked + markClicked(map, e, feature.properties.id); + // populate selectedObservations list with the newly selected observation point setSelectedObservations(previous => [...previous, feature.properties]); }); diff --git a/src/components/map/map.js b/src/components/map/map.js index d54bf614..7fb63715 100644 --- a/src/components/map/map.js +++ b/src/components/map/map.js @@ -17,7 +17,7 @@ export const Map = () => { zoom={5} zoomControl={false} scrollWheelZoom={true} - whenCreated={setMap} + ref={setMap} style={{ height: '100vh', width:'100wh' }}> { // get references to the observation data/list const { + map, selectedObservations, setSelectedObservations } = useLayers(); @@ -29,7 +31,7 @@ export default function ObservationDialog(obs_data) { }; // create an object for the base dialog - const floaterArgs = {title: obs_data.obs.location_name, dialogObject: {...graphObj(obs_data.obs.csvurl)}, dataKey: obs_data.obs.station_name, dataList: selectedObservations, setDataList: setSelectedObservations}; + const floaterArgs = {title: obs_data.obs.location_name, dialogObject: {...graphObj(obs_data.obs.csvurl)}, dataKey: obs_data.obs.station_name, dataList: selectedObservations, setDataList: setSelectedObservations, map: map}; // render the dialog. // the key here will be used to remove the dialog from the selected observation list when the dialog is closed diff --git a/src/utils/base-floating-dialog.js b/src/utils/base-floating-dialog.js index 013a2291..50aaf37e 100644 --- a/src/utils/base-floating-dialog.js +++ b/src/utils/base-floating-dialog.js @@ -10,6 +10,7 @@ import DialogContent from '@mui/material/DialogActions'; import DialogTitle from '@mui/material/DialogTitle'; import Paper from '@mui/material/Paper'; import Slide from '@mui/material/Slide'; +import { markUnclicked } from '@utils/map-utils'; // define the properties of this component BaseFloatingDialog.propTypes = { @@ -17,7 +18,8 @@ BaseFloatingDialog.propTypes = { dialogObject: PropTypes.any, dataKey: PropTypes.any, dataList: PropTypes.any, - setDataList: PropTypes.func + setDataList: PropTypes.func, + map: PropTypes.any, }; /** @@ -30,16 +32,16 @@ BaseFloatingDialog.propTypes = { * @param dataList: * @param setDataList: */ -export default function BaseFloatingDialog({ title, dialogObject, dataKey, dataList, setDataList} ) { +export default function BaseFloatingDialog({ title, dialogObject, dataKey, dataList, setDataList, map} ) { // define the dialog open/close session state //const [open, setOpen] = React.useState(true); - /** * the close dialog handler */ const handleClose = () => { // if there was a data key defined, use it if (dataKey !== undefined) { + markUnclicked(map, dataKey); // remove this item from the data list setDataList(dataList.filter(item => item.id !== dataKey)); } diff --git a/src/utils/map-utils.js b/src/utils/map-utils.js index bb46b5e6..fe91304e 100644 --- a/src/utils/map-utils.js +++ b/src/utils/map-utils.js @@ -12,16 +12,33 @@ import locationIcon from '@images/location_searching_FILL0_wght400_GRAD0_opsz24. // function to add a location marker where ever and obs mod layer // feature is clicked icon downloaded as png from here: // https://fonts.google.com/icons?selected=Material+Symbols+Outlined:location_searching:FILL@0;wght@400;GRAD@0;opsz@24&icon.query=location -export const markClicked = (map, event) => { +export const markClicked = (map, event, id) => { const L = window.L; + const iconSize = 38; + const iconAnchor = iconSize/2; const targetIcon = L.icon({ iconUrl: locationIcon, - iconSize: [38, 38], - iconAnchor: [19, 19], + iconSize: [iconSize, iconSize], + iconAnchor: [iconAnchor, iconAnchor], popupAnchor: [0, 0], }); - L.marker([event.latlng.lat, event.latlng.lng], {icon: targetIcon}).addTo(map); -}; \ No newline at end of file + const marker = L.marker([event.latlng.lat, event.latlng.lng], {icon: targetIcon}); + marker._id = id; + + marker.addTo(map); +}; + + +export const markUnclicked = (map, id) => { + + map.eachLayer((layer) => { + if (layer.options && layer.options.pane === "markerPane") { + if (layer._id === id) { + map.removeLayer(layer); + } + } + }); +} \ No newline at end of file