style osmose dashboard
This commit is contained in:
parent
684bf1da66
commit
e715d66020
2 changed files with 74 additions and 103 deletions
|
@ -2588,8 +2588,8 @@ final class AdminController extends AbstractController
|
||||||
if ($this->isPointInCity($issue['lat'], $issue['lon'], $lat, $lon, 10)) {
|
if ($this->isPointInCity($issue['lat'], $issue['lon'], $lat, $lon, 10)) {
|
||||||
$issues[] = [
|
$issues[] = [
|
||||||
'id' => $issue['id'] ?? '',
|
'id' => $issue['id'] ?? '',
|
||||||
'title' => $issue['title'] ?? 'Problème sans titre',
|
'title' => $issue['properties']['title'] ?? 'Problème sans titre',
|
||||||
'subtitle' => $issue['subtitle'] ?? '',
|
'subtitle' => $issue['properties']['subtitle'] ?? '',
|
||||||
'lat' => $issue['lat'],
|
'lat' => $issue['lat'],
|
||||||
'lon' => $issue['lon'],
|
'lon' => $issue['lon'],
|
||||||
'item' => $issue['item'] ?? '',
|
'item' => $issue['item'] ?? '',
|
||||||
|
|
|
@ -5,10 +5,18 @@
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
.maplibregl-ctrl-group button{
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
}
|
||||||
|
.maplibregl-popup{
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
#map {
|
#map {
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 430px;
|
||||||
}
|
}
|
||||||
.filters {
|
.filters {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
@ -36,24 +44,7 @@
|
||||||
.issue-item.level-3 {
|
.issue-item.level-3 {
|
||||||
border-left-color: #ffc107; /* Jaune pour les avertissements */
|
border-left-color: #ffc107; /* Jaune pour les avertissements */
|
||||||
}
|
}
|
||||||
.marker-cluster-small {
|
/* Styles de clustering supprimés car le clustering est désactivé */
|
||||||
background-color: rgba(181, 226, 140, 0.6);
|
|
||||||
}
|
|
||||||
.marker-cluster-small div {
|
|
||||||
background-color: rgba(110, 204, 57, 0.6);
|
|
||||||
}
|
|
||||||
.marker-cluster-medium {
|
|
||||||
background-color: rgba(241, 211, 87, 0.6);
|
|
||||||
}
|
|
||||||
.marker-cluster-medium div {
|
|
||||||
background-color: rgba(240, 194, 12, 0.6);
|
|
||||||
}
|
|
||||||
.marker-cluster-large {
|
|
||||||
background-color: rgba(253, 156, 115, 0.6);
|
|
||||||
}
|
|
||||||
.marker-cluster-large div {
|
|
||||||
background-color: rgba(241, 128, 23, 0.6);
|
|
||||||
}
|
|
||||||
.marker-level-1 {
|
.marker-level-1 {
|
||||||
background-color: #dc3545;
|
background-color: #dc3545;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
@ -324,58 +315,16 @@
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
features: features
|
features: features
|
||||||
},
|
},
|
||||||
cluster: true,
|
cluster: false // Désactiver le clustering comme demandé
|
||||||
clusterMaxZoom: 14,
|
|
||||||
clusterRadius: 50
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ajouter une couche pour les clusters
|
// Avec le clustering désactivé, nous n'avons plus besoin des couches de clusters
|
||||||
|
|
||||||
|
// Ajouter une couche pour les points (sans filtre de clustering puisqu'il est désactivé)
|
||||||
map.addLayer({
|
map.addLayer({
|
||||||
id: 'clusters',
|
id: 'point',
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
source: 'issues',
|
source: 'issues',
|
||||||
filter: ['has', 'point_count'],
|
|
||||||
paint: {
|
|
||||||
'circle-color': [
|
|
||||||
'step',
|
|
||||||
['get', 'point_count'],
|
|
||||||
'rgba(181, 226, 140, 0.6)',
|
|
||||||
10,
|
|
||||||
'rgba(241, 211, 87, 0.6)',
|
|
||||||
30,
|
|
||||||
'rgba(253, 156, 115, 0.6)'
|
|
||||||
],
|
|
||||||
'circle-radius': [
|
|
||||||
'step',
|
|
||||||
['get', 'point_count'],
|
|
||||||
20,
|
|
||||||
10,
|
|
||||||
30,
|
|
||||||
30,
|
|
||||||
40
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter une couche pour le nombre de points dans chaque cluster
|
|
||||||
map.addLayer({
|
|
||||||
id: 'cluster-count',
|
|
||||||
type: 'symbol',
|
|
||||||
source: 'issues',
|
|
||||||
filter: ['has', 'point_count'],
|
|
||||||
layout: {
|
|
||||||
'text-field': '{point_count_abbreviated}',
|
|
||||||
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
|
|
||||||
'text-size': 12
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter une couche pour les points individuels
|
|
||||||
map.addLayer({
|
|
||||||
id: 'unclustered-point',
|
|
||||||
type: 'circle',
|
|
||||||
source: 'issues',
|
|
||||||
filter: ['!', ['has', 'point_count']],
|
|
||||||
paint: {
|
paint: {
|
||||||
'circle-color': [
|
'circle-color': [
|
||||||
'match',
|
'match',
|
||||||
|
@ -391,45 +340,73 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ajouter un événement de clic sur les clusters
|
// Avec le clustering désactivé, nous n'avons plus besoin de l'événement de clic sur les clusters
|
||||||
map.on('click', 'clusters', function(e) {
|
|
||||||
const features = map.queryRenderedFeatures(e.point, { layers: ['clusters'] });
|
|
||||||
const clusterId = features[0].properties.cluster_id;
|
|
||||||
|
|
||||||
map.getSource('issues').getClusterExpansionZoom(clusterId, function(err, zoom) {
|
|
||||||
if (err) return;
|
|
||||||
|
|
||||||
map.easeTo({
|
|
||||||
center: features[0].geometry.coordinates,
|
|
||||||
zoom: zoom
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajouter un événement de clic sur les points individuels
|
// Ajouter un événement de clic sur les points individuels
|
||||||
map.on('click', 'unclustered-point', function(e) {
|
map.on('click', 'point', function(e) {
|
||||||
const coordinates = e.features[0].geometry.coordinates.slice();
|
const coordinates = e.features[0].geometry.coordinates.slice();
|
||||||
const title = e.features[0].properties.title;
|
const properties = e.features[0].properties;
|
||||||
const subtitle = e.features[0].properties.subtitle;
|
|
||||||
const item = e.features[0].properties.item;
|
|
||||||
const url = e.features[0].properties.url;
|
|
||||||
|
|
||||||
// Créer le contenu de la popup
|
// Extraire toutes les propriétés disponibles
|
||||||
|
const id = properties.id || 'N/A';
|
||||||
|
const title = properties.title || 'Problème sans titre';
|
||||||
|
const subtitle = properties.subtitle || '';
|
||||||
|
const lat = e.features[0].geometry.coordinates[1];
|
||||||
|
const lon = e.features[0].geometry.coordinates[0];
|
||||||
|
const item = properties.item || '';
|
||||||
|
const itemClass = properties.class || '';
|
||||||
|
const level = properties.level || '';
|
||||||
|
const updateTimestamp = properties.update_timestamp ? new Date(properties.update_timestamp * 1000).toLocaleString() : 'N/A';
|
||||||
|
const url = properties.url || '#';
|
||||||
|
|
||||||
|
// Créer le contenu de la popup avec toutes les propriétés
|
||||||
let popupContent = `
|
let popupContent = `
|
||||||
<h5>${title}</h5>
|
<div class="popup-content" style="max-width: 300px;">
|
||||||
|
<h5>${title}</h5>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (subtitle) {
|
if (subtitle) {
|
||||||
popupContent += `<p>${subtitle}</p>`;
|
popupContent += `<p class="text-muted">${subtitle}</p>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ajouter toutes les propriétés dans un tableau
|
||||||
popupContent += `
|
popupContent += `
|
||||||
<div>
|
<table class="table table-sm table-bordered mt-2">
|
||||||
<span class="badge bg-secondary">Item: ${item}</span>
|
<tbody>
|
||||||
</div>
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<td>${id}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Coordonnées</th>
|
||||||
|
<td>${lat.toFixed(6)}, ${lon.toFixed(6)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Item</th>
|
||||||
|
<td>${item}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Classe</th>
|
||||||
|
<td>${itemClass}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Niveau</th>
|
||||||
|
<td>
|
||||||
|
<span class="badge ${level == 1 ? 'bg-danger' : level == 2 ? 'bg-warning text-dark' : 'bg-info'}">
|
||||||
|
${level == 1 ? 'Critique' : level == 2 ? 'Important' : 'Avertissement'}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Dernière mise à jour</th>
|
||||||
|
<td>${updateTimestamp}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<a href="${url}" target="_blank" class="btn btn-sm btn-primary">Voir sur Osmose</a>
|
<a href="${url}" target="_blank" class="btn btn-sm btn-primary">Voir sur Osmose</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Assurer que si le zoom change, la popup reste à la bonne position
|
// Assurer que si le zoom change, la popup reste à la bonne position
|
||||||
|
@ -443,17 +420,11 @@
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Changer le curseur au survol des clusters et des points
|
// Changer le curseur au survol des points
|
||||||
map.on('mouseenter', 'clusters', function() {
|
map.on('mouseenter', 'point', function() {
|
||||||
map.getCanvas().style.cursor = 'pointer';
|
map.getCanvas().style.cursor = 'pointer';
|
||||||
});
|
});
|
||||||
map.on('mouseleave', 'clusters', function() {
|
map.on('mouseleave', 'point', function() {
|
||||||
map.getCanvas().style.cursor = '';
|
|
||||||
});
|
|
||||||
map.on('mouseenter', 'unclustered-point', function() {
|
|
||||||
map.getCanvas().style.cursor = 'pointer';
|
|
||||||
});
|
|
||||||
map.on('mouseleave', 'unclustered-point', function() {
|
|
||||||
map.getCanvas().style.cursor = '';
|
map.getCanvas().style.cursor = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -467,7 +438,7 @@
|
||||||
// Simuler un clic sur le point pour ouvrir la popup
|
// Simuler un clic sur le point pour ouvrir la popup
|
||||||
const features = map.queryRenderedFeatures(
|
const features = map.queryRenderedFeatures(
|
||||||
map.project([lon, lat]),
|
map.project([lon, lat]),
|
||||||
{ layers: ['unclustered-point'] }
|
{ layers: ['point'] }
|
||||||
);
|
);
|
||||||
|
|
||||||
if (features.length > 0) {
|
if (features.length > 0) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue