Skip to content

Commit

Permalink
Merge branch 'sprint-release' into dev-c
Browse files Browse the repository at this point in the history
  • Loading branch information
CelineMP committed Jun 3, 2024
2 parents c5a4a73 + 1a70a74 commit caba92f
Show file tree
Hide file tree
Showing 13 changed files with 42,669 additions and 385 deletions.
643 changes: 353 additions & 290 deletions frontend/package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
"@phosphor-icons/react": "^2.1.5",
"@types/autosuggest-highlight": "^3.2.3",
"@types/geojson": "^7946.0.14",
"@types/leaflet.markercluster": "^1.5.4",
"@types/proj4leaflet": "^1.0.10",
"autosuggest-highlight": "^3.3.4",
"axios": "^1.7.2",
"geojson": "^0.5.0",
"leaflet": "^1.9.4",
"leaflet-geosearch": "^4.0.0",
"leaflet.markercluster": "^1.5.3",
"proj4leaflet": "^1.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-leaflet": "^4.2.1"
Expand Down
14 changes: 6 additions & 8 deletions frontend/src/components/DatasetsList/DatasetsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,10 @@ import { TabProps, TabsContext } from "../../contexts/TabsContext";
import "./DatasetsList.css";
import { AlertContext } from "../../contexts/AlertContext";
import { FeatureCollection } from "geojson";
import L, { Icon as LIcon, DivIcon } from "leaflet";
import L, { Icon as LIcon, DivIcon, LatLngBounds } from "leaflet";
import { createRoot } from "react-dom/client";
import { flushSync } from "react-dom";

// Enum for types of markers
enum MarkersTypes {
Markers = "markers", // Map will display single coordinates with markers on top.
Areas = "areas", // Map will display polygon areas.
None = "none", // Map will not display anything.
}
import { MarkersTypes } from "./MarkersTypes";

// Dataset Type
export type Dataset = {
Expand All @@ -38,6 +32,7 @@ export type Dataset = {
datasetIcon: Icon;
markerIcon: LIcon | DivIcon | undefined;
data: FeatureCollection;
lastDataRequestBounds: LatLngBounds;
};

// Define an empty FeatureCollection
Expand Down Expand Up @@ -72,6 +67,7 @@ const datasetsData: Dataset[] = [
datasetIcon: MapTrifold,
markerIcon: undefined,
data: emptyFeatureCollection,
lastDataRequestBounds: L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0)),
},
{
id: "charging_stations",
Expand All @@ -81,6 +77,7 @@ const datasetsData: Dataset[] = [
datasetIcon: ChargingStation,
markerIcon: divIconChargingStation,
data: emptyFeatureCollection,
lastDataRequestBounds: L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0)),
},
{
id: "house_footprints",
Expand All @@ -90,6 +87,7 @@ const datasetsData: Dataset[] = [
datasetIcon: Blueprint,
markerIcon: undefined,
data: emptyFeatureCollection,
lastDataRequestBounds: L.latLngBounds(L.latLng(0, 0), L.latLng(0, 0)),
},
];

