347 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| {% extends "layout.html" %}
 | |
| 
 | |
| {% block title %}Événement {{ properties.label|default(id) }} - OpenEventDatabase{% endblock %}
 | |
| 
 | |
| {% block css %}
 | |
| <style>
 | |
|     .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;
 | |
|     }
 | |
| </style>
 | |
| {% endblock %}
 | |
| 
 | |
| {% 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 %}
 | |
| 
 | |
| {% block content %}
 | |
| <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;">
 | |
|                             {{ value }}
 | |
| 
 | |
|                         </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>
 | |
| {% endblock %}
 | |
| 
 | |
| {% block scripts %}
 | |
| <script>
 | |
|     // 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);
 | |
|     }
 | |
| </script>
 | |
| {% endblock %} | 
