423 lines
16 KiB
JavaScript
423 lines
16 KiB
JavaScript
// Variables globales
|
|
let map;
|
|
let draw;
|
|
let currentMarker = null;
|
|
|
|
// Initialisation quand le DOM est chargé
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initializeForm();
|
|
initializeMap();
|
|
setupEventHandlers();
|
|
});
|
|
|
|
function initializeForm() {
|
|
if (!window.eventData) {
|
|
console.error('Aucune donnée d\'événement disponible');
|
|
return;
|
|
}
|
|
|
|
const properties = window.eventData.properties || {};
|
|
const geometry = window.eventData.geometry || {};
|
|
|
|
// Remplir le tableau des propriétés
|
|
populatePropertiesTable();
|
|
|
|
// Remplir les champs du formulaire
|
|
document.getElementById('label').value = properties.label || '';
|
|
document.getElementById('type').value = properties.type || 'scheduled';
|
|
document.getElementById('what').value = properties.what || '';
|
|
document.getElementById('what_series').value = properties['what:series'] || '';
|
|
document.getElementById('where').value = properties.where || '';
|
|
|
|
// Convertir les dates pour les inputs datetime-local
|
|
if (properties.start) {
|
|
const startDate = new Date(properties.start);
|
|
document.getElementById('start').value = formatDateTimeLocal(startDate);
|
|
}
|
|
if (properties.stop) {
|
|
const stopDate = new Date(properties.stop);
|
|
document.getElementById('stop').value = formatDateTimeLocal(stopDate);
|
|
}
|
|
|
|
console.log('✅ Formulaire initialisé avec les données de l\'événement');
|
|
}
|
|
|
|
function formatDateTimeLocal(date) {
|
|
// Convertir une date en format compatible avec datetime-local
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
}
|
|
|
|
function initializeMap() {
|
|
if (!window.maplibregl) {
|
|
console.error('MapLibre GL JS non disponible');
|
|
return;
|
|
}
|
|
|
|
const geometry = window.eventData?.geometry || {};
|
|
const coordinates = geometry.coordinates || [2.3522, 48.8566]; // Paris par défaut
|
|
|
|
// Initialiser la carte
|
|
map = new maplibregl.Map({
|
|
container: 'map',
|
|
style: 'https://tiles.openfreemap.org/styles/liberty',
|
|
center: coordinates,
|
|
zoom: coordinates[0] === 0 && coordinates[1] === 0 ? 2 : 12
|
|
});
|
|
|
|
// Ajouter les contrôles
|
|
map.addControl(new maplibregl.NavigationControl());
|
|
map.addControl(new maplibregl.GeolocateControl({
|
|
positionOptions: {
|
|
enableHighAccuracy: true
|
|
}
|
|
}));
|
|
|
|
// Ajouter un marqueur pour la position actuelle
|
|
if (coordinates[0] !== 0 || coordinates[1] !== 0) {
|
|
currentMarker = new maplibregl.Marker()
|
|
.setLngLat(coordinates)
|
|
.addTo(map);
|
|
}
|
|
|
|
// Gérer les clics sur la carte pour changer la position
|
|
map.on('click', function(e) {
|
|
const coords = [e.lngLat.lng, e.lngLat.lat];
|
|
|
|
// Supprimer l'ancien marqueur
|
|
if (currentMarker) {
|
|
currentMarker.remove();
|
|
}
|
|
|
|
// Ajouter un nouveau marqueur
|
|
currentMarker = new maplibregl.Marker()
|
|
.setLngLat(coords)
|
|
.addTo(map);
|
|
|
|
console.log('📍 Position mise à jour:', coords);
|
|
});
|
|
|
|
console.log('✅ Carte initialisée');
|
|
}
|
|
|
|
function populatePropertiesTable() {
|
|
if (!window.eventData || !window.eventData.properties) {
|
|
return;
|
|
}
|
|
|
|
const tableBody = document.getElementById('propertiesTableBody');
|
|
const properties = window.eventData.properties;
|
|
|
|
// Vider le tableau
|
|
tableBody.innerHTML = '';
|
|
|
|
// Trier les propriétés alphabétiquement
|
|
const sortedKeys = Object.keys(properties).sort();
|
|
|
|
// Ajouter chaque propriété au tableau
|
|
sortedKeys.forEach(key => {
|
|
const value = properties[key];
|
|
const valueType = typeof value;
|
|
|
|
const row = document.createElement('tr');
|
|
row.style.borderBottom = '1px solid #eee';
|
|
|
|
// Formater la valeur pour l'affichage
|
|
let displayValue = '';
|
|
if (value === null) {
|
|
displayValue = '<em style="color: #999;">null</em>';
|
|
} else if (value === undefined) {
|
|
displayValue = '<em style="color: #999;">undefined</em>';
|
|
} else if (typeof value === 'object') {
|
|
displayValue = `<pre style="margin: 0; white-space: pre-wrap; font-size: 12px;">${JSON.stringify(value, null, 2)}</pre>`;
|
|
} else if (typeof value === 'string' && value.length > 50) {
|
|
displayValue = `<span title="${value}">${value.substring(0, 50)}...</span>`;
|
|
} else {
|
|
displayValue = String(value);
|
|
}
|
|
|
|
row.innerHTML = `
|
|
<td style="padding: 8px; font-weight: bold; background-color: #f8f9fa;">${key}</td>
|
|
<td style="padding: 8px; word-break: break-word; max-width: 300px;">${displayValue}</td>
|
|
<td style="padding: 8px; color: #666; font-style: italic;">${valueType}</td>
|
|
`;
|
|
|
|
tableBody.appendChild(row);
|
|
});
|
|
|
|
console.log('✅ Tableau des propriétés rempli');
|
|
}
|
|
|
|
function setupEventHandlers() {
|
|
// Gestionnaire de soumission du formulaire
|
|
const form = document.getElementById('eventForm');
|
|
if (form) {
|
|
form.addEventListener('submit', handleFormSubmit);
|
|
}
|
|
|
|
// Gestionnaire du bouton de suppression
|
|
const deleteButton = document.getElementById('deleteButton');
|
|
if (deleteButton) {
|
|
deleteButton.addEventListener('click', handleDelete);
|
|
}
|
|
|
|
// Gestionnaire du bouton d'inversion des coordonnées
|
|
const swapButton = document.getElementById('swapCoordinatesButton');
|
|
if (swapButton) {
|
|
swapButton.addEventListener('click', handleSwapCoordinates);
|
|
|
|
// Vérifier si c'est un Point pour activer/désactiver le bouton
|
|
const geometry = window.eventData?.geometry;
|
|
if (!geometry || geometry.type !== 'Point') {
|
|
swapButton.disabled = true;
|
|
swapButton.textContent = '🔄 Non disponible (pas un Point)';
|
|
swapButton.style.backgroundColor = '#6c757d';
|
|
}
|
|
}
|
|
|
|
// Initialiser l'autocomplétion pour le champ "what"
|
|
const whatInput = document.getElementById('what');
|
|
if (whatInput && window.initializeEventTypeAutocomplete) {
|
|
initializeEventTypeAutocomplete(whatInput, function(suggestion) {
|
|
console.log('Type d\'événement sélectionné:', suggestion);
|
|
|
|
// Émettre un événement de validation du formulaire
|
|
setTimeout(() => {
|
|
whatInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
}, 100);
|
|
});
|
|
console.log('✅ Autocomplétion initialisée pour le champ "what"');
|
|
}
|
|
}
|
|
|
|
async function handleFormSubmit(e) {
|
|
e.preventDefault();
|
|
|
|
const resultElement = document.getElementById('result');
|
|
resultElement.innerHTML = '<div style="color: #0078ff;">⏳ Mise à jour en cours...</div>';
|
|
resultElement.style.display = 'block';
|
|
|
|
try {
|
|
// Récupérer les données du formulaire
|
|
const formData = new FormData(e.target);
|
|
const eventId = document.getElementById('eventId').value;
|
|
|
|
// Construire l'objet événement
|
|
const updatedEvent = {
|
|
type: 'Feature',
|
|
geometry: {
|
|
type: 'Point',
|
|
coordinates: currentMarker ?
|
|
[currentMarker.getLngLat().lng, currentMarker.getLngLat().lat] :
|
|
[0, 0]
|
|
},
|
|
properties: {
|
|
...window.eventData.properties,
|
|
label: formData.get('label'),
|
|
type: formData.get('type'),
|
|
what: formData.get('what'),
|
|
'what:series': formData.get('what_series') || undefined,
|
|
where: formData.get('where') || undefined,
|
|
start: formData.get('start') ? new Date(formData.get('start')).toISOString() : undefined,
|
|
stop: formData.get('stop') ? new Date(formData.get('stop')).toISOString() : undefined
|
|
}
|
|
};
|
|
|
|
// Nettoyer les propriétés undefined
|
|
Object.keys(updatedEvent.properties).forEach(key => {
|
|
if (updatedEvent.properties[key] === undefined) {
|
|
delete updatedEvent.properties[key];
|
|
}
|
|
});
|
|
|
|
// Envoyer la mise à jour
|
|
const response = await fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(updatedEvent)
|
|
});
|
|
|
|
if (response.ok) {
|
|
resultElement.innerHTML = `
|
|
<div style="color: #28a745; padding: 15px; background: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;">
|
|
<i class="fas fa-check"></i>
|
|
<strong>Succès:</strong> L'événement a été mis à jour avec succès.
|
|
<br><a href="/demo/by_id/${eventId}">Voir l'événement</a>
|
|
</div>
|
|
`;
|
|
} else {
|
|
const errorData = await response.text();
|
|
throw new Error(`HTTP ${response.status}: ${errorData}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de la mise à jour:', error);
|
|
resultElement.innerHTML = `
|
|
<div style="color: #dc3545; padding: 15px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px;">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<strong>Erreur:</strong> ${error.message}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
async function handleDelete() {
|
|
const eventId = document.getElementById('eventId').value;
|
|
const eventLabel = window.eventData?.properties?.label || 'cet événement';
|
|
|
|
if (!confirm(`Êtes-vous sûr de vouloir supprimer "${eventLabel}" ? Cette action est irréversible.`)) {
|
|
return;
|
|
}
|
|
|
|
const resultElement = document.getElementById('result');
|
|
resultElement.innerHTML = '<div style="color: #dc3545;">⏳ Suppression en cours...</div>';
|
|
resultElement.style.display = 'block';
|
|
|
|
try {
|
|
const response = await fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
|
|
if (response.ok) {
|
|
resultElement.innerHTML = `
|
|
<div style="color: #28a745; padding: 15px; background: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;">
|
|
<i class="fas fa-check"></i>
|
|
<strong>Succès:</strong> L'événement a été supprimé avec succès.
|
|
<br><a href="/demo">Retour à la démo</a>
|
|
</div>
|
|
`;
|
|
|
|
// Désactiver le formulaire après suppression
|
|
document.getElementById('eventForm').style.display = 'none';
|
|
} else {
|
|
const errorData = await response.text();
|
|
throw new Error(`HTTP ${response.status}: ${errorData}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de la suppression:', error);
|
|
resultElement.innerHTML = `
|
|
<div style="color: #dc3545; padding: 15px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px;">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<strong>Erreur:</strong> ${error.message}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
async function handleSwapCoordinates() {
|
|
const eventId = document.getElementById('eventId').value;
|
|
const resultElement = document.getElementById('result');
|
|
const geometry = window.eventData?.geometry;
|
|
|
|
// Vérifications de sécurité
|
|
if (!geometry || geometry.type !== 'Point') {
|
|
resultElement.innerHTML = `
|
|
<div style="color: #dc3545; padding: 15px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px;">
|
|
<strong>Erreur:</strong> L'inversion des coordonnées n'est disponible que pour les événements de type Point.
|
|
</div>
|
|
`;
|
|
resultElement.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
const currentCoords = geometry.coordinates;
|
|
if (!Array.isArray(currentCoords) || currentCoords.length < 2) {
|
|
resultElement.innerHTML = `
|
|
<div style="color: #dc3545; padding: 15px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px;">
|
|
<strong>Erreur:</strong> Coordonnées invalides détectées.
|
|
</div>
|
|
`;
|
|
resultElement.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
// Afficher les coordonnées actuelles et futures
|
|
const [currentLon, currentLat] = currentCoords;
|
|
const newCoords = [currentLat, currentLon]; // Inverser longitude et latitude
|
|
|
|
const confirmMessage = `Voulez-vous inverser les coordonnées ?
|
|
|
|
Actuelles: [${currentLon.toFixed(6)}, ${currentLat.toFixed(6)}] (lon, lat)
|
|
Nouvelles: [${newCoords[0].toFixed(6)}, ${newCoords[1].toFixed(6)}] (lat→lon, lon→lat)
|
|
|
|
Cette action sera sauvegardée immédiatement sur le serveur.`;
|
|
|
|
if (!confirm(confirmMessage)) {
|
|
return;
|
|
}
|
|
|
|
resultElement.innerHTML = '<div style="color: #17a2b8;">⏳ Inversion des coordonnées en cours...</div>';
|
|
resultElement.style.display = 'block';
|
|
|
|
try {
|
|
// Créer l'événement modifié avec coordonnées inversées
|
|
const updatedEvent = {
|
|
...window.eventData,
|
|
geometry: {
|
|
...geometry,
|
|
coordinates: newCoords
|
|
}
|
|
};
|
|
|
|
// Envoyer la mise à jour au serveur
|
|
const response = await fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(updatedEvent)
|
|
});
|
|
|
|
if (response.ok) {
|
|
// Mettre à jour les données locales
|
|
window.eventData = updatedEvent;
|
|
|
|
// Mettre à jour le marqueur sur la carte
|
|
if (currentMarker) {
|
|
currentMarker.setLngLat(newCoords);
|
|
}
|
|
|
|
// Centrer la carte sur les nouvelles coordonnées
|
|
if (map) {
|
|
map.flyTo({
|
|
center: newCoords,
|
|
zoom: Math.max(map.getZoom(), 12)
|
|
});
|
|
}
|
|
|
|
// Mettre à jour le tableau des propriétés
|
|
populatePropertiesTable();
|
|
|
|
resultElement.innerHTML = `
|
|
<div style="color: #28a745; padding: 15px; background: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;">
|
|
<i class="fas fa-check"></i>
|
|
<strong>Succès:</strong> Les coordonnées ont été inversées avec succès.<br>
|
|
<small>Anciennes: [${currentLon.toFixed(6)}, ${currentLat.toFixed(6)}]<br>
|
|
Nouvelles: [${newCoords[0].toFixed(6)}, ${newCoords[1].toFixed(6)}]</small>
|
|
</div>
|
|
`;
|
|
|
|
console.log('✅ Coordonnées inversées avec succès:', {
|
|
avant: [currentLon, currentLat],
|
|
après: newCoords
|
|
});
|
|
} else {
|
|
const errorData = await response.text();
|
|
throw new Error(`HTTP ${response.status}: ${errorData}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de l\'inversion des coordonnées:', error);
|
|
resultElement.innerHTML = `
|
|
<div style="color: #dc3545; padding: 15px; background: #f8d7da; border: 1px solid #f5c6cb; border-radius: 4px;">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<strong>Erreur:</strong> Impossible d'inverser les coordonnées. ${error.message}
|
|
</div>
|
|
`;
|
|
}
|
|
}
|