Expand Down
6 changes: 6 additions & 0 deletions frontend/src/components/DatasetsList/MarkersTypes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Enum for types of markers
export enum MarkersTypes {
Markers = "markers", // Map will display single coordinates with markers on top.
Areas = "areas", // Map will display polygon areas.
None = "none", // Map will not display anything.
}
63 changes: 42 additions & 21 deletions frontend/src/components/MapView/DataFetch.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { FeatureCollection, Geometry } from "geojson";
import defaultCityLocationData from "./FeatureCollection.json";
import defaultPolygonData from "./gemeinden_simplify20.json";
import defaultPolygonData from "./output1000.json";
import { LatLngBounds } from "leaflet";
import { useContext, useEffect, useState } from "react";
import axios from "axios";
import { TabsContext } from "../../contexts/TabsContext";
import { AlertContext } from "../../contexts/AlertContext";
import axios from "axios";
const geojsonCities: FeatureCollection =
defaultCityLocationData as FeatureCollection;
const geojsonGemeindenPolygons: FeatureCollection =
Expand Down Expand Up @@ -32,11 +33,18 @@ const useGeoData = (
id: string,
bounds: LatLngBounds,
zoom: number,
onUpdate: (data: FeatureCollection<Geometry>) => void

onUpdate: (data: FeatureCollection<Geometry>, bounds: LatLngBounds) => void
): FeatureCollection<Geometry> | undefined => {
const [data, setData] = useState<FeatureCollection<Geometry>>();
const { currentAlertCache, setCurrentAlertCache } = useContext(AlertContext);

const { currentTabsCache } = useContext(TabsContext);

const tabProps = currentTabsCache.openedTabs.find(
(tab) => tab.dataset.id === id
);

// Returns the API URL of the endpoint for a specific dataset
const getApiUrlForDataset = (): string => {
switch (id) {
Expand All @@ -58,35 +66,48 @@ const useGeoData = (
};

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const fetchData = async (_bounds: LatLngBounds): Promise<void> => {
// Skip if just an empty map was loaded
if (id === "empty_map") {
return;
if (id === "empty_map") return;
if (tabProps && tabProps.dataset.lastDataRequestBounds === bounds) {
console.log("SAME AS LAST TIME");
return;
}
if (tabProps && tabProps.dataset.type === "markers" && zoom <= 10) {
setData(undefined);
console.log("too far away");
return;
}
if (id === "house_footprints") {
if (tabProps?.dataset.data.features.length == 0) {
setData(geojsonGemeindenPolygons as FeatureCollection<Geometry>);
onUpdate(geojsonGemeindenPolygons, bounds);
} else {
setData(geojsonGemeindenPolygons as FeatureCollection<Geometry>);
//console.log("already loaded house_footprints");
}

return;
}
const fetchData = async (bounds: LatLngBounds): Promise<void> => {
try {
// const bottomLat = bounds.getSouth();
// const bottomLong = bounds.getWest();
// const topLat = bounds.getNorth();
// const topLong = bounds.getEast();
console.log(getBaseApiUrl());
// Define the query parameters
const params = {
BottomLat: 9, // bottomLat,
BottomLong: 10, //bottomLong,
TopLat: 48, //topLat,
TopLong: 49, //topLong,
BottomLat: bounds.getSouthWest().lat, // bottomLat,
BottomLong: bounds.getSouthWest().lng, //bottomLong,
TopLat: bounds.getNorthEast().lat, //topLat,
TopLong: bounds.getNorthEast().lng, //topLong,
ZoomLevel: zoom,
};
console.log(getApiUrlForDataset());
//console.log(getApiUrlForDataset());
const url = `http://localhost:8081/api/v1.0/Dataset/1/data?BottomLat=${params.BottomLat}&BottomLong=${params.BottomLong}&TopLat=${params.TopLat}&TopLong=${params.TopLong}`;
console.log(url);
const response = await axios.get<FeatureCollection<Geometry>>(
getApiUrlForDataset(),
{
params,
}
);
setData(response.data);
onUpdate(response.data);
onUpdate(response.data, bounds);
} catch (error) {
// Display alert
// setCurrentAlertCache({
Expand All @@ -105,11 +126,11 @@ const useGeoData = (
switch (id) {
case "charging_stations":
setData(geojsonCities as FeatureCollection<Geometry>);
onUpdate(geojsonCities);
onUpdate(geojsonCities, bounds);
return;
case "house_footprints":
setData(geojsonGemeindenPolygons as FeatureCollection<Geometry>);
onUpdate(geojsonGemeindenPolygons);
onUpdate(geojsonGemeindenPolygons, bounds);
return;
default:
return;
Expand Down
124 changes: 124 additions & 0 deletions frontend/src/components/MapView/MapDatasetVisualizer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { useMap } from "react-leaflet";
import { Dataset } from "../DatasetsList/DatasetsList";
import { useCallback, useContext, useEffect } from "react";
import { FeatureCollection } from "geojson";
import { MapContext } from "../../contexts/MapContext";
import { TabsContext } from "../../contexts/TabsContext";
import useGeoData from "./DataFetch";
import L from "leaflet";
import { LatLngBounds } from "leaflet";
import "proj4leaflet";
import "proj4";

interface MapDatasetVisualizerProps {
dataset: Dataset;
}

const MapDatasetVisualizer: React.FC<MapDatasetVisualizerProps> = ({
dataset,
}) => {
const map = useMap();
const { currentMapCache } = useContext(MapContext);
const { setCurrentTabsCache } = useContext(TabsContext);

const updateDatasetData = useCallback(
(newData: FeatureCollection, bounds: LatLngBounds) => {
setCurrentTabsCache((prevCache) => {
const updatedTabs = prevCache.openedTabs.map((tab) => {
if (tab.dataset.id === dataset.id) {
return {
...tab,
dataset: {
...tab.dataset,
lastDataRequestBounds: bounds,
data: newData,
},
};
}
return tab;
});

return {
...prevCache,
openedTabs: updatedTabs,
};
});
},
[dataset.id, setCurrentTabsCache]
);
const geoData = useGeoData(
dataset.id,
currentMapCache.mapBounds,
currentMapCache.zoom,
updateDatasetData
);
const myCRS = new L.Proj.CRS(
"EPSG:25832",
"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
);
const coordsToLatLngWithCRS = (coords: number[]) => {
const latLng = myCRS.unproject(L.point(coords[0], coords[1]));
return latLng;
};

useEffect(() => {
if (!geoData) return;

if (dataset.id === "house_footprints") {
console.log("hi from data visualizer");

if (currentMapCache.zoom < 13) {
const markerClusterGroup = L.markerClusterGroup();
L.geoJson(geoData, {
coordsToLatLng: coordsToLatLngWithCRS,
onEachFeature: function (feature, featureLayer) {
if (feature.geometry.type === "Polygon") {
const bounds = (
featureLayer as unknown as { getBounds: () => L.LatLngBounds }
).getBounds();
const center = bounds.getCenter();
const marker = L.marker(center);
marker.addTo(markerClusterGroup);
}
},
});

//map.fitBounds(g.getBounds());
map.addLayer(markerClusterGroup);
return () => {
map.removeLayer(markerClusterGroup);
};
} else {
const geojsonLayer = L.geoJson(geoData, {
coordsToLatLng: coordsToLatLngWithCRS,
});
geojsonLayer.addTo(map);

return () => {
map.removeLayer(geojsonLayer);
};
}
} else {
const geojsonLayer = L.geoJson(geoData, {
pointToLayer: function (_feature, latlng) {
return L.marker(latlng, { icon: dataset.markerIcon });
},

style: { fillOpacity: 0.1 },
});
const markerClusterGroup = L.markerClusterGroup();

markerClusterGroup.addLayer(geojsonLayer);
map.addLayer(markerClusterGroup);

return () => {
map.removeLayer(markerClusterGroup);
};
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataset, currentMapCache.zoom, map, geoData]);

return null;
};

export default MapDatasetVisualizer;
1 change: 1 addition & 0 deletions frontend/src/components/MapView/MapEventsHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const MapEventsHandler = () => {
});
},
moveend: (event) => {
console.log("updates");
setCurrentMapCache({
...currentMapCache,
mapCenter: event.target.getCenter(),
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/MapView/MapOptions.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//import { useState } from "react";
import { Stack } from "@phosphor-icons/react";
import { useState } from "react";
import { ArrowsClockwise } from "@phosphor-icons/react";
import "./MapOptions.css";
import { Tooltip } from "@mui/material";
//import SearchPopUp from "../PopUp/SearchPopUp";
Expand Down Expand Up @@ -31,7 +33,10 @@ const MapOptions: React.FC<MapOptionsProps> = ({ toggleShowSatellite }) => {
</Tooltip> */}
<Tooltip arrow title="Switch layers" placement="right">
<div className="layers-map-icon-container leaflet-touch leaflet-bar leaflet-control leaflet-control-custom">
<Stack className="layers-map-icon" onClick={toggleShowSatellite} />
<ArrowsClockwise
/** ArrowsClockwise requested from po. stack only if we have more than 2 backgrounds */ className="layers-map-icon"
onClick={toggleShowSatellite}
/>
</div>
</Tooltip>
{/* <SearchPopUp
Expand Down
Loading

0 comments on commit caba92f

Please sign in to comment.