Skip to content

Commit

Permalink
Merge pull request #316 from nowcommunity/map-select-locality
Browse files Browse the repository at this point in the history
Map select locality
  • Loading branch information
kaarleol authored Oct 13, 2024
2 parents 162b689 + 35bf4c4 commit dc147c2
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 17 deletions.
26 changes: 26 additions & 0 deletions cypress/e2e/locality.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,29 @@ describe("Locality min and max age checks work", () => {
cy.contains("11.63")
})
})

describe('Locality\'s Map works', () => {
beforeEach('Login as admin', () => {
cy.login('testSu')
})

// note that this changes only dec coordinates, dms is still the old one
it('Opening map view in edit works', () => {
cy.visit(`/locality/20920?tab=1`)
cy.contains('Coordinates')
cy.get('[id=edit-button]').click()
cy.contains('Latitude')
cy.contains('Open Map').click()
cy.contains('OpenStreetMap')
cy.contains('Leaflet')

cy.contains('Save').click()
cy.contains('OpenStreetMap').should('not.exist')
cy.contains('Longitude')
cy.contains('Finalize entry').click()
cy.contains('Complete and save').click()
cy.visit(`/locality/20920?tab=1`)
cy.contains('60.202665856')
cy.contains('24.957662836')
})
})
27 changes: 26 additions & 1 deletion frontend/src/components/Locality/Tabs/LocalityTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import { useForm } from 'react-hook-form'
import { EditableTable } from '@/components/DetailView/common/EditableTable'
import { EditingModal } from '@/components/DetailView/common/EditingModal'
import { emptyOption } from '@/components/DetailView/common/misc'
import { Map } from '@/components/Map/Map'
import { useState } from 'react'

export const LocalityTab = () => {
const { textField, radioSelection, dropdown, mode, bigTextField } = useDetailContext<LocalityDetailsType>()
const { editData, setEditData } = useDetailContext<LocalityDetailsType>()

const approximateCoordinatesOptions = [
{ display: 'No', value: 'false' },
Expand Down Expand Up @@ -83,14 +86,36 @@ export const LocalityTab = () => {
</EditingModal>
)

// Kumpula Coordinates, could be changed later to be existing coordinates if exists
const [coordinates, setCoordinates] = useState({ lat: 60.202665856, lng: 24.957662836 })

// ONLY dec coordinates, no conversion to dms yet
// eslint-disable-next-line @typescript-eslint/require-await
const onSaveCoord = async () => {
setEditData({ ...editData, dec_lat: coordinates.lat, dec_long: coordinates.lng })
return Object.keys(errors).length === 0 //no idea if this is needed, just copypasted
}

// TODO name this better, plagiarized from editingModal
const coordinateButton = (
<EditingModal buttonText="Open Map" onSave={onSaveCoord}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '1em' }}>
<Map coordinates={coordinates} setCoordinates={setCoordinates} />
</Box>
</EditingModal>
)

return (
<>
<HalfFrames>
<ArrayFrame half array={info} title="Info" />
<ArrayFrame half array={country} title="Country" />
</HalfFrames>

<ArrayFrame array={latlong} title="Latitude & Longitude" />
<Grouped>
<ArrayFrame array={latlong} title="Latitude & Longitude" />
{!mode.read && coordinateButton}
</Grouped>

<Grouped title="Synonyms">
{!mode.read && editingModal}
Expand Down
49 changes: 49 additions & 0 deletions frontend/src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useRef, useMemo } from 'react'
import { MapContainer, TileLayer, Marker } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'

type Coordinate = {
lat: number
lng: number
}

type CoordinateSetter = (Coordinate: Coordinate) => void

const DraggableMarker = ({ setMarkerPos, coord }: { setMarkerPos: CoordinateSetter; coord: Coordinate }) => {
const markerRef = useRef<L.Marker>(null)
const eventHandlers = useMemo(
() => ({
dragend() {
const marker = markerRef.current
if (marker != null) {
setMarkerPos(marker.getLatLng())
}
},
}),
[setMarkerPos]
)

return <Marker draggable={true} eventHandlers={eventHandlers} position={coord} ref={markerRef} />
}

