diff --git a/assets/app.js b/assets/app.js
index 40604d5c..fe2b5628 100644
--- a/assets/app.js
+++ b/assets/app.js
@@ -8,13 +8,10 @@
// any CSS you import will output into a single css file (app.css in this case)
import './styles/app.css';
import jQuery from 'jquery';
-window.$ = jQuery;
-window.jQuery = jQuery;
import 'tablesort/tablesort.css';
// start the Stimulus application
// import './bootstrap';
-
import './utils.js';
import './opening_hours.js';
import './josm.js';
@@ -27,17 +24,21 @@ import Chart from 'chart.js/auto';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import maplibregl from 'maplibre-gl';
import {
- genererCouleurPastel,
- setupCitySearch,
- handleAddCityFormSubmit,
- enableLabourageForm,
- getLabourerUrl,
- adjustListGroupFontSize,
- toggleCompletionInfo,
- updateMapHeightForLargeScreens
+ adjustListGroupFontSize,
+ enableLabourageForm,
+ genererCouleurPastel,
+ getLabourerUrl,
+ handleAddCityFormSubmit,
+ setupCitySearch,
+ toggleCompletionInfo,
+ updateMapHeightForLargeScreens
} from './utils.js';
import tableSortJs from 'table-sort-js/table-sort.js';
import 'chartjs-adapter-date-fns';
+
+window.$ = jQuery;
+window.jQuery = jQuery;
+
console.log('TableSort', tableSortJs)
// Charger table-sortable (version non minifiée locale)
@@ -58,303 +59,302 @@ Chart.register(ChartDataLabels);
// Attendre le chargement du DOM
document.addEventListener('DOMContentLoaded', () => {
- console.log('DOMContentLoaded');
+ console.log('DOMContentLoaded');
- if(updateMapHeightForLargeScreens){
+ if (updateMapHeightForLargeScreens) {
-
- window.addEventListener('resize', updateMapHeightForLargeScreens);
- }
- const randombg = genererCouleurPastel();
- // Appliquer la couleur au body
+ window.addEventListener('resize', updateMapHeightForLargeScreens);
+ }
- document.querySelectorAll('body, .edit-land, .body-landing').forEach(element => {
- element.style.backgroundColor = randombg;
- });
+ const randombg = genererCouleurPastel();
+ // Appliquer la couleur au body
- // Gestion du bouton pour afficher tous les champs
- const btnShowAllFields = document.querySelector('#showAllFields');
- if (btnShowAllFields) {
- console.log('btnShowAllFields détecté');
- btnShowAllFields.addEventListener('click', () => {
- // Sélectionner tous les inputs dans le formulaire
- const form = document.querySelector('form');
- if (form) {
- // Sélectionner tous les inputs sauf #validation_messages
- const hiddenInputs = form.querySelectorAll('#advanced_tags');
+ document.querySelectorAll('body, .edit-land, .body-landing').forEach(element => {
+ element.style.backgroundColor = randombg;
+ });
- hiddenInputs.forEach(input => {
- input.classList.toggle('d-none');
+ // Gestion du bouton pour afficher tous les champs
+ const btnShowAllFields = document.querySelector('#showAllFields');
+ if (btnShowAllFields) {
+ console.log('btnShowAllFields détecté');
+ btnShowAllFields.addEventListener('click', () => {
+ // Sélectionner tous les inputs dans le formulaire
+ const form = document.querySelector('form');
+ if (form) {
+ // Sélectionner tous les inputs sauf #validation_messages
+ const hiddenInputs = form.querySelectorAll('#advanced_tags');
+
+ hiddenInputs.forEach(input => {
+ input.classList.toggle('d-none');
+ });
+ }
});
- }
+ }
+ const btnClosedCommerce = document.querySelector('#closedCommerce');
+ if (btnClosedCommerce) {
+ btnClosedCommerce.addEventListener('click', () => {
+
+ if (!confirm('Êtes-vous sûr de vouloir signaler ce commerce comme fermé ?')) {
+ return;
+ }
+ window.location.href = '/closed_commerce/' + document.getElementById('app_public_closed_commerce').value;
+ });
+ }
+
+ openingHoursFormManager.init();
+
+
+ // Vérifier si l'élément avec l'ID 'userChangesHistory' existe avant d'appeler la fonction
+ if (document.getElementById('userChangesHistory')) {
+ listChangesets();
+ } else {
+ console.log('userChangesHistory non trouvé');
+ }
+
+ document.querySelectorAll('input[type="text"]').forEach(input => {
+ input.addEventListener('blur', updateCompletionProgress);
});
- }
- const btnClosedCommerce = document.querySelector('#closedCommerce');
- if (btnClosedCommerce) {
- btnClosedCommerce.addEventListener('click', () => {
+ const form = document.querySelector('form')
+ if (form) {
+ form.addEventListener('submit', check_validity);
+ updateCompletionProgress()
+ }
+ updateCompletionProgress();
- if (!confirm('Êtes-vous sûr de vouloir signaler ce commerce comme fermé ?')) {
- return;
- }
- window.location.href = '/closed_commerce/' + document.getElementById('app_public_closed_commerce').value;
- });
- }
-
- openingHoursFormManager.init();
+ // Focus sur le premier champ texte au chargement
+ // const firstTextInput = document.querySelector('input.form-control');
+ // if (firstTextInput) {
+ // firstTextInput.focus();
+ // console.log('focus sur le premier champ texte', firstTextInput);
+ // } else {
+ // console.log('pas de champ texte trouvé');
+ // }
- // Vérifier si l'élément avec l'ID 'userChangesHistory' existe avant d'appeler la fonction
- if (document.getElementById('userChangesHistory')) {
- listChangesets();
- } else {
- console.log('userChangesHistory non trouvé');
- }
+ parseCuisine();
- document.querySelectorAll('input[type="text"]').forEach(input => {
- input.addEventListener('blur', updateCompletionProgress);
- });
- const form = document.querySelector('form')
- if (form) {
- form.addEventListener('submit', check_validity);
- updateCompletionProgress()
- }
- updateCompletionProgress();
+ // Modifier la fonction de recherche existante
+ const searchInput = document.getElementById('app_admin_labourer');
+ const suggestionList = document.getElementById('suggestionList');
- // Focus sur le premier champ texte au chargement
- // const firstTextInput = document.querySelector('input.form-control');
- // if (firstTextInput) {
- // firstTextInput.focus();
- // console.log('focus sur le premier champ texte', firstTextInput);
- // } else {
- // console.log('pas de champ texte trouvé');
- // }
+ if (searchInput && suggestionList) {
+ let timeoutId;
+ searchInput.addEventListener('input', () => {
+ clearTimeout(timeoutId);
+ const query = searchInput.value.trim();
+ if (query.length < 2) {
+ suggestionList.innerHTML = '';
+ return;
+ }
+ timeoutId = setTimeout(async () => {
+ const suggestions = await searchInseeCode(query);
+ suggestionList.innerHTML = '';
- parseCuisine();
-
- // Modifier la fonction de recherche existante
- const searchInput = document.getElementById('app_admin_labourer');
- const suggestionList = document.getElementById('suggestionList');
-
- if (searchInput && suggestionList) {
- let timeoutId;
-
- searchInput.addEventListener('input', () => {
- clearTimeout(timeoutId);
- const query = searchInput.value.trim();
-
- if (query.length < 2) {
- suggestionList.innerHTML = '';
- return;
- }
-
- timeoutId = setTimeout(async () => {
- const suggestions = await searchInseeCode(query);
- suggestionList.innerHTML = '';
-
- if (suggestions.length === 0) {
- const li = document.createElement('li');
- li.style.cssText = `
+ if (suggestions.length === 0) {
+ const li = document.createElement('li');
+ li.style.cssText = `
padding: 8px 12px;
color: #666;
font-style: italic;
`;
- li.textContent = 'Aucun résultat trouvé';
- suggestionList.appendChild(li);
- return;
- }
+ li.textContent = 'Aucun résultat trouvé';
+ suggestionList.appendChild(li);
+ return;
+ }
- suggestions.forEach(suggestion => {
- const li = document.createElement('li');
- li.style.cssText = `
+ suggestions.forEach(suggestion => {
+ const li = document.createElement('li');
+ li.style.cssText = `
padding: 8px 12px;
cursor: pointer;
border-bottom: 1px solid #eee;
`;
- li.textContent = suggestion.label;
+ li.textContent = suggestion.label;
- li.addEventListener('mouseenter', () => {
- li.style.backgroundColor = '#f0f0f0';
- });
+ li.addEventListener('mouseenter', () => {
+ li.style.backgroundColor = '#f0f0f0';
+ });
- li.addEventListener('mouseleave', () => {
- li.style.backgroundColor = 'white';
- });
+ li.addEventListener('mouseleave', () => {
+ li.style.backgroundColor = 'white';
+ });
- li.addEventListener('click', () => {
- searchInput.value = suggestion.insee;
- suggestionList.innerHTML = '';
- labourer();
- });
+ li.addEventListener('click', () => {
+ searchInput.value = suggestion.insee;
+ suggestionList.innerHTML = '';
+ labourer();
+ });
- suggestionList.appendChild(li);
+ suggestionList.appendChild(li);
+ });
+ }, 300);
});
- }, 300);
- });
- }
-
- if(enableLabourageForm){
-
- enableLabourageForm();
- }
- adjustListGroupFontSize('.list-group-item');
-
- // Activer le tri naturel sur tous les tableaux avec la classe table-sort
- if (tableSortJs) {
- tableSortJs();
- }else{
- console.log('pas de tablesort')
- }
-
- // Initialisation du tri et filtrage sur les tableaux du dashboard et de la page stats
- // if (document.querySelector('#dashboard-table')) {
- // $('#dashboard-table').tableSortable({
- // pagination: false,
- // showPaginationLabel: true,
- // searchField: '#dashboard-table-search',
- // responsive: false
- // });
- // }
- // if (document.querySelector('#stats-table')) {
- // $('#stats-table').tableSortable({
- // pagination: false,
- // showPaginationLabel: true,
- // searchField: '#stats-table-search',
- // responsive: false
- // });
- // }
-
- // Correction pour le formulaire de labourage
- const labourerForm = document.getElementById('labourerForm');
- if (labourerForm) {
- labourerForm.addEventListener('submit', async function(e) {
- e.preventDefault();
- const zipInput = document.getElementById('selectedZipCode');
- const cityInput = document.getElementById('citySearch');
- let insee = zipInput.value;
- if (!insee && cityInput && cityInput.value.trim().length > 0) {
- // Recherche du code INSEE via l'API
- const response = await fetch(`https://geo.api.gouv.fr/communes?nom=${encodeURIComponent(cityInput.value.trim())}&fields=nom,code&limit=1`);
- const data = await response.json();
- if (data.length > 0) {
- insee = data[0].code;
- }
- }
- if (insee) {
- window.location.href = `/add-city-without-labourage/${insee}`;
- } else {
- alert('Veuillez sélectionner une ville valide.');
- }
- });
- }
-
- // Ajouter un écouteur pour l'événement 'load' de MapLibre afin d'ajuster la hauteur de la carte
- if (window.maplibregl && document.getElementById('map')) {
- // On suppose que la carte est initialisée ailleurs et accessible via window.mapInstance
- // Sinon, on peut essayer de détecter l'instance automatiquement
- let mapInstance = window.mapInstance;
- if (!mapInstance && window.maplibreMap) {
- mapInstance = window.maplibreMap;
}
- // Si l'instance n'est pas trouvée, essayer de la récupérer via une variable globale courante
- if (!mapInstance && window.map) {
- mapInstance = window.map;
+
+ if (enableLabourageForm) {
+
+ enableLabourageForm();
}
- if (mapInstance && typeof mapInstance.on === 'function') {
- mapInstance.on('load', function() {
- updateMapHeightForLargeScreens();
- });
+ adjustListGroupFontSize('.list-group-item');
+
+ // Activer le tri naturel sur tous les tableaux avec la classe table-sort
+ if (tableSortJs) {
+ tableSortJs();
+ } else {
+ console.log('pas de tablesort')
}
- }
- //updateMapHeightForLargeScreens();
- console.log('window.followupSeries',window.followupSeries)
- if (!window.followupSeries) return;
+ // Correction pour le formulaire de labourage
+ const labourerForm = document.getElementById('labourerForm');
+ if (labourerForm) {
+ labourerForm.addEventListener('submit', async function (e) {
+ e.preventDefault();
+ const zipInput = document.getElementById('selectedZipCode');
+ const cityInput = document.getElementById('citySearch');
+ let insee = zipInput.value;
+ if (!insee && cityInput && cityInput.value.trim().length > 0) {
+ // Recherche du code INSEE via l'API
+ const response = await fetch(`https://geo.api.gouv.fr/communes?nom=${encodeURIComponent(cityInput.value.trim())}&fields=nom,code&limit=1`);
+ const data = await response.json();
+ if (data.length > 0) {
+ insee = data[0].code;
+ }
+ }
+ if (insee) {
+ window.location.href = `/add-city-without-labourage/${insee}`;
+ } else {
+ alert('Veuillez sélectionner une ville valide.');
+ }
+ });
+ }
- const series = window.followupSeries;
-
- // Données bornes de recharge
- const chargingStationCount = (series['charging_station_count'] || []).map(point => ({ x: point.date, y: point.value }));
- const chargingStationCompletion = (series['charging_station_completion'] || []).map(point => ({ x: point.date, y: point.value }));
-
- // Données bornes incendie
- const fireHydrantCount = (series['fire_hydrant_count'] || []).map(point => ({ x: point.date, y: point.value }));
- const fireHydrantCompletion = (series['fire_hydrant_completion'] || []).map(point => ({ x: point.date, y: point.value }));
-
- // Graphique bornes de recharge
- const chargingStationChart = document.getElementById('chargingStationChart');
- if (chargingStationChart) {
- new Chart(chargingStationChart, {
- type: 'line',
- data: {
- datasets: [
- {
- label: 'Nombre de bornes de recharge',
- data: chargingStationCount,
- borderColor: 'blue',
- backgroundColor: 'rgba(0,0,255,0.1)',
- fill: false,
- yAxisID: 'y',
- },
- {
- label: 'Complétion (%)',
- data: chargingStationCompletion,
- borderColor: 'green',
- backgroundColor: 'rgba(0,255,0,0.1)',
- fill: false,
- yAxisID: 'y1',
- }
- ]
- },
- options: {
- parsing: false,
- responsive: true,
- scales: {
- x: { type: 'time', time: { unit: 'day' }, title: { display: true, text: 'Date' } },
- y: { beginAtZero: true, title: { display: true, text: 'Nombre' } },
- y1: { beginAtZero: true, position: 'right', title: { display: true, text: 'Complétion (%)' }, grid: { drawOnChartArea: false } }
+ // Ajouter un écouteur pour l'événement 'load' de MapLibre afin d'ajuster la hauteur de la carte
+ if (window.maplibregl && document.getElementById('map')) {
+ // On suppose que la carte est initialisée ailleurs et accessible via window.mapInstance
+ // Sinon, on peut essayer de détecter l'instance automatiquement
+ let mapInstance = window.mapInstance;
+ if (!mapInstance && window.maplibreMap) {
+ mapInstance = window.maplibreMap;
}
- }
- });
- }
-
- // Graphique bornes incendie
- const fireHydrantChart = document.getElementById('fireHydrantChart');
- if (fireHydrantChart) {
- new Chart(fireHydrantChart, {
- type: 'line',
- data: {
- datasets: [
- {
- label: 'Nombre de bornes incendie',
- data: fireHydrantCount,
- borderColor: 'red',
- backgroundColor: 'rgba(255,0,0,0.1)',
- fill: false,
- yAxisID: 'y',
- },
- {
- label: 'Complétion (%)',
- data: fireHydrantCompletion,
- borderColor: 'orange',
- backgroundColor: 'rgba(255,165,0,0.1)',
- fill: false,
- yAxisID: 'y1',
- }
- ]
- },
- options: {
- parsing: false,
- responsive: true,
- scales: {
- x: { type: 'time', time: { unit: 'day' }, title: { display: true, text: 'Date' } },
- y: { beginAtZero: true, title: { display: true, text: 'Nombre' } },
- y1: { beginAtZero: true, position: 'right', title: { display: true, text: 'Complétion (%)' }, grid: { drawOnChartArea: false } }
+ // Si l'instance n'est pas trouvée, essayer de la récupérer via une variable globale courante
+ if (!mapInstance && window.map) {
+ mapInstance = window.map;
}
- }
- });
- }
+ if (mapInstance && typeof mapInstance.on === 'function') {
+ mapInstance.on('load', function () {
+ updateMapHeightForLargeScreens();
+ });
+ }
+ }
+ //updateMapHeightForLargeScreens();
+
+ console.log('window.followupSeries', window.followupSeries)
+ if (!window.followupSeries) return;
+
+ const series = window.followupSeries;
+
+ // Données bornes de recharge
+ const chargingStationCount = (series['charging_station_count'] || []).map(point => ({
+ x: point.date,
+ y: point.value
+ }));
+ const chargingStationCompletion = (series['charging_station_completion'] || []).map(point => ({
+ x: point.date,
+ y: point.value
+ }));
+
+ // Données bornes incendie
+ const fireHydrantCount = (series['fire_hydrant_count'] || []).map(point => ({x: point.date, y: point.value}));
+ const fireHydrantCompletion = (series['fire_hydrant_completion'] || []).map(point => ({
+ x: point.date,
+ y: point.value
+ }));
+
+ // Graphique bornes de recharge
+ const chargingStationChart = document.getElementById('chargingStationChart');
+ if (chargingStationChart) {
+ new Chart(chargingStationChart, {
+ type: 'line',
+ data: {
+ datasets: [
+ {
+ label: 'Nombre de bornes de recharge',
+ data: chargingStationCount,
+ borderColor: 'blue',
+ backgroundColor: 'rgba(0,0,255,0.1)',
+ fill: false,
+ yAxisID: 'y',
+ },
+ {
+ label: 'Complétion (%)',
+ data: chargingStationCompletion,
+ borderColor: 'green',
+ backgroundColor: 'rgba(0,255,0,0.1)',
+ fill: false,
+ yAxisID: 'y1',
+ }
+ ]
+ },
+ options: {
+ parsing: false,
+ responsive: true,
+ scales: {
+ x: {type: 'time', time: {unit: 'day'}, title: {display: true, text: 'Date'}},
+ y: {beginAtZero: true, title: {display: true, text: 'Nombre'}},
+ y1: {
+ beginAtZero: true,
+ position: 'right',
+ title: {display: true, text: 'Complétion (%)'},
+ grid: {drawOnChartArea: false}
+ }
+ }
+ }
+ });
+ }
+
+ // Graphique bornes incendie
+ const fireHydrantChart = document.getElementById('fireHydrantChart');
+ if (fireHydrantChart) {
+ new Chart(fireHydrantChart, {
+ type: 'line',
+ data: {
+ datasets: [
+ {
+ label: 'Nombre de bornes incendie',
+ data: fireHydrantCount,
+ borderColor: 'red',
+ backgroundColor: 'rgba(255,0,0,0.1)',
+ fill: false,
+ yAxisID: 'y',
+ },
+ {
+ label: 'Complétion (%)',
+ data: fireHydrantCompletion,
+ borderColor: 'orange',
+ backgroundColor: 'rgba(255,165,0,0.1)',
+ fill: false,
+ yAxisID: 'y1',
+ }
+ ]
+ },
+ options: {
+ parsing: false,
+ responsive: true,
+ scales: {
+ x: {type: 'time', time: {unit: 'day'}, title: {display: true, text: 'Date'}},
+ y: {beginAtZero: true, title: {display: true, text: 'Nombre'}},
+ y1: {
+ beginAtZero: true,
+ position: 'right',
+ title: {display: true, text: 'Complétion (%)'},
+ grid: {drawOnChartArea: false}
+ }
+ }
+ }
+ });
+ }
});
diff --git a/templates/admin/speed_limit.html.twig b/templates/admin/speed_limit.html.twig
index f8eafbe7..27bc5b9b 100644
--- a/templates/admin/speed_limit.html.twig
+++ b/templates/admin/speed_limit.html.twig
@@ -3,134 +3,316 @@
{% block title %}Limites de vitesse - {{ stats.name }}{% endblock %}
{% block body %}
-
-
Limites de vitesse à {{ stats.name }} ({{ stats.zone }})
-
Complétion des limitations de vitesse sur le réseau routier OSM.
- Tags attendus :
+
+
+
+
+ {{ stats.name }} :
+ {% include 'admin/_city_sidebar.html.twig' with {'stats': stats, 'active_menu': 'speed-limit'} %}
+
+
+
+
+
+
+
+
+
+
Limites de vitesse à {{ stats.name }} ({{ stats.zone }})
+
+
Complétion des limitations de vitesse sur le réseau routier OSM.
+ Tags attendus :
{% for tag in expected_tags %}{{ tag }}
{% if not loop.last %}, {% endif %}{% endfor %}
-
-
-
-
-
-
-
- - Rouge : route sans
maxspeed
- - Vert : route avec
maxspeed
- - Bleu : panneau routier (
traffic_sign
)
- - Orange : feu de circulation (
traffic_signals
)
-
-
Cliquer sur un objet pour ouvrir dans OSM, iD ou JOSM.
+
+
+
+
+
+
+
+
+
+
+
Objets trouvés
+
Chargement...
+
+
+
+
+
+
+
+
+
+
+
+ - Rouge : route sans
maxspeed
+ - Vert : route avec
maxspeed
+ - Bleu : panneau routier (
traffic_sign
)
+ - Orange : feu de circulation (
traffic_signals
)
+
+
Cliquer sur un objet pour ouvrir dans OSM, iD ou JOSM.
+
+
+
+
+
+
-
+
{% endblock %}
{% block javascripts %}
-{{ parent() }}
-
-
+
+
{% endblock %}
\ No newline at end of file