up dashboard osmose de ville

This commit is contained in:
Tykayn 2025-08-31 18:23:41 +02:00 committed by tykayn
parent 1535cf8ee3
commit 684bf1da66
3 changed files with 108 additions and 27 deletions

View file

@ -2410,6 +2410,9 @@ final class AdminController extends AbstractController
// Récupérer tous les thèmes disponibles
$themes = $this->followUpService->getFollowUpThemes();
// Liste complète des items Osmose à utiliser
$allOsmoseItems = '7051%2C7070%2C7100%2C7150%2C7160%2C7170%2C7190%2C7220%2C7240%2C7250%2C8010%2C8020%2C8021%2C8030%2C8031%2C8050%2C8051%2C8090%2C8091%2C8101%2C8110%2C8121%2C8150%2C8151%2C8180%2C8191%2C8201%2C8211%2C8221%2C8230%2C8240';
// Récupérer les problèmes Osmose pour cette ville
$osmoseIssues = $this->getOsmoseIssuesForCity($city, $theme);
@ -2485,6 +2488,24 @@ final class AdminController extends AbstractController
// Ajouter le libellé pour "Autres"
$themes['other'] = 'Autres problèmes';
// Calculer la bounding box pour la ville
$bbox = $this->calculateBoundingBox($city->getLat(), $city->getLon(), 5);
// Récupérer les items Osmose correspondant aux thèmes si un thème spécifique est sélectionné
$itemsParam = $theme !== 'all' ?
(!empty($this->getOsmoseItemIdsForTheme($theme)) ? implode('%2C', $this->getOsmoseItemIdsForTheme($theme)) : $allOsmoseItems) :
$allOsmoseItems;
// Construire l'URL de l'API Osmose pour le GeoJSON
$jsonOsmoseUrl = sprintf(
'https://osmose.openstreetmap.fr/api/0.3/issues.geojson?zoom=14&item=%s&level=1%%2C2%%2C3&class=&source=&limit=500&bbox=%f%%2C%f%%2C%f%%2C%f',
$itemsParam,
$bbox['min_lon'],
$bbox['min_lat'],
$bbox['max_lon'],
$bbox['max_lat']
);
return $this->render('admin/osmose_issues_map.html.twig', [
'city' => $city,
'theme' => $theme,
@ -2492,7 +2513,18 @@ final class AdminController extends AbstractController
'osmoseIssues' => $osmoseIssues,
'issuesByTheme' => $issuesByTheme,
'issuesByLevel' => $issuesByLevel,
'osmoseApiUrl' => 'https://osmose.openstreetmap.fr/fr/map/#zoom=14&lat=' . $city->getLat() . '&lon=' . $city->getLon()
'mapbox_token' => $_ENV['MAPBOX_TOKEN'] ?? null,
'maptiler_token' => $_ENV['MAPTILER_TOKEN'] ?? null,
'jsonOsmose' => $jsonOsmoseUrl,
'osmoseApiUrl' => sprintf(
'https://osmose.openstreetmap.fr/fr/map/#zoom=14&lat=%s&lon=%s&item=%s&level=1%%2C2%%2C3&loc=14/%s/%s',
$city->getLat(),
$city->getLon(),
$allOsmoseItems,
$city->getLat(),
$city->getLon()
),
]);
}
@ -2531,36 +2563,62 @@ final class AdminController extends AbstractController
try {
// Appeler l'API Osmose
$response = file_get_contents($osmoseApiUrl);
$context = stream_context_create([
'http' => [
'timeout' => 30, // Augmenter le timeout à 30 secondes
'user_agent' => 'OSM-Commerces/1.0'
]
]);
$response = file_get_contents($osmoseApiUrl, false, $context);
if ($response === false) {
throw new \Exception('Échec de la récupération des données Osmose');
}
$data = json_decode($response, true);
if (isset($data['issues'])) {
if (isset($data['issues']) && is_array($data['issues'])) {
foreach ($data['issues'] as $issue) {
// Vérifier si l'issue a les propriétés nécessaires
if (!isset($issue['lat']) || !isset($issue['lon'])) {
continue;
}
// Vérifier si l'issue est dans les limites de la ville (approximativement)
if ($this->isPointInCity($issue['lat'], $issue['lon'], $lat, $lon, 5)) {
// Utiliser un rayon plus grand (10km) pour inclure plus d'issues
if ($this->isPointInCity($issue['lat'], $issue['lon'], $lat, $lon, 10)) {
$issues[] = [
'id' => $issue['id'],
'id' => $issue['id'] ?? '',
'title' => $issue['title'] ?? 'Problème sans titre',
'subtitle' => $issue['subtitle'] ?? '',
'lat' => $issue['lat'],
'lon' => $issue['lon'],
'item' => $issue['item'],
'class' => $issue['class'],
'item' => $issue['item'] ?? '',
'class' => $issue['class'] ?? '',
'level' => $issue['level'] ?? 2,
'update_timestamp' => $issue['update_timestamp'] ?? null,
'url' => sprintf('https://osmose.openstreetmap.fr/fr/issue/%s', $issue['uuid'])
'url' => isset($issue['uuid']) ? sprintf('https://osmose.openstreetmap.fr/fr/issue/%s', $issue['uuid']) : '#'
];
}
}
}
// Si aucune issue n'a été trouvée, ajouter un message de log
if (empty($issues)) {
$this->actionLogger->log('osmose_no_issues', [
'insee_code' => $city->getZone(),
'theme' => $theme,
'url' => $osmoseApiUrl
]);
}
} catch (\Exception $e) {
$this->actionLogger->log('error_osmose_api', [
'insee_code' => $city->getZone(),
'error' => $e->getMessage()
'error' => $e->getMessage(),
'url' => $osmoseApiUrl
]);
// Ajouter un message flash pour informer l'utilisateur
$this->addFlash('warning', 'Impossible de récupérer les problèmes Osmose : ' . $e->getMessage());
}
return $issues;

View file

@ -102,9 +102,14 @@
</select>
</div>
<div class="col-md-6 text-end">
<a href="{{ osmoseApiUrl }}" target="_blank" class="btn btn-primary">
<i class="fas fa-external-link-alt"></i> Voir sur Osmose
</a>
<div class="btn-group">
<a href="{{ osmoseApiUrl }}" target="_blank" class="btn btn-primary">
<i class="fas fa-external-link-alt"></i> Voir sur Osmose
</a>
<a href="{{ jsonOsmose }}" target="_blank" class="btn btn-success">
<i class="fas fa-download"></i> Télécharger GeoJSON
</a>
</div>
</div>
</form>
</div>
@ -268,11 +273,17 @@
// Initialiser la carte avec MapLibre
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json', // style URL
style: 'https://api.maptiler.com/maps/streets/style.json?key={{ maptiler_token|default("") }}', // Utiliser MapTiler si disponible
center: [{{ city.lon }}, {{ city.lat }}], // Note: MapLibre uses [longitude, latitude] order
zoom: 13
});
// Gérer les erreurs de chargement de la carte
map.on('error', function(e) {
console.error('Erreur de chargement de la carte:', e.error);
document.getElementById('map').innerHTML = '<div class="alert alert-danger">Erreur de chargement de la carte. Veuillez réessayer plus tard.</div>';
});
// Ajouter les contrôles de navigation
map.addControl(new maplibregl.NavigationControl());
@ -299,6 +310,13 @@
});
{% endfor %}
// Vérifier s'il y a des problèmes à afficher
if (features.length === 0) {
// Ajouter un message si aucun problème n'est trouvé
const mapContainer = document.getElementById('map');
mapContainer.insertAdjacentHTML('afterend', '<div class="alert alert-info mt-3">Aucun problème Osmose trouvé pour cette ville avec le filtre actuel.</div>');
}
// Ajouter la source de données à la carte
map.addSource('issues', {
type: 'geojson',

View file

@ -294,20 +294,25 @@
<div class="row mb-4" id="themes">
<div class="col-12">
<h2 class="section-anchor">Thèmes</h2>
<ul class="nav nav-tabs" id="themeTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="tab-table" data-bs-toggle="tab"
data-bs-target="#tabTableContent" type="button" role="tab"
aria-controls="tabTableContent" aria-selected="true">Tableau
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-cards" data-bs-toggle="tab"
data-bs-target="#tabCardsContent" type="button" role="tab"
aria-controls="tabCardsContent" aria-selected="false">Cartes
</button>
</li>
</ul>
<div class="d-flex justify-content-between align-items-center mb-3">
<ul class="nav nav-tabs" id="themeTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="tab-table" data-bs-toggle="tab"
data-bs-target="#tabTableContent" type="button" role="tab"
aria-controls="tabTableContent" aria-selected="true">Tableau
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-cards" data-bs-toggle="tab"
data-bs-target="#tabCardsContent" type="button" role="tab"
aria-controls="tabCardsContent" aria-selected="false">Cartes
</button>
</li>
</ul>
<a href="{{ path('app_admin_osmose_issues_map', {'inseeCode': stats.zone}) }}" class="btn btn-primary">
<i class="bi bi-exclamation-triangle"></i> Voir les alertes Osmose
</a>
</div>
<div class="tab-content" id="themeTabsContent">
<div class="tab-pane fade show active" id="tabTableContent" role="tabpanel"
aria-labelledby="tab-table">