From 9cad75838bbf96fd6cc6f1cdc3248e465787bac3 Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 3 May 2023 11:13:52 +0200 Subject: [PATCH] chore(rxPage): add missing changes After rebase develop some changes where missing --- package-lock.json | 1 + plugins/lime-plugin-locate/index.ts | 8 + plugins/lime-plugin-locate/src/locatePage.tsx | 239 ++++++++++++++++++ .../src/components/config/config.tsx | 21 +- 4 files changed, 262 insertions(+), 7 deletions(-) create mode 100644 plugins/lime-plugin-locate/index.ts create mode 100644 plugins/lime-plugin-locate/src/locatePage.tsx diff --git a/package-lock.json b/package-lock.json index 38a64a58..a8a567e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "redux": "^4.2.0", "redux-observable": "^2.0.0", "simple-color-scale": "^1.0.1", + "tailwindcss": "^3.2.6", "timeago.js": "^4.0.2" }, "devDependencies": { diff --git a/plugins/lime-plugin-locate/index.ts b/plugins/lime-plugin-locate/index.ts new file mode 100644 index 00000000..fc2045db --- /dev/null +++ b/plugins/lime-plugin-locate/index.ts @@ -0,0 +1,8 @@ +import { LocateMenu } from "./src/locateMenu"; +import Locate from "./src/locatePage"; + +export default { + name: "Locate", + page: Locate, + menu: LocateMenu, +} as LimePlugin; diff --git a/plugins/lime-plugin-locate/src/locatePage.tsx b/plugins/lime-plugin-locate/src/locatePage.tsx new file mode 100644 index 00000000..cc65c67f --- /dev/null +++ b/plugins/lime-plugin-locate/src/locatePage.tsx @@ -0,0 +1,239 @@ +import { Trans } from "@lingui/macro"; +import L, { LatLngExpression, icon } from "leaflet"; +import { useEffect, useRef, useState } from "preact/hooks"; +import { LayersControl, MapContainer, Marker, TileLayer } from "react-leaflet"; + +import { Loading } from "components/loading"; + +import { + useChangeLocation, + useLoadLeaflet, + useLocation, + useNodesandlinks, +} from "plugins/lime-plugin-locate/src/locateQueries"; + +import { useBoardData } from "utils/queries"; + +import { getCommunityGeoJSON } from "./communityGeoJSON"; +import { homeIcon } from "./leafletUtils"; +import style from "./style.less"; + +const openStreetMapTileString = "http://{s}.tile.osm.org/{z}/{x}/{y}.png"; +const openStreetMapAttribution = + '© OpenStreetMap contributors'; + +const gmSatellite = "https://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}"; +const gmHybrid = "https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}"; +const gmSubdomains = ["mt0", "mt1", "mt2", "mt3"]; + +function getCommunityLayer(nodeHostname, stationLat, stationLon, nodesData) { + /** Create a Leaflet layer with community nodes and links to be added to the map*/ + if (nodesData[nodeHostname]) { + nodesData[nodeHostname].data.coordinates = { + lat: stationLat, + lon: stationLon, + }; + } + // Get community GeoJSON, filter out nodes in same location as station host. + const geoJSON = getCommunityGeoJSON(nodesData, [stationLon, stationLat]); + return L.geoJSON(geoJSON, { + onEachFeature: (feature, layer) => { + if (feature.properties && feature.properties.name) { + layer.bindTooltip(feature.properties.name).openTooltip(); + } + }, + }); +} + +export const LocatePage = () => { + const { data: boardData } = useBoardData(); + const { + isError: isAssetError, + isFetchedAfterMount: assetsLoaded, + isLoading: isLoadingAssets, + } = useLoadLeaflet({ + refetchOnWindowFocus: false, + }); + + const { + data: nodeLocation, + isLoading: isLoadingLocation, + isFetched: locationLoaded, + } = useLocation({ + enabled: assetsLoaded, + }); + + const { data: nodesData } = useNodesandlinks({ + enabled: locationLoaded, + }); + + const { mutate: changeLocation, isLoading: submitting } = useChangeLocation( + { + onSettled: () => { + toogleEdition(); + }, + } + ); + + const loading = isLoadingLocation || isLoadingAssets; + const isCommunityLocation = nodeLocation.default; + const stationLat = + nodeLocation.location.lat !== "FIXME" + ? nodeLocation.location.lat + : null; + const stationLon = + nodeLocation.location.lon !== "FIXME" + ? nodeLocation.location.lon + : null; + const hasLocation = stationLat && !isCommunityLocation; + + const [editting, setEditting] = useState(false); + const [nodeMarker, setNodeMarker] = useState(null); + const [communityLayer, setCommunityLayer] = useState(null); + + const mapRef = useRef(); + + // Set map position when map is available or location gets updated + useEffect(() => { + function updateNodeMarker(lat, lon) { + setNodeMarker([lat, lon]); + } + const mapInstance = mapRef.current; + + if (!loading && mapInstance && stationLat) { + mapInstance.setView([+stationLat, +stationLon], 13); + updateNodeMarker(stationLat, stationLon); + } + }, [stationLat, stationLon, loading]); + + // Center the map on the node also when editting is turned on + useEffect(() => { + const map = mapRef.current; + if (map && stationLat) { + editting && map.setView([+stationLat, +stationLon], 13); + } + }, [mapRef, editting, stationLat, stationLon]); + + function onConfirmLocation() { + const position = mapRef.current.getCenter(); + changeLocation({ lat: position.lat, lon: position.lng }); + if (communityLayer) { + // Hide the community view, to avoid outdated links + toogleCommunityLayer(); + } + } + + function toogleCommunityLayer() { + if (communityLayer) { + mapRef.current.removeLayer(communityLayer); + setCommunityLayer(null); + } else { + const layer = getCommunityLayer( + boardData.hostname, + stationLat, + stationLon, + nodesData + ); + layer.addTo(mapRef.current); + setCommunityLayer(layer); + } + } + + function isReady() { + return !loading && typeof stationLat !== "undefined"; + } + + function toogleEdition() { + setEditting(!editting); + } + + if (isAssetError) { + return ( +
+ Cannot load map, check your internet connection +
+ ); + } + + return ( + <> + {(!isReady() || submitting) && ( +
+ +
+ )} + {isReady() && ( + + + + + + + + + + + + + {nodeMarker && ( + + )} + {editting && ( +
+ )} + + )} + {isReady() && ( +
+ {editting && ( + + )} + {!editting && ( + + )} + + +
+ )} + + ); +}; + +export default LocatePage; diff --git a/plugins/lime-plugin-node-admin/src/components/config/config.tsx b/plugins/lime-plugin-node-admin/src/components/config/config.tsx index e3cacb7f..f3c4792e 100644 --- a/plugins/lime-plugin-node-admin/src/components/config/config.tsx +++ b/plugins/lime-plugin-node-admin/src/components/config/config.tsx @@ -1,15 +1,17 @@ +import { ComponentChildren } from "preact"; + import { ListItem } from "components/list"; import Loading from "components/loading"; import style from "./config.style.less"; type ConfigProps = { - title: React.ReactNode, - subtitle?: React.ReactNode, - value: React.ReactNode, - onClick: () => void, - isLoading: boolean, -} + title: ComponentChildren; + subtitle?: ComponentChildren; + value: ComponentChildren; + onClick: () => void; + isLoading: boolean; +}; export const Config = ({ title, @@ -27,7 +29,12 @@ export const Config = ({ {isLoading && } {!isLoading && (
- {subtitle &&
{subtitle}
} + {subtitle && ( +
+ {" "} + {subtitle}{" "} +
+ )}
{value}
)}