| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  | {% extends "layout.html" %} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  | {% block title %}Événement {{ properties.label|default(id) }} - OpenEventDatabase{% endblock %} | 
					
						
							| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | {% block css %} | 
					
						
							|  |  |  | <style> | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  |     .event-header { | 
					
						
							|  |  |  |         background: white; | 
					
						
							|  |  |  |         padding: 20px; | 
					
						
							|  |  |  |         border-radius: 8px; | 
					
						
							|  |  |  |         box-shadow: 0 2px 4px rgba(0,0,0,0.1); | 
					
						
							|  |  |  |         margin-bottom: 20px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .event-title { | 
					
						
							|  |  |  |         margin: 0 0 10px 0; | 
					
						
							|  |  |  |         color: #333; | 
					
						
							|  |  |  |         font-size: 1.8rem; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .event-subtitle { | 
					
						
							|  |  |  |         color: #666; | 
					
						
							|  |  |  |         font-size: 1rem; | 
					
						
							|  |  |  |         margin: 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #map {  | 
					
						
							|  |  |  |         width: 100%;  | 
					
						
							|  |  |  |         height: 400px;  | 
					
						
							|  |  |  |         border: 1px solid #ddd;  | 
					
						
							|  |  |  |         border-radius: 8px; | 
					
						
							|  |  |  |         margin-bottom: 20px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .properties-table { | 
					
						
							|  |  |  |         background: white; | 
					
						
							|  |  |  |         border-radius: 8px; | 
					
						
							|  |  |  |         box-shadow: 0 2px 4px rgba(0,0,0,0.1); | 
					
						
							|  |  |  |         overflow: hidden; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .table-header { | 
					
						
							|  |  |  |         background: #f8f9fa; | 
					
						
							|  |  |  |         padding: 15px 20px; | 
					
						
							|  |  |  |         border-bottom: 1px solid #dee2e6; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .table-header h2 { | 
					
						
							|  |  |  |         margin: 0; | 
					
						
							|  |  |  |         color: #333; | 
					
						
							|  |  |  |         font-size: 1.3rem; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     table {  | 
					
						
							|  |  |  |         width: 100%;  | 
					
						
							|  |  |  |         border-collapse: collapse;  | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     th, td {  | 
					
						
							|  |  |  |         padding: 12px 20px;  | 
					
						
							|  |  |  |         border-bottom: 1px solid #eee;  | 
					
						
							|  |  |  |         text-align: left;  | 
					
						
							|  |  |  |         vertical-align: top; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     th {  | 
					
						
							|  |  |  |         background: #f9fafb; | 
					
						
							|  |  |  |         font-weight: 600; | 
					
						
							|  |  |  |         color: #495057; | 
					
						
							|  |  |  |         width: 200px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     td { | 
					
						
							|  |  |  |         word-wrap: break-word; | 
					
						
							|  |  |  |         max-width: 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .what-link { | 
					
						
							|  |  |  |         display: inline-block; | 
					
						
							|  |  |  |         padding: 4px 12px; | 
					
						
							|  |  |  |         background: #0078ff; | 
					
						
							|  |  |  |         color: white !important; | 
					
						
							|  |  |  |         text-decoration: none; | 
					
						
							|  |  |  |         border-radius: 20px; | 
					
						
							|  |  |  |         font-size: 0.9rem; | 
					
						
							|  |  |  |         font-weight: 500; | 
					
						
							|  |  |  |         transition: background-color 0.2s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .what-link:hover { | 
					
						
							|  |  |  |         background: #0056b3; | 
					
						
							|  |  |  |         text-decoration: none; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .nav-links { | 
					
						
							|  |  |  |         margin-top: 10px; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .nav-links a { | 
					
						
							|  |  |  |         color: #0078ff; | 
					
						
							|  |  |  |         text-decoration: none; | 
					
						
							|  |  |  |         margin-right: 15px; | 
					
						
							|  |  |  |         font-weight: 500; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .nav-links a:hover { | 
					
						
							|  |  |  |         text-decoration: underline; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .error-message { | 
					
						
							|  |  |  |         background: #f8d7da; | 
					
						
							|  |  |  |         color: #721c24; | 
					
						
							|  |  |  |         padding: 12px; | 
					
						
							|  |  |  |         border-radius: 4px; | 
					
						
							|  |  |  |         margin-bottom: 20px; | 
					
						
							|  |  |  |         border: 1px solid #f5c6cb; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     .loading { | 
					
						
							|  |  |  |         text-align: center; | 
					
						
							|  |  |  |         padding: 20px; | 
					
						
							|  |  |  |         color: #6c757d; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  | </style> | 
					
						
							|  |  |  | {% endblock %} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  | {% block header %} | 
					
						
							|  |  |  | <div class="event-header"> | 
					
						
							|  |  |  |     <h1 class="event-title">{{ properties.label|default('Événement sans titre') }}</h1> | 
					
						
							|  |  |  |     <p class="event-subtitle">ID: {{ id }}</p> | 
					
						
							|  |  |  |     <div class="nav-links"> | 
					
						
							|  |  |  |         <a href="/demo"><i class="fas fa-home"></i> Accueil</a> | 
					
						
							|  |  |  |         <a href="/demo/view-events"><i class="fas fa-table"></i> Tous les événements</a> | 
					
						
							|  |  |  |         <a href="https://api.openeventdatabase.org/event/{{ id }}" target="_blank"><i class="fas fa-code"></i> API JSON</a> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  | </div> | 
					
						
							|  |  |  | {% endblock %} | 
					
						
							| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | {% block content %} | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  | <div id="loading-map" class="loading"> | 
					
						
							|  |  |  |     <i class="fas fa-spinner fa-spin"></i> | 
					
						
							|  |  |  |     Chargement de la carte... | 
					
						
							|  |  |  | </div> | 
					
						
							|  |  |  | <div id="map-error" class="error-message" style="display: none;"> | 
					
						
							|  |  |  |     <i class="fas fa-exclamation-triangle"></i> | 
					
						
							|  |  |  |     Erreur lors du chargement de la carte | 
					
						
							|  |  |  | </div> | 
					
						
							|  |  |  | <div id="map" style="display: none;"></div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <div class="properties-table"> | 
					
						
							|  |  |  |     <div class="table-header"> | 
					
						
							|  |  |  |         <h2><i class="fas fa-info-circle"></i> Propriétés de l'événement</h2> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |     <table> | 
					
						
							|  |  |  |         <thead> | 
					
						
							|  |  |  |             <tr> | 
					
						
							|  |  |  |                 <th>Propriété</th> | 
					
						
							|  |  |  |                 <th>Valeur</th> | 
					
						
							|  |  |  |             </tr> | 
					
						
							|  |  |  |         </thead> | 
					
						
							|  |  |  |         <tbody> | 
					
						
							|  |  |  |             {% for key, value in properties.items()|sort %} | 
					
						
							|  |  |  |             <tr> | 
					
						
							|  |  |  |                 <td><strong>{{ key }}</strong></td> | 
					
						
							|  |  |  |                 <td> | 
					
						
							|  |  |  |                     {% if key == 'what' %} | 
					
						
							|  |  |  |                         <a href="/demo/map-by-what/{{ value }}" class="what-link"> | 
					
						
							|  |  |  |                             <i class="fas fa-tag"></i> {{ value }} | 
					
						
							|  |  |  |                         </a> | 
					
						
							|  |  |  |                         <small style="display: block; margin-top: 5px; color: #6c757d;"> | 
					
						
							|  |  |  |                             Cliquez pour voir tous les événements de ce type | 
					
						
							|  |  |  |                         </small> | 
					
						
							|  |  |  |                     {% elif key in ['start', 'stop', 'createdate', 'lastupdate'] and value %} | 
					
						
							|  |  |  |                         {{ value }} | 
					
						
							|  |  |  |                         <small style="display: block; color: #6c757d;"> | 
					
						
							| 
									
										
										
										
											2025-09-26 17:40:12 +02:00
										 |  |  |                             {{ value }} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  |                         </small> | 
					
						
							|  |  |  |                     {% elif key == 'url' and value %} | 
					
						
							|  |  |  |                         <a href="{{ value }}" target="_blank" style="color: #0078ff;"> | 
					
						
							|  |  |  |                             {{ value }} | 
					
						
							|  |  |  |                             <i class="fas fa-external-link-alt" style="font-size: 0.8em;"></i> | 
					
						
							|  |  |  |                         </a> | 
					
						
							|  |  |  |                     {% elif value is string and value.startswith('http') %} | 
					
						
							|  |  |  |                         <a href="{{ value }}" target="_blank" style="color: #0078ff;"> | 
					
						
							|  |  |  |                             {{ value }} | 
					
						
							|  |  |  |                             <i class="fas fa-external-link-alt" style="font-size: 0.8em;"></i> | 
					
						
							|  |  |  |                         </a> | 
					
						
							|  |  |  |                     {% else %} | 
					
						
							|  |  |  |                         {{ value|safe if value else '-' }} | 
					
						
							|  |  |  |                     {% endif %} | 
					
						
							|  |  |  |                 </td> | 
					
						
							|  |  |  |             </tr> | 
					
						
							|  |  |  |             {% endfor %} | 
					
						
							|  |  |  |         </tbody> | 
					
						
							|  |  |  |     </table> | 
					
						
							|  |  |  | </div> | 
					
						
							| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  | {% endblock %} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | {% block scripts %} | 
					
						
							|  |  |  | <script> | 
					
						
							| 
									
										
										
										
											2025-09-26 17:38:30 +02:00
										 |  |  |     // Fonction pour formater les dates | 
					
						
							|  |  |  |     function formatDate(dateString) { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             const date = new Date(dateString); | 
					
						
							|  |  |  |             return date.toLocaleDateString('fr-FR', { | 
					
						
							|  |  |  |                 weekday: 'long', | 
					
						
							|  |  |  |                 year: 'numeric', | 
					
						
							|  |  |  |                 month: 'long', | 
					
						
							|  |  |  |                 day: 'numeric', | 
					
						
							|  |  |  |                 hour: '2-digit', | 
					
						
							|  |  |  |                 minute: '2-digit' | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } catch (e) { | 
					
						
							|  |  |  |             return dateString; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Formater les dates dans le tableau après le chargement de la page | 
					
						
							|  |  |  |     function formatDatesInTable() { | 
					
						
							|  |  |  |         const dateElements = document.querySelectorAll('.date-display[data-date]'); | 
					
						
							|  |  |  |         dateElements.forEach(element => { | 
					
						
							|  |  |  |             const dateValue = element.getAttribute('data-date'); | 
					
						
							|  |  |  |             if (dateValue) { | 
					
						
							|  |  |  |                 const formattedDate = formatDate(dateValue); | 
					
						
							|  |  |  |                 element.textContent = formattedDate; | 
					
						
							|  |  |  |                 element.title = dateValue; // Garder la date originale en tooltip | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Gestion des erreurs et logging | 
					
						
							|  |  |  |     function logError(message, error) { | 
					
						
							|  |  |  |         console.error(message, error); | 
					
						
							|  |  |  |         document.getElementById('loading-map').style.display = 'none'; | 
					
						
							|  |  |  |         document.getElementById('map-error').style.display = 'block'; | 
					
						
							|  |  |  |         document.getElementById('map-error').innerHTML = ` | 
					
						
							|  |  |  |             <i class="fas fa-exclamation-triangle"></i> | 
					
						
							|  |  |  |             ${message}: ${error.message || error} | 
					
						
							|  |  |  |         `; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Formater les dates dans le tableau | 
					
						
							|  |  |  |     formatDatesInTable(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Initialisation de la carte | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         console.log('🗺️ Initialisation de la carte...'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Parser les données de l'événement de manière sécurisée | 
					
						
							|  |  |  |         let eventFeature; | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             const featureJson = '{{ feature_json|safe }}'; | 
					
						
							|  |  |  |             console.log('📄 JSON reçu:', featureJson); | 
					
						
							|  |  |  |             eventFeature = JSON.parse(featureJson); | 
					
						
							|  |  |  |             console.log('✅ Données de l\'événement parsées:', eventFeature); | 
					
						
							|  |  |  |         } catch (parseError) { | 
					
						
							|  |  |  |             throw new Error(`Impossible de parser les données JSON: ${parseError.message}`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Vérifier la structure des données | 
					
						
							|  |  |  |         if (!eventFeature) { | 
					
						
							|  |  |  |             throw new Error('Aucune donnée d\'événement trouvée'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Déterminer les coordonnées pour la carte | 
					
						
							|  |  |  |         let center = [2.3522, 48.8566]; // Paris par défaut | 
					
						
							|  |  |  |         let hasValidGeometry = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (eventFeature.geometry &&  | 
					
						
							|  |  |  |             eventFeature.geometry.type === 'Point' &&  | 
					
						
							|  |  |  |             eventFeature.geometry.coordinates && | 
					
						
							|  |  |  |             Array.isArray(eventFeature.geometry.coordinates) && | 
					
						
							|  |  |  |             eventFeature.geometry.coordinates.length === 2) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const coords = eventFeature.geometry.coordinates; | 
					
						
							|  |  |  |             // Vérifier que les coordonnées sont des nombres valides | 
					
						
							|  |  |  |             if (typeof coords[0] === 'number' && typeof coords[1] === 'number' && | 
					
						
							|  |  |  |                 !isNaN(coords[0]) && !isNaN(coords[1])) { | 
					
						
							|  |  |  |                 center = coords; | 
					
						
							|  |  |  |                 hasValidGeometry = true; | 
					
						
							|  |  |  |                 console.log('📍 Coordonnées trouvées:', center); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!hasValidGeometry) { | 
					
						
							|  |  |  |             console.warn('⚠️ Pas de coordonnées valides, utilisation du centre par défaut'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Créer la carte | 
					
						
							|  |  |  |         const map = new maplibregl.Map({ | 
					
						
							|  |  |  |             container: 'map', | 
					
						
							|  |  |  |             style: 'https://tiles.openfreemap.org/styles/liberty', | 
					
						
							|  |  |  |             center: center, | 
					
						
							|  |  |  |             zoom: hasValidGeometry ? 14 : 6 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Ajouter les contrôles | 
					
						
							|  |  |  |         map.addControl(new maplibregl.NavigationControl()); | 
					
						
							|  |  |  |         map.addControl(new maplibregl.AttributionControl({ | 
					
						
							|  |  |  |             customAttribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | 
					
						
							|  |  |  |         })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Quand la carte est chargée | 
					
						
							|  |  |  |         map.on('load', function() { | 
					
						
							|  |  |  |             console.log('✅ Carte chargée avec succès'); | 
					
						
							|  |  |  |             document.getElementById('loading-map').style.display = 'none'; | 
					
						
							|  |  |  |             document.getElementById('map').style.display = 'block'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Ajouter le marqueur si on a des coordonnées valides | 
					
						
							|  |  |  |             if (hasValidGeometry) { | 
					
						
							|  |  |  |                 const marker = new maplibregl.Marker({ | 
					
						
							|  |  |  |                     color: '#0078ff' | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |                 .setLngLat(center) | 
					
						
							|  |  |  |                 .addTo(map); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Créer une popup avec les informations de l'événement | 
					
						
							|  |  |  |                 const properties = eventFeature.properties || {}; | 
					
						
							|  |  |  |                 const popupContent = ` | 
					
						
							|  |  |  |                     <div style="max-width: 250px;"> | 
					
						
							|  |  |  |                         <h3 style="margin: 0 0 10px 0;">${properties.label || 'Événement'}</h3> | 
					
						
							|  |  |  |                         ${properties.what ? `<p><strong>Type:</strong> ${properties.what}</p>` : ''} | 
					
						
							|  |  |  |                         ${properties.start ? `<p><strong>Début:</strong> ${formatDate(properties.start)}</p>` : ''} | 
					
						
							|  |  |  |                         ${properties.where ? `<p><strong>Lieu:</strong> ${properties.where}</p>` : ''} | 
					
						
							|  |  |  |                     </div> | 
					
						
							|  |  |  |                 `; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const popup = new maplibregl.Popup({ offset: 25 }) | 
					
						
							|  |  |  |                     .setHTML(popupContent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 marker.setPopup(popup); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 console.log('📍 Marqueur ajouté à la carte'); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Gestion des erreurs de carte | 
					
						
							|  |  |  |         map.on('error', function(e) { | 
					
						
							|  |  |  |             logError('Erreur lors du chargement de la carte', e.error || e); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |         logError('Erreur lors de l\'initialisation de la carte', error); | 
					
						
							| 
									
										
										
										
											2025-09-26 14:18:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | {% endblock %} |