export const Map = ({ coordinates, setCoordinates }: { coordinates: Coordinate; setCoordinates: CoordinateSetter }) => {
const mapRef = useRef(null)
const latitude = 30
const longitude = -5
document.title = 'Map'

return (
<div>
<MapContainer center={[latitude, longitude]} zoom={2} ref={mapRef} style={{ height: '50vh', width: '50vw' }}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<DraggableMarker coord={coordinates} setMarkerPos={setCoordinates} />
</MapContainer>
<p>
Lat: {coordinates ? coordinates.lat : null} Lon: {coordinates ? coordinates.lng : null}
</p>
</div>
)
}
70 changes: 70 additions & 0 deletions frontend/src/components/Map/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Map thoughts and stuff I'm writing, very incomplete bilingual documentation + thoughts

# Functionality for now

- there is a page for a map
- you can toggle drag of the marker by first clicking it and then clicking the pop-up text
- when the marker is draggable, you can double-click it to grab it
- then while holding the mouse button, you can move the marker around
- now you can see the lat/lng on the Map Page

### Thinking:
- OSM:n Tile Usage Policy.
- en tiedä mitä server-side rendering on, mut react-leaflet ei sovi sen kaa yhteen
- Make sure the map container has a defined height, for example by setting it in CSS: #map { height: 180px; }

OpenStreetMap tiles are fine for programming your Leaflet map, but read the Tile Usage Policy https://operations.osmfoundation.org/policies/tiles/ of OpenStreetMap if you’re going to use the tiles in production.

> OpenStreetMap data is free for everyone to use. Our tile servers are not.
> Because OpenStreetMap data is free, many other organisations provide map tiles made from OSM data. If your project doesn’t meet our requirements, you can get OSM-derived map tiles elsewhere.
Leaflet makes direct calls to the DOM when it is loaded, therefore React Leaflet is not compatible with server-side rendering.
https://medium.com/@timndichu/getting-started-with-leaflet-js-and-react-rendering-a-simple-map-ef9ee0498202


### TODO
TODO:
- show lat/lon DONE

- do things in Locality
- add button to locality
- open map in locality by pressing the button
- a small popup?
- add a way to click/drag a location
- some confirmation or show info or "is this ok?", maybe?
- add input from map to fields


### maybe later
- show country based on lat/lon?
- make the draggable marker always draggable

- add search bar to Map (by cities or something)
- make draggable marker move when a city is chosen
- make map move closer to the city when a city is chosen

### NOW_DATABASE test/current versiossa

Locality -> New -> get coordinates -button

-> popup.

Clicking on map => shows Lat + Long
- esim Latitude: 60.722200435142156, Longitude: 26.3671875

- sisältää myös "search location"
- jossa nuuksio tuo 1 tulos
- new york tuo 1 tulos
- new ei tuo mitään
- york tuo 2, both same from UK?
- Moscow ja joku muu jota pitäis olla useampi kaupunki, nii löyty vaan 1?

- tuloslista on tyyliä "Helsinki, Finland"
- tuloksen klikkaaminen ei muuta näkyvää Lat/Lon
- tulee marker kartalle
- sen klikkaaminen muuttaa Lat/Lon


### NOW_DATABASE dev versiossa
- ?

20 changes: 4 additions & 16 deletions frontend/src/components/MapPage.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
import { useRef } from 'react'
import { MapContainer, TileLayer } from 'react-leaflet'
import { Map } from './Map/Map'
import { useState } from 'react'
import 'leaflet/dist/leaflet.css'

export const MapPage = () => {
const mapRef = useRef(null)
const latitude = 30
const longitude = -5
const [coordinates, setCoordinates] = useState({ lat: 60.202665856, lng: 24.957662836 })

document.title = 'Map'

return (
<MapContainer center={[latitude, longitude]} zoom={2} ref={mapRef} style={{ height: '50vh', width: '50vw' }}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{/* Additional map layers or components can be added here */}
</MapContainer>
)
return <Map coordinates={coordinates} setCoordinates={setCoordinates} />
}

0 comments on commit dc147c2

Please sign in to comment.