diff --git a/loko/authorizations/templates/authorizations/new_authorization_default.html b/loko/authorizations/templates/authorizations/new_authorization_default.html
index 7741564..183b108 100644
--- a/loko/authorizations/templates/authorizations/new_authorization_default.html
+++ b/loko/authorizations/templates/authorizations/new_authorization_default.html
@@ -219,9 +219,6 @@
-
@@ -478,52 +475,118 @@
if (!drawing) return;
addVertex(e.lngLat.lng, e.lngLat.lat);
});
+
+ map.on('dblclick', function (e) {
+ if (!drawing) return;
+ e.preventDefault();
+ handleDoubleClick();
+ });
}
function addVertex(lng, lat) {
vertices.push([lng, lat]);
+ const isFirst = markers.length === 0;
+
const el = document.createElement('div');
- el.style.cssText = 'width:10px;height:10px;border-radius:50%;background:#0d6efd;border:2px solid #fff;box-shadow:0 0 3px rgba(0,0,0,.4);cursor:pointer;';
+ if (isFirst) {
+ el.className = 'poly-marker poly-marker-first';
+ el.style.cssText = 'width:14px;height:14px;border-radius:50%;background:#198754;border:2px solid #fff;box-shadow:0 0 4px rgba(0,0,0,.5);cursor:pointer;transition:transform 0.15s;';
+ el.title = '{% translate "Cliquer pour fermer le polygone" %}';
+ el.addEventListener('mouseenter', function () {
+ if (vertices.length >= 3) el.style.transform = 'scale(1.3)';
+ });
+ el.addEventListener('mouseleave', function () {
+ el.style.transform = 'scale(1)';
+ });
+ el.addEventListener('click', function (ev) {
+ ev.stopPropagation();
+ if (vertices.length >= 3) {
+ finishPolygon();
+ }
+ });
+ } else {
+ el.className = 'poly-marker';
+ el.style.cssText = 'width:10px;height:10px;border-radius:50%;background:#0d6efd;border:2px solid #fff;box-shadow:0 0 3px rgba(0,0,0,.4);cursor:default;';
+ }
+
const marker = new maplibregl.Marker({ element: el }).setLngLat([lng, lat]).addTo(map);
markers.push(marker);
- // Clicking the first vertex closes the polygon
- if (markers.length === 1) {
- el.title = '{% translate "Cliquer pour fermer le polygone" %}';
- el.addEventListener('click', function (ev) {
- ev.stopPropagation();
- finishPolygon();
- });
- }
renderPreview();
+ updateGeoJSON();
+ updateHint();
+ }
+
+ function handleDoubleClick() {
+ if (!drawing) return;
+ // In MapLibre, dblclick triggers two click events first.
+ // Remove the duplicated last vertex if close to the preceding one.
+ if (vertices.length >= 2) {
+ const last = vertices[vertices.length - 1];
+ const prev = vertices[vertices.length - 2];
+ if (Math.hypot(last[0] - prev[0], last[1] - prev[1]) < 0.0001) {
+ vertices.pop();
+ const lastMarker = markers.pop();
+ if (lastMarker) lastMarker.remove();
+ }
+ }
+ if (vertices.length >= 3) {
+ finishPolygon();
+ }
+ }
+
+ function updateGeoJSON() {
+ if (vertices.length >= 3) {
+ const coords = [vertices.concat([vertices[0]])];
+ const geojson = JSON.stringify({ type: 'Polygon', coordinates: coords });
+ document.getElementById('id_geom_geojson').value = geojson;
+ } else {
+ document.getElementById('id_geom_geojson').value = '';
+ }
}
function renderPreview() {
if (!map.getSource('poly-preview')) return;
- const coords = vertices.length >= 3
- ? [vertices.concat([vertices[0]])]
- : [];
- const geojson = coords.length ? {
- type: 'Feature',
- geometry: { type: 'Polygon', coordinates: coords },
- } : { type: 'FeatureCollection', features: [] };
- map.getSource('poly-preview').setData(geojson);
+ if (vertices.length >= 3) {
+ const coords = [vertices.concat([vertices[0]])];
+ map.getSource('poly-preview').setData({
+ type: 'Feature',
+ geometry: { type: 'Polygon', coordinates: coords },
+ });
+ } else if (vertices.length === 2) {
+ map.getSource('poly-preview').setData({
+ type: 'Feature',
+ geometry: { type: 'LineString', coordinates: vertices },
+ });
+ } else {
+ map.getSource('poly-preview').setData({
+ type: 'FeatureCollection',
+ features: [],
+ });
+ }
}
- function finishPolygon() {
- if (vertices.length < 3) return;
- drawing = false;
- const geojson = JSON.stringify({ type: 'Polygon', coordinates: [vertices.concat([vertices[0]])] });
- document.getElementById('id_geom_geojson').value = geojson;
- renderPreview();
- updateUI(false);
- document.getElementById('poly-hint').textContent =
- '{% translate "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner." %}';
- map.getCanvas().style.cursor = 'default';
+ function updateHint() {
+ const hintEl = document.getElementById('poly-hint');
+ if (!hintEl) return;
+ if (!drawing) {
+ if (vertices.length >= 3 || document.getElementById('id_geom_geojson').value) {
+ hintEl.textContent = '{% translate "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner." %}';
+ } else {
+ hintEl.textContent = '{% translate "Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet pour fermer le polygone." %}';
+ }
+ return;
+ }
+
+ if (vertices.length <= 1) {
+ hintEl.textContent = '{% translate "Cliquez sur la carte pour ajouter des sommets." %}';
+ } else {
+ hintEl.textContent = '{% translate "Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet pour fermer le polygone." %}';
+ }
}
- function clearPolygon() {
- drawing = false;
+ function startDrawing() {
+ drawing = true;
vertices = [];
markers.forEach(m => m.remove());
markers = [];
@@ -531,35 +594,45 @@
if (map.getSource('poly-preview')) {
map.getSource('poly-preview').setData({ type: 'FeatureCollection', features: [] });
}
- updateUI(false);
- document.getElementById('poly-hint').textContent =
- '{% translate "Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter des sommets." %}';
- map.getCanvas().style.cursor = 'default';
+ map.doubleClickZoom.disable();
+ map.getCanvas().style.cursor = 'crosshair';
+ document.getElementById('poly-draw-btn').classList.add('active');
+ updateHint();
}
- function updateUI(isDrawing) {
- document.getElementById('poly-draw-btn').classList.toggle('d-none', isDrawing);
- document.getElementById('poly-finish-btn').classList.toggle('d-none', !isDrawing);
- map.getCanvas().style.cursor = isDrawing ? 'crosshair' : 'default';
+ function finishPolygon() {
+ if (vertices.length < 3) return;
+ drawing = false;
+ map.doubleClickZoom.enable();
+ map.getCanvas().style.cursor = 'default';
+ updateGeoJSON();
+ renderPreview();
+ document.getElementById('poly-draw-btn').classList.remove('active');
+ updateHint();
+ }
+
+ function clearPolygon() {
+ drawing = false;
+ map.doubleClickZoom.enable();
+ map.getCanvas().style.cursor = 'default';
+ vertices = [];
+ markers.forEach(m => m.remove());
+ markers = [];
+ document.getElementById('id_geom_geojson').value = '';
+ if (map.getSource('poly-preview')) {
+ map.getSource('poly-preview').setData({ type: 'FeatureCollection', features: [] });
+ }
+ document.getElementById('poly-draw-btn').classList.remove('active');
+ updateHint();
}
document.addEventListener('DOMContentLoaded', function () {
initMap();
document.getElementById('poly-draw-btn').addEventListener('click', function () {
- drawing = true;
- vertices = [];
- markers.forEach(m => m.remove());
- markers = [];
- if (map.getSource('poly-preview')) {
- map.getSource('poly-preview').setData({ type: 'FeatureCollection', features: [] });
- }
- updateUI(true);
- document.getElementById('poly-hint').textContent =
- '{% translate "Cliquez sur la carte pour ajouter des sommets. Cliquez sur le premier sommet pour fermer le polygone." %}';
+ startDrawing();
});
- document.getElementById('poly-finish-btn').addEventListener('click', finishPolygon);
document.getElementById('poly-clear-btn').addEventListener('click', clearPolygon);
// -----------------------------------------------------------------------