mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-25 22:44:19 +00:00
✨ Complete map
This commit is contained in:
parent
115cff620e
commit
d289ff41bd
3 changed files with 98 additions and 27 deletions
|
@ -1,4 +1,4 @@
|
||||||
import React, { useCallback, useState, useRef, useMemo } from "react"
|
import React, { useCallback, useState, useRef, useMemo, useEffect } from "react"
|
||||||
import BoxFull from "../base/BoxFull"
|
import BoxFull from "../base/BoxFull"
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
||||||
import { faMapPin, faPlus } from "@fortawesome/free-solid-svg-icons"
|
import { faMapPin, faPlus } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
@ -10,9 +10,37 @@ import useRepositoryEditor from "../../hooks/useRepositoryEditor"
|
||||||
import Condition from "../../utils/Condition"
|
import Condition from "../../utils/Condition"
|
||||||
|
|
||||||
|
|
||||||
const STARTING_POSITION = [41.89309, 12.48289]
|
const STARTING_POSITION = {lat: 41.89309, lng: 12.48289}
|
||||||
const STARTING_ZOOM = 3
|
const STARTING_ZOOM = 3
|
||||||
|
|
||||||
|
// FIXME: this only works correctly at the equator!
|
||||||
|
/**
|
||||||
|
* https://wiki.openstreetmap.org/wiki/Zoom_levels
|
||||||
|
*/
|
||||||
|
const MPIXEL = [
|
||||||
|
156412,
|
||||||
|
78206,
|
||||||
|
39103,
|
||||||
|
19551,
|
||||||
|
9776,
|
||||||
|
4888,
|
||||||
|
2444,
|
||||||
|
1222,
|
||||||
|
610.984,
|
||||||
|
305.492,
|
||||||
|
152.746,
|
||||||
|
76.373,
|
||||||
|
38.187,
|
||||||
|
19.093,
|
||||||
|
9.547,
|
||||||
|
4.773,
|
||||||
|
2.387,
|
||||||
|
1.193,
|
||||||
|
0.596,
|
||||||
|
0.298,
|
||||||
|
0.149,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link BoxFull} that allows the user to select a geographical location to use to filter tweets.
|
* A {@link BoxFull} that allows the user to select a geographical location to use to filter tweets.
|
||||||
|
@ -22,35 +50,56 @@ const STARTING_ZOOM = 3
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export default function BoxConditionMap({ ...props }) {
|
export default function BoxConditionMap({ ...props }) {
|
||||||
const [position, setPosition] = useState({lat: STARTING_POSITION[0], lng: STARTING_POSITION[1]})
|
const [position, setPosition] = useState(STARTING_POSITION)
|
||||||
|
const [zoom, setZoom] = useState(STARTING_ZOOM)
|
||||||
|
const [map, setMap] = useState(null)
|
||||||
const {addCondition} = useRepositoryEditor()
|
const {addCondition} = useRepositoryEditor()
|
||||||
|
|
||||||
const markerRef = useRef(null)
|
const onMove = useCallback(
|
||||||
const eventHandlers = useMemo(
|
() => {
|
||||||
() => ({
|
setPosition(map.getCenter())
|
||||||
dragend() {
|
},
|
||||||
const marker = markerRef.current
|
[map]
|
||||||
if (marker != null) {
|
)
|
||||||
const pos = marker.getLatLng()
|
|
||||||
console.debug("Changing marker position to: ", pos)
|
const onZoom = useCallback(
|
||||||
setPosition(pos)
|
() => {
|
||||||
}
|
setZoom(map.getZoom())
|
||||||
},
|
},
|
||||||
}),
|
[map]
|
||||||
[],
|
)
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if(map === null) return
|
||||||
|
|
||||||
|
map.on("move", onMove)
|
||||||
|
map.on("zoom", onZoom)
|
||||||
|
return () => {
|
||||||
|
map.off("move", onMove)
|
||||||
|
map.off("zoom", onZoom)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[map]
|
||||||
)
|
)
|
||||||
|
|
||||||
const onButtonClick = () => {
|
const onButtonClick = () => {
|
||||||
|
const mapSize = map.getSize()
|
||||||
|
const minSize = Math.min(mapSize.x, mapSize.y)
|
||||||
|
const radius = minSize * MPIXEL[zoom]
|
||||||
|
|
||||||
addCondition(new Condition(
|
addCondition(new Condition(
|
||||||
"COORDINATES",
|
"COORDINATES",
|
||||||
`WIP WIP ${position.lat.toFixed(6)} ${position.lng.toFixed(6)}`
|
`< ${radius} ${position.lat} ${position.lng}`
|
||||||
))
|
))
|
||||||
setPosition({lat: STARTING_POSITION[0], lng: STARTING_POSITION[1]})
|
setPosition(STARTING_POSITION)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BoxFull
|
<BoxFull
|
||||||
header={<span>Search by <FontAwesomeIcon icon={faMapPin}/> zone</span>}
|
header={
|
||||||
|
<span>Search by <FontAwesomeIcon icon={faMapPin}/> zone</span>
|
||||||
|
}
|
||||||
childrenClassName={Style.BoxConditionMapContents}
|
childrenClassName={Style.BoxConditionMapContents}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
@ -58,19 +107,23 @@ export default function BoxConditionMap({ ...props }) {
|
||||||
center={STARTING_POSITION}
|
center={STARTING_POSITION}
|
||||||
zoom={STARTING_ZOOM}
|
zoom={STARTING_ZOOM}
|
||||||
className={Style.MapContainer}
|
className={Style.MapContainer}
|
||||||
|
whenCreated={setMap}
|
||||||
>
|
>
|
||||||
<TileLayer
|
<TileLayer
|
||||||
attribution='(c) <a href="https://osm.org/copyright">OpenStreetMap</a> contributors'
|
attribution='(c) <a href="https://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
/>
|
/>
|
||||||
<Marker ref={markerRef} draggable={true} position={position} eventHandlers={eventHandlers}/>
|
<div className={"leaflet-top leaflet-right"}>
|
||||||
|
<div className={"leaflet-control"}>
|
||||||
|
<ButtonIconOnly
|
||||||
|
className={Style.Button}
|
||||||
|
icon={faPlus}
|
||||||
|
color={"Green"}
|
||||||
|
onClick={onButtonClick}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</MapContainer>
|
</MapContainer>
|
||||||
<ButtonIconOnly
|
|
||||||
className={Style.Button}
|
|
||||||
icon={faPlus}
|
|
||||||
color={"Green"}
|
|
||||||
onClick={onButtonClick}
|
|
||||||
/>
|
|
||||||
</BoxFull>
|
</BoxFull>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,3 +9,6 @@
|
||||||
height: 300px;
|
height: 300px;
|
||||||
border-radius: 0 0 25px 25px;
|
border-radius: 0 0 25px 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Button {
|
||||||
|
}
|
|
@ -38,6 +38,21 @@ export default function ConditionBadge({ ...condition }) {
|
||||||
const icon = CONDITION_ICONS[type]
|
const icon = CONDITION_ICONS[type]
|
||||||
const {removeRawCondition} = useContext(ContextRepositoryEditor)
|
const {removeRawCondition} = useContext(ContextRepositoryEditor)
|
||||||
|
|
||||||
|
let displayedContent = content
|
||||||
|
if(type === 3) {
|
||||||
|
let split = displayedContent.split(" ")
|
||||||
|
let type = split[0]
|
||||||
|
let radius = Number.parseFloat(split[1]).toFixed(0)
|
||||||
|
let radiusType = "m"
|
||||||
|
if(radius >= 2000) {
|
||||||
|
radius = Math.round(radius / 1000)
|
||||||
|
radiusType = "km"
|
||||||
|
}
|
||||||
|
let lat = Number(split[2]).toFixed(3)
|
||||||
|
let lng = Number(split[3]).toFixed(3)
|
||||||
|
displayedContent = `${split[0]} ${radius}${radiusType} ${lat} ${lng}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
title={id ? `💠 Condition ID: ${id}` : "✨ New Condition"}
|
title={id ? `💠 Condition ID: ${id}` : "✨ New Condition"}
|
||||||
|
@ -47,7 +62,7 @@ export default function ConditionBadge({ ...condition }) {
|
||||||
<FontAwesomeIcon icon={icon}/>
|
<FontAwesomeIcon icon={icon}/>
|
||||||
</div>
|
</div>
|
||||||
<div className={Style.Text}>
|
<div className={Style.Text}>
|
||||||
{content}
|
{displayedContent}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ButtonSmallX onClick={() => {
|
<ButtonSmallX onClick={() => {
|
||||||
|
|
Loading…
Reference in a new issue