From 87fd986b35e5c4fe309bbcb6e6f767dddacbb9b1 Mon Sep 17 00:00:00 2001 From: Valerii Budko Date: Fri, 14 Jun 2024 09:35:41 +0100 Subject: [PATCH] Feature/core 4887 fux map (#343) * CORE-4887 docs * CORE-4887 All points set * CORE-4887 Clean * CORE-4887 Add icon style * CORE-4887 Icon size * Fix loading group * Fix loading group * Fix loading group --- README.md | 3 + main/global.css | 5 ++ modules/map/map.jsx | 109 ++++++++++++++--------------- pages/data-providers/index.jsx | 7 +- templates/data-providers/index.jsx | 54 +++++++------- 5 files changed, 88 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index e0df96dc..5cb43cb8 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,9 @@ npm run build # to build all files for next server (stored in .next folder) npm run start # to start simple development server ``` +Fix broken dependencies: +`npm install --legacy-peer-deps` + Server starts listen on `0.0.0.0:3000` [github-token]: https://github.com/settings/tokens diff --git a/main/global.css b/main/global.css index fac251ed..46579bc3 100644 --- a/main/global.css +++ b/main/global.css @@ -26,3 +26,8 @@ body, .leaflet-popup-tip { margin-top: -10px; } + +.leaflet-container .leaflet-bar a:first-child, +.leaflet-container .leaflet-bar a:last-child { + text-decoration: none; +} diff --git a/modules/map/map.jsx b/modules/map/map.jsx index 75fb3f33..3a1ea5da 100644 --- a/modules/map/map.jsx +++ b/modules/map/map.jsx @@ -1,86 +1,81 @@ -import React, { useRef, useEffect } from 'react' +import React, { useRef, useEffect, useState } from 'react' import L from 'leaflet' -import { MarkerClusterGroup } from 'leaflet.markercluster' - -import styles from './styles.module.css' +import 'leaflet.markercluster' import { getAssetsPath } from 'utils/helpers' -// somewhere in the middle of North Atlantic ocean +const KEY_MOVE = 'moveend' + const centerPosition = new L.LatLng(26.523257520856546, -43.10211013159716) const markerIcon = L.icon({ iconUrl: getAssetsPath('/static/images/map/marker.svg'), - iconSize: [32, 32], + iconSize: [18, 18], iconAnchor: [16, 32], popupAnchor: [0, -32], }) const CustomMap = ({ locations }) => { - const mapContainerRef = useRef(null) - const map = useRef(null) + const [visibleMarkers, setVisibleMarkers] = useState([]) + // const [mapLoaded, setMapLoaded] = useState(false) + + const mapRef = useRef(null) + + const loadVisibleMarkers = () => { + const bounds = mapRef.current.getBounds() + const inViewMarkers = locations.filter((loc) => + bounds.contains(new L.LatLng(loc.latitude, loc.longitude)) + ) + setVisibleMarkers(inViewMarkers) + } useEffect(() => { - const coverLayer = L.tileLayer( - 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - { - attribution: ` - OpenStreetMap under - CC-BY-SA - `, + // Initialize the map + if (locations.length > 0 && !mapRef.current) { + mapRef.current = L.map('map', { + center: centerPosition, + zoom: 2, minZoom: 1, maxZoom: 12, - } - ) + layers: [ + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: + '© OpenStreetMap contributors', + }), + ], + }) + // Handle map movements to load new markers + mapRef.current.on(KEY_MOVE, loadVisibleMarkers) + } - map.current = L.map(mapContainerRef.current, { - center: - locations[0]?.latitude && locations[0]?.longitude - ? new L.LatLng(locations[0]?.latitude, locations[0]?.longitude) - : centerPosition, - zoom: 1, - maxBounds: [ - [70, 180], - [-70, -180], - ], - layers: [coverLayer], - scrollWheelZoom: false, - }) - return () => map.current.remove() + // Initialize marker cluster group + const markerClusterGroup = new L.MarkerClusterGroup() + mapRef.current.addLayer(markerClusterGroup) + + return () => { + // Cleanup the map and markers + mapRef.current.off(KEY_MOVE, loadVisibleMarkers) + mapRef.current.remove() + mapRef.current = null + } }, []) useEffect(() => { - const markers = new MarkerClusterGroup({ - chunkedLoading: true, - icon: markerIcon, - }) - - locations.forEach(({ name, href, latitude, longitude }) => { - const marker = L.marker(new L.LatLng(latitude, longitude), { - title: name, + const markerClusterGroup = new L.MarkerClusterGroup() + // Create and add markers + visibleMarkers.forEach(({ name, href, latitude, longitude }) => { + const marker = L.marker([latitude, longitude], { icon: markerIcon, - }) - if (href) { - marker.bindPopup( - ` - ${name} - ` - ) - } else marker.bindPopup(name) - - markers.addLayer(marker) + }).bindPopup(href ? `${name}` : name) + markerClusterGroup.addLayer(marker) }) - map.current.addLayer(markers) + mapRef.current.addLayer(markerClusterGroup) - return () => map.current.removeLayer(markers) - }, [locations]) + return () => markerClusterGroup.clearLayers() + }, [visibleMarkers]) - return
+ return
} export default CustomMap diff --git a/pages/data-providers/index.jsx b/pages/data-providers/index.jsx index 41e9a821..869b0d61 100644 --- a/pages/data-providers/index.jsx +++ b/pages/data-providers/index.jsx @@ -18,12 +18,7 @@ export async function getServerSideProps({ query }) { props: { initialState: { dataProviders: { - data: - // TODO: Remove once https://github.com/vercel/next.js/issues/16122 is solved - // or once we migrate to backend search - normalizeDataProviders( - process.env.NODE_ENV === 'production' ? data : data.slice(0, 200) - ), + data: normalizeDataProviders(data), params: { ...Object.fromEntries( Object.entries(query).filter(([, v]) => v != null) diff --git a/templates/data-providers/index.jsx b/templates/data-providers/index.jsx index 2a862d5a..a0998fa9 100644 --- a/templates/data-providers/index.jsx +++ b/templates/data-providers/index.jsx @@ -8,23 +8,22 @@ import AddDataProviderForm from './form' import { formatNumber } from 'utils/format-number' import Search from 'modules/search-layout' +import Map from 'modules/map' -// REMOVE TEMP until data is correct - -// const filterAndMapDataProviders = (dataProviders) => -// dataProviders -// .filter( -// ({ name, dataProviderLocation }) => -// dataProviderLocation?.latitude != null && -// dataProviderLocation?.longitude != null && -// name -// ) -// .map(({ id, name, dataProviderLocation }) => ({ -// name, -// href: `/data-providers/${id}`, -// latitude: dataProviderLocation?.latitude, -// longitude: dataProviderLocation?.longitude, -// })) +const filterAndMapDataProviders = (dataProviders) => + dataProviders + .filter( + ({ name, dataProviderLocation }) => + dataProviderLocation?.latitude != null && + dataProviderLocation?.longitude != null && + name + ) + .map(({ id, name, dataProviderLocation }) => ({ + name, + href: `/data-providers/${id}`, + latitude: dataProviderLocation?.latitude, + longitude: dataProviderLocation?.longitude, + })) const getCountryName = (code) => { const countryName = countries[String(code).toUpperCase()] @@ -151,7 +150,11 @@ const DataProvidersSearchTemplate = React.memo( results={results} setDataProvidersOffset={setDataProvidersSize} > -
+
{showAddDataProviderForm ? ( - {/* // REMOVE TEMP until data is correct */} - - {/* {results.length > 0 && ( */} - {/* */} - {/* )} */} + {results.length > 0 && ( + + )}

We aggregate research papers from data providers all over the world including institutional and subject repositories and journal