From 090c7dd03ca685496c2dd41aa073f2f9a8935b1a Mon Sep 17 00:00:00 2001 From: kdeterme Date: Mon, 21 Sep 2026 11:38:52 +0200 Subject: [PATCH] refactor: integrate plans and calques into LayerSwitcherControl and remove custom plans control --- .../trafficlights_intersection_detail.js | 555 ++++++++++++------ .../trafficlights_intersection_detail.html | 107 +--- .../static/common/layer-switcher-control.js | 225 ++++++- 3 files changed, 598 insertions(+), 289 deletions(-) diff --git a/loko/assets/static/assets/trafficlights_intersection_detail.js b/loko/assets/static/assets/trafficlights_intersection_detail.js index 11f639d..d005f8f 100644 --- a/loko/assets/static/assets/trafficlights_intersection_detail.js +++ b/loko/assets/static/assets/trafficlights_intersection_detail.js @@ -10,37 +10,7 @@ const map = new maplibregl.Map({ antialias: true }); -// Custom Plans Control in Top Right (first, at the top) -class CustomPlansControl { - onAdd(map) { - this._container = document.createElement('div'); - this._container.className = 'maplibregl-ctrl maplibregl-ctrl-group'; - - const button = document.createElement('button'); - button.type = 'button'; - button.id = 'btn-load-georef-plan'; - button.className = 'btn btn-xs btn-light bg-white border shadow-sm d-flex align-items-center gap-1'; - button.style.border = 'none'; - button.style.padding = '8px 12px'; - button.style.height = 'auto'; - button.style.width = 'auto'; - button.style.fontWeight = 'bold'; - button.style.fontSize = '0.75rem'; - button.innerHTML = ' Plans'; - - // Toggle bootstrap modal natively - button.setAttribute('data-bs-toggle', 'modal'); - button.setAttribute('data-bs-target', '#georefPlanModal'); - - this._container.appendChild(button); - return this._container; - } - onRemove() { - this._container.parentNode.removeChild(this._container); - this._map = undefined; - } -} -map.addControl(new CustomPlansControl(), 'top-right'); +// Plans & Calques are integrated into LayerSwitcherControl below // ── Helper to determine where to place the orthophoto layer ── function getOrthoBeforeLayer(m) { @@ -140,9 +110,10 @@ function reorderIntersectionLayers() { }); } -// --- Contrôle photo aérienne (LayerSwitcherControl) --- (second, below Plans button) +// --- Contrôle photo aérienne & Plans (LayerSwitcherControl) --- +let layerSwitcher = null; if (typeof LayerSwitcherControl !== 'undefined') { - const layerSwitcher = new LayerSwitcherControl({ + layerSwitcher = new LayerSwitcherControl({ layers: [ { id: 'ortho', @@ -883,7 +854,25 @@ if (georeferencedDocumentsDataEl) { } } +const dxfFilesDataEl = document.getElementById('dxfFilesData'); +let dxfFiles = []; +if (dxfFilesDataEl) { + try { + dxfFiles = JSON.parse(dxfFilesDataEl.textContent); + } catch (e) { + console.error("Error parsing dxf files data:", e); + } +} +const crossroadPlansConfigEl = document.getElementById('crossroadPlansConfig'); +let crossroadPlansConfig = {}; +if (crossroadPlansConfigEl) { + try { + crossroadPlansConfig = JSON.parse(crossroadPlansConfigEl.textContent); + } catch (e) { + console.error("Error parsing crossroad plans config:", e); + } +} function showGeorefImage(doc, active, opacity) { const srcId = `georef-image-overlay-${doc.id}`; @@ -932,11 +921,13 @@ function showGeorefImage(doc, active, opacity) { } // Zoom/fitBounds to document - const coords = doc.coords; - const bounds = coords.reduce((acc, coord) => { - return acc.extend(coord); - }, new maplibregl.LngLatBounds(coords[0], coords[0])); - map.fitBounds(bounds, { padding: 40, maxZoom: 19 }); + if (doc.coords && doc.coords.length > 0) { + const coords = doc.coords; + const bounds = coords.reduce((acc, coord) => { + return acc.extend(coord); + }, new maplibregl.LngLatBounds(coords[0], coords[0])); + map.fitBounds(bounds, { padding: 40, maxZoom: 19 }); + } } let fullDxfGeoJson = null; @@ -981,119 +972,33 @@ function applyDxfVectorFilters() { if (map.getSource('dxf-layout')) { map.getSource('dxf-layout').setData(filteredData); + const isVisible = selectedLayers.length > 0; ['dxf-layout-fills', 'dxf-layout-lines', 'dxf-layout-symbols'].forEach(lId => { if (map.getLayer(lId)) { - map.setLayoutProperty(lId, 'visibility', 'visible'); + map.setLayoutProperty(lId, 'visibility', isVisible ? 'visible' : 'none'); } }); reorderIntersectionLayers(); } } -function updateButtonActiveState() { - const btn = document.getElementById('btn-load-georef-plan'); - if (!btn) return; - - let anyImageActive = false; - document.querySelectorAll('.image-plan-toggle').forEach(cb => { - if (cb.checked) anyImageActive = true; - }); - - let anyVectorActive = false; - document.querySelectorAll('.dxf-vector-layer-toggle').forEach(cb => { - if (cb.checked) anyVectorActive = true; - }); - - if (anyImageActive || anyVectorActive) { - btn.classList.remove('btn-light', 'bg-white', 'border'); - btn.classList.add('btn-primary'); - } else { - btn.classList.remove('btn-primary'); - btn.classList.add('btn-light', 'bg-white', 'border'); - } -} - -const noGeorefImagesAlert = document.getElementById('no-georef-images-alert'); -const imagePlansList = document.getElementById('image-plans-list'); -if (imagePlansList) { - imagePlansList.innerHTML = ''; - if (georeferencedDocuments.length === 0) { - if (noGeorefImagesAlert) noGeorefImagesAlert.style.display = 'block'; - } else { - if (noGeorefImagesAlert) noGeorefImagesAlert.style.display = 'none'; - - georeferencedDocuments.forEach(doc => { - const item = document.createElement('div'); - item.className = 'image-plan-item p-3 bg-light border rounded-3 d-flex flex-column gap-2'; - item.innerHTML = ` -
- - ${doc.title} - -
- -
-
- - `; - imagePlansList.appendChild(item); - - const toggle = item.querySelector('.image-plan-toggle'); - const opacityContainer = item.querySelector('.image-plan-opacity-container'); - const slider = item.querySelector('.image-plan-opacity-slider'); - const opacityVal = item.querySelector('.opacity-val'); - - toggle.addEventListener('change', () => { - const active = toggle.checked; - if (active) { - opacityContainer.style.display = 'block'; - } else { - opacityContainer.style.display = 'none'; - } - const opacity = parseFloat(slider.value) / 100.0; - showGeorefImage(doc, active, opacity); - updateButtonActiveState(); - }); - - slider.addEventListener('input', () => { - const val = slider.value; - opacityVal.textContent = val + '%'; - const opacity = parseFloat(val) / 100.0; - showGeorefImage(doc, toggle.checked, opacity); - }); - }); - } -} - -const dxfFileSelect = document.getElementById('select-dxf-file'); let detailLayersFetched = {}; let detailLayersResponseData = {}; -function fetchDetailLayers() { - if (!dxfFileSelect) return; - const file = dxfFileSelect.value; - if (!file) { - const section = document.getElementById('dxf-detail-layers-section'); - if (section) section.style.display = 'none'; - return; - } +function fetchDetailLayers(file, autoCheckAll = false) { + if (!file) return; + + const layersAccordion = document.getElementById('dxf-layers-accordion'); + if (layersAccordion) layersAccordion.style.display = 'block'; if (detailLayersFetched[file]) { - renderDetailLayers(file); + renderDetailLayers(file, autoCheckAll); fetchDxfGeoJson(file); return; } const spinner = document.getElementById('dxf-detail-layers-spinner'); const list = document.getElementById('dxf-detail-layers-list'); - const section = document.getElementById('dxf-detail-layers-section'); - if (section) section.style.display = 'block'; if (spinner) spinner.style.display = 'block'; if (list) list.style.display = 'none'; @@ -1102,101 +1007,389 @@ function fetchDetailLayers() { .then(data => { detailLayersFetched[file] = data.layers || []; detailLayersResponseData[file] = data; - renderDetailLayers(file); + renderDetailLayers(file, autoCheckAll); fetchDxfGeoJson(file); if (spinner) spinner.style.display = 'none'; - if (list) list.style.display = 'block'; + if (list) list.style.display = 'flex'; }) .catch(err => { console.error("Error fetching detail layers:", err); if (spinner) { - spinner.innerHTML = `
Erreur de chargement.
`; + spinner.innerHTML = `
Erreur de chargement.
`; } }); } -function renderDetailLayers(file) { +function renderDetailLayers(file, autoCheckAll = false) { const container = document.getElementById('dxf-detail-layers-list'); if (!container) return; container.innerHTML = ''; const layers = detailLayersFetched[file] || []; - const responseData = detailLayersResponseData[file] || {}; - const selectedLayers = responseData.selected_layers || []; layers.forEach(layer => { - const isChecked = false; const div = document.createElement('div'); - div.className = 'form-check py-1 d-flex align-items-center justify-content-between'; + div.className = 'd-flex align-items-center justify-content-between py-1 px-1 rounded'; + div.style.fontSize = '11px'; div.innerHTML = ` -
- -