feat: create new base template for public occupation authorization requests

This commit is contained in:
Karl Determe 2026-08-25 10:08:36 +02:00
parent c90ee9ece5
commit cb9e8a1c8b

View file

@ -219,9 +219,6 @@
<button type="button" id="poly-draw-btn" class="btn btn-sm btn-outline-success"> <button type="button" id="poly-draw-btn" class="btn btn-sm btn-outline-success">
<i class="bi bi-pentagon"></i> {% translate "Dessiner un polygone" %} <i class="bi bi-pentagon"></i> {% translate "Dessiner un polygone" %}
</button> </button>
<button type="button" id="poly-finish-btn" class="btn btn-sm btn-success d-none">
<i class="bi bi-check-circle"></i> {% translate "Terminer" %}
</button>
<button type="button" id="poly-clear-btn" class="btn btn-sm btn-outline-danger"> <button type="button" id="poly-clear-btn" class="btn btn-sm btn-outline-danger">
<i class="bi bi-x-circle"></i> {% translate "Effacer" %} <i class="bi bi-x-circle"></i> {% translate "Effacer" %}
</button> </button>
@ -478,52 +475,118 @@
if (!drawing) return; if (!drawing) return;
addVertex(e.lngLat.lng, e.lngLat.lat); addVertex(e.lngLat.lng, e.lngLat.lat);
}); });
map.on('dblclick', function (e) {
if (!drawing) return;
e.preventDefault();
handleDoubleClick();
});
} }
function addVertex(lng, lat) { function addVertex(lng, lat) {
vertices.push([lng, lat]); vertices.push([lng, lat]);
const isFirst = markers.length === 0;
const el = document.createElement('div'); 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); const marker = new maplibregl.Marker({ element: el }).setLngLat([lng, lat]).addTo(map);
markers.push(marker); 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(); 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() { function renderPreview() {
if (!map.getSource('poly-preview')) return; if (!map.getSource('poly-preview')) return;
const coords = vertices.length >= 3 if (vertices.length >= 3) {
? [vertices.concat([vertices[0]])] const coords = [vertices.concat([vertices[0]])];
: []; map.getSource('poly-preview').setData({
const geojson = coords.length ? { type: 'Feature',
type: 'Feature', geometry: { type: 'Polygon', coordinates: coords },
geometry: { type: 'Polygon', coordinates: coords }, });
} : { type: 'FeatureCollection', features: [] }; } else if (vertices.length === 2) {
map.getSource('poly-preview').setData(geojson); map.getSource('poly-preview').setData({
type: 'Feature',
geometry: { type: 'LineString', coordinates: vertices },
});
} else {
map.getSource('poly-preview').setData({
type: 'FeatureCollection',
features: [],
});
}
} }
function finishPolygon() { function updateHint() {
if (vertices.length < 3) return; const hintEl = document.getElementById('poly-hint');
drawing = false; if (!hintEl) return;
const geojson = JSON.stringify({ type: 'Polygon', coordinates: [vertices.concat([vertices[0]])] }); if (!drawing) {
document.getElementById('id_geom_geojson').value = geojson; if (vertices.length >= 3 || document.getElementById('id_geom_geojson').value) {
renderPreview(); hintEl.textContent = '{% translate "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner." %}';
updateUI(false); } else {
document.getElementById('poly-hint').textContent = 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." %}';
'{% translate "Polygone enregistré. Cliquez sur « Dessiner » pour le redessiner." %}'; }
map.getCanvas().style.cursor = 'default'; 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() { function startDrawing() {
drawing = false; drawing = true;
vertices = []; vertices = [];
markers.forEach(m => m.remove()); markers.forEach(m => m.remove());
markers = []; markers = [];
@ -531,35 +594,45 @@
if (map.getSource('poly-preview')) { if (map.getSource('poly-preview')) {
map.getSource('poly-preview').setData({ type: 'FeatureCollection', features: [] }); map.getSource('poly-preview').setData({ type: 'FeatureCollection', features: [] });
} }
updateUI(false); map.doubleClickZoom.disable();
document.getElementById('poly-hint').textContent = map.getCanvas().style.cursor = 'crosshair';
'{% translate "Cliquez sur « Dessiner un polygone » puis cliquez sur la carte pour ajouter des sommets." %}'; document.getElementById('poly-draw-btn').classList.add('active');
map.getCanvas().style.cursor = 'default'; updateHint();
} }
function updateUI(isDrawing) { function finishPolygon() {
document.getElementById('poly-draw-btn').classList.toggle('d-none', isDrawing); if (vertices.length < 3) return;
document.getElementById('poly-finish-btn').classList.toggle('d-none', !isDrawing); drawing = false;
map.getCanvas().style.cursor = isDrawing ? 'crosshair' : 'default'; 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 () { document.addEventListener('DOMContentLoaded', function () {
initMap(); initMap();
document.getElementById('poly-draw-btn').addEventListener('click', function () { document.getElementById('poly-draw-btn').addEventListener('click', function () {
drawing = true; startDrawing();
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." %}';
}); });
document.getElementById('poly-finish-btn').addEventListener('click', finishPolygon);
document.getElementById('poly-clear-btn').addEventListener('click', clearPolygon); document.getElementById('poly-clear-btn').addEventListener('click', clearPolygon);
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------