mirror of
https://git.rezel.net/LudoTech/traque.git
synced 2026-02-09 02:10:18 +01:00
Improvements on maps
This commit is contained in:
@@ -1,14 +1,67 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
|
||||
|
||||
export function List({array, children}) {
|
||||
// The elements of array have to be identified by a field id
|
||||
// TODO : change key
|
||||
return (
|
||||
<div className='w-full h-full bg-gray-300 overflow-y-auto'>
|
||||
<ul className="w-full p-1 divide-y-4 divide-gray-300">
|
||||
<div className='w-full h-full bg-gray-300 overflow-y-scroll'>
|
||||
<ul className="w-full p-1 pb-0">
|
||||
{array.map((elem, i) => (
|
||||
<li className="w-full" key={elem.id}>
|
||||
<li className="w-full" key={elem.id ?? i}>
|
||||
{children(elem, i)}
|
||||
<div className="w-full h-1"/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ReorderList({droppableId, array, setArray, children}) {
|
||||
const [arrayLocal, setArrayLocal] = useState(array);
|
||||
|
||||
useEffect(() => {
|
||||
setArrayLocal(array);
|
||||
}, [array])
|
||||
|
||||
function reorder(list, startIndex, endIndex) {
|
||||
const result = Array.from(list);
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
return result;
|
||||
};
|
||||
|
||||
function onDragEnd(result) {
|
||||
if (!result.destination) return;
|
||||
if (result.destination.index === result.source.index) return;
|
||||
const newArray = reorder(array, result.source.index, result.destination.index);
|
||||
setArrayLocal(newArray);
|
||||
setArray(newArray);
|
||||
}
|
||||
|
||||
return (
|
||||
<DragDropContext onDragEnd={onDragEnd} >
|
||||
<Droppable droppableId={droppableId}>
|
||||
{provided => (
|
||||
<div className='w-full h-full bg-gray-300 overflow-y-scroll' ref={provided.innerRef} {...provided.droppableProps}>
|
||||
<ul className="w-full p-1 pb-0">
|
||||
{arrayLocal.map((elem, i) => (
|
||||
<li className='w-full' key={elem.id}>
|
||||
<Draggable draggableId={elem.id.toString()} index={i}>
|
||||
{provided => (
|
||||
<div className='w-full' {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||
{children(elem, i)}
|
||||
<div className="w-full h-1"/>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useMap } from "react-leaflet";
|
||||
import { MapContainer, TileLayer, useMap } from "react-leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
|
||||
export function MapPan(props) {
|
||||
const DEFAULT_ZOOM = 14;
|
||||
|
||||
const mapStyles = {
|
||||
default: {
|
||||
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
},
|
||||
satellite: {
|
||||
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
|
||||
attribution: 'Tiles © Esri'
|
||||
},
|
||||
}
|
||||
|
||||
export function MapPan({center, zoom}) {
|
||||
const map = useMap();
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized && props.center) {
|
||||
map.flyTo(props.center, props.zoom, { animate: false });
|
||||
setInitialized(true)
|
||||
if (center, zoom) {
|
||||
map.flyTo(center, zoom, { animate: false });
|
||||
}
|
||||
}, [props.center]);
|
||||
}, [center, zoom]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -21,6 +32,8 @@ export function MapEventListener({ onLeftClick, onRightClick, onMouseMove }) {
|
||||
|
||||
// Handle the mouse click left
|
||||
useEffect(() => {
|
||||
if (!onLeftClick) return;
|
||||
|
||||
let moved = false;
|
||||
let downButton = null;
|
||||
|
||||
@@ -55,6 +68,7 @@ export function MapEventListener({ onLeftClick, onRightClick, onMouseMove }) {
|
||||
|
||||
// Handle the right click
|
||||
useEffect(() => {
|
||||
if (!onRightClick) return;
|
||||
|
||||
const handleMouseDown = (e) => {
|
||||
if (e.originalEvent.button == 2) {
|
||||
@@ -71,6 +85,8 @@ export function MapEventListener({ onLeftClick, onRightClick, onMouseMove }) {
|
||||
|
||||
// Handle the mouse move
|
||||
useEffect(() => {
|
||||
if (!onMouseMove) return;
|
||||
|
||||
map.on('mousemove', onMouseMove);
|
||||
|
||||
return () => {
|
||||
@@ -85,4 +101,42 @@ export function MapEventListener({ onLeftClick, onRightClick, onMouseMove }) {
|
||||
container.addEventListener('contextmenu', preventContextMenu);
|
||||
return () => container.removeEventListener('contextmenu', preventContextMenu);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function CustomMapContainer({mapStyle, children}) {
|
||||
const [location, setLocation] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (!navigator.geolocation) {
|
||||
console.log('Geolocation not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(pos) => {
|
||||
setLocation([pos.coords.latitude, pos.coords.longitude]);
|
||||
setLoading(false);
|
||||
},
|
||||
(err) => console.log("Error :", err),
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0
|
||||
}
|
||||
);
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <div className="w-full h-full"/>
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer className='w-full h-full' center={location} zoom={DEFAULT_ZOOM} scrollWheelZoom={true}>
|
||||
<TileLayer url={(mapStyle || mapStyles.default).url} attribution={(mapStyle || mapStyles.default).attribution}/>
|
||||
{children}
|
||||
</MapContainer>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user