Add a point on map from coordinates input

This commit is contained in:
Paul Chavard 2021-07-06 15:23:55 +02:00
parent ab31087f23
commit 527db7631e
7 changed files with 126 additions and 3 deletions

View file

@ -135,6 +135,11 @@
height: 18px;
}
.icon-size-big {
width: 25px;
height: 25px;
}
.state-button {
display: inline-block;
}

View file

@ -50,6 +50,10 @@
color: $black;
}
.mt-1 {
margin-top: $default-spacer;
}
.mt-2 {
margin-top: 2 * $default-spacer;
}

View file

@ -2,7 +2,15 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import ReactMapboxGl, { ZoomControl } from 'react-mapbox-gl';
import DrawControl from 'react-mapbox-gl-draw';
import { CursorClickIcon } from '@heroicons/react/outline';
import {
CursorClickIcon,
PlusIcon,
LocationMarkerIcon
} from '@heroicons/react/outline';
import CoordinateInput from 'react-coordinate-input';
import { fire } from '@utils';
import VisuallyHidden from '@reach/visually-hidden';
import { useId } from '@reach/auto-id';
import 'mapbox-gl/dist/mapbox-gl.css';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
@ -162,6 +170,87 @@ function MapEditor({ featureCollection, url, options, preview }) {
</div>
)}
</Mapbox>
<PointInput />
</>
);
}
function PointInput() {
const inputId = useId();
const [value, setValue] = useState('');
const [feature, setFeature] = useState(null);
const getCurrentPosition = () => {
navigator.geolocation &&
navigator.geolocation.getCurrentPosition(({ coords }) => {
setValue(
`${coords.latitude.toPrecision(6)}, ${coords.longitude.toPrecision(
6
)}`
);
});
};
const addPoint = () => {
if (feature) {
fire(document, 'map:feature:create', feature);
setValue('');
setFeature(null);
}
};
return (
<>
<label
className="areas-title mt-1"
htmlFor={inputId}
style={{ fontSize: '16px' }}
>
Ajouter un point sur la carte
</label>
<div className="flex align-center mt-1 mb-2">
{navigator.geolocation ? (
<button
type="button"
className="button mr-1"
onClick={getCurrentPosition}
title="Localiser votre position"
>
<VisuallyHidden>Localiser votre position</VisuallyHidden>
<LocationMarkerIcon className="icon-size-big" />
</button>
) : null}
<CoordinateInput
id={inputId}
className="m-0 mr-1"
value={value}
onChange={(value, { dd }) => {
setValue(value);
setFeature(
dd.length
? {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: dd.reverse()
},
properties: {}
}
: null
);
}}
/>
<button
type="button"
className="button"
onClick={addPoint}
disabled={!feature}
title="Ajouter le point avec les coordonnées saisies sur la carte"
>
<VisuallyHidden>
Ajouter le point avec les coordonnées saisies sur la carte
</VisuallyHidden>
<PlusIcon className="icon-size-big" />
</button>
</div>
</>
);
}

View file

@ -1,4 +1,4 @@
%li{ class: editing ? '' : 'flex column mb-2' }
%li{ class: editing ? 'mb-1' : 'flex column mb-2' }
- if editing
= link_to '#', data: { geo_area: geo_area.id } do
= geo_area_label(geo_area)

View file

@ -11,6 +11,7 @@
"@rails/webpacker": "5.1.1",
"@reach/combobox": "^0.13.0",
"@reach/slider": "^0.15.0",
"@reach/visually-hidden": "^0.15.2",
"@sentry/browser": "^5.15.5",
"@tmcw/togeojson": "^4.3.0",
"babel-plugin-macros": "^2.8.0",
@ -27,6 +28,7 @@
"match-sorter": "^6.2.0",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-coordinate-input": "^1.0.0-rc.2",
"react-dom": "^17.0.1",
"react-intersection-observer": "^8.31.0",
"react-mapbox-gl": "^5.1.1",

View file

@ -122,6 +122,9 @@ feature 'As an administrateur I can edit types de champ', js: true do
preview_window = window_opened_by { click_on 'Prévisualiser le formulaire' }
within_window(preview_window) do
expect(page).to have_content('Libellé de champ carte')
expect(page).to have_content('Ajouter un point sur la carte')
fill_in 'Ajouter un point sur la carte', with: "48°52'27\"N 002°54'32\"E"
click_on 'Ajouter le point avec les coordonnées saisies sur la carte'
end
end

View file

@ -1740,6 +1740,14 @@
tiny-warning "^1.0.3"
tslib "^2.1.0"
"@reach/visually-hidden@^0.15.2":
version "0.15.2"
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.15.2.tgz#07794cb53f4bd23a9452d53a0ad7778711ee323f"
integrity sha512-suDSCuKKuqiEB4UDgwWHbrPRxNwrusZ3ImXr85kfsQXGmKptMogaq22xoaHn32NC++lzZXxdWtAJriieszzFXw==
dependencies:
prop-types "^15.7.2"
tslib "^2.3.0"
"@sentry/browser@^5.15.5":
version "5.15.5"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.15.5.tgz#d9a51f1388581067b50d30ed9b1aed2cbb333a36"
@ -6597,6 +6605,11 @@ ignore@^5.1.1, ignore@^5.1.4:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
imask@^6.0.5:
version "6.1.0"
resolved "https://registry.yarnpkg.com/imask/-/imask-6.1.0.tgz#8dcf4c44c51c4297f691349b925b7d5b21edff1c"
integrity sha512-IuElVZpc7iuGw+CXfwoUZYpGdoD5H7cGo3S93gZPgjTTWfY5XAXCFL3g3b/ZJBZ18RG2dFF2kxAuuFlXMjq7oQ==
import-cwd@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
@ -10464,6 +10477,13 @@ rc@^1.2.8:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-coordinate-input@^1.0.0-rc.2:
version "1.0.0-rc.2"
resolved "https://registry.yarnpkg.com/react-coordinate-input/-/react-coordinate-input-1.0.0-rc.2.tgz#274aa920ba28318f515f22089ff2f6870a0e66bd"
integrity sha512-Umfnh0jEt/bKmIM+B/fT3QscL06CrRo0WRYIMEhgcieoeU5A54hR5WGjS7dKm33sMF5fywGXs7rZ/iyCk/N5yA==
dependencies:
imask "^6.0.5"
react-dom@^17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
@ -12263,7 +12283,7 @@ tslib@^2.0.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
tslib@^2.1.0:
tslib@^2.1.0, tslib@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==