491 lines
No EOL
17 KiB
JavaScript
491 lines
No EOL
17 KiB
JavaScript
|
|
// Variable globale pour les données de l'événement
|
|
let eventData = null
|
|
|
|
// Initialize the map
|
|
const map = new maplibregl.Map({
|
|
container: 'map',
|
|
style: 'https://tiles.openfreemap.org/styles/liberty',
|
|
center: [2.2137, 46.2276], // Default center (center of metropolitan France)
|
|
zoom: 5
|
|
});
|
|
|
|
// Add navigation controls
|
|
map.addControl(new maplibregl.NavigationControl());
|
|
|
|
// Add attribution control with OpenStreetMap attribution
|
|
map.addControl(new maplibregl.AttributionControl({
|
|
customAttribution: '© <a href="https://www.openstreetmap.org/copyright" >OpenStreetMap</a> contributors'
|
|
}));
|
|
|
|
// Add marker for event location
|
|
let marker = new maplibregl.Marker({
|
|
draggable: true
|
|
});
|
|
;
|
|
|
|
// Function to populate form with event data
|
|
function populateForm() {
|
|
console.log('🔄 Tentative de récupération des données événement...');
|
|
|
|
// Essayer de récupérer les données depuis window (définies dans le template)
|
|
try {
|
|
if (typeof window.eventData !== 'undefined' && window.eventData) {
|
|
eventData = window.eventData;
|
|
console.log('✅ Données événement récupérées depuis window:', eventData);
|
|
} else {
|
|
throw new Error('Aucune donnée d\'événement trouvée dans window.eventData');
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Erreur lors de la récupération des données événement:', error);
|
|
showResult('Erreur lors du chargement des données de l\'événement: ' + error.message, 'error');
|
|
return;
|
|
}
|
|
|
|
// Vérifier la validité des données
|
|
if (!eventData) {
|
|
console.error('❌ eventData est null ou undefined');
|
|
showResult('Données d\'événement manquantes', 'error');
|
|
return;
|
|
}
|
|
|
|
if (!eventData.properties) {
|
|
console.error('❌ eventData.properties est manquant:', eventData);
|
|
showResult('Structure de données d\'événement invalide (properties manquant)', 'error');
|
|
return;
|
|
}
|
|
|
|
console.log('✅ Données événement validées, remplissage du formulaire...');
|
|
|
|
// Remplir le tableau des propriétés
|
|
populatePropertiesTable(eventData.properties);
|
|
|
|
const properties = eventData.properties;
|
|
|
|
// Set form values
|
|
document.getElementById('label').value = properties.label || '';
|
|
document.getElementById('type').value = properties.type || 'scheduled';
|
|
document.getElementById('what').value = properties.what || '';
|
|
|
|
// Handle optional fields
|
|
if (properties['what:series']) {
|
|
document.getElementById('what_series').value = properties['what:series'];
|
|
}
|
|
|
|
if (properties.where) {
|
|
document.getElementById('where').value = properties.where;
|
|
}
|
|
|
|
// Format dates for datetime-local input
|
|
if (properties.start) {
|
|
const startDate = new Date(properties.start);
|
|
document.getElementById('start').value = startDate.toISOString().slice(0, 16);
|
|
}
|
|
|
|
if (properties.stop) {
|
|
const stopDate = new Date(properties.stop);
|
|
document.getElementById('stop').value = stopDate.toISOString().slice(0, 16);
|
|
}
|
|
|
|
// Set marker on map
|
|
if (eventData.geometry && eventData.geometry.coordinates) {
|
|
const coords = eventData.geometry.coordinates;
|
|
marker.setLngLat(coords).addTo(map);
|
|
|
|
// Center map on event location
|
|
map.flyTo({
|
|
center: coords,
|
|
zoom: 10
|
|
});
|
|
}
|
|
|
|
// Initialiser l'autocomplétion pour le champ "what"
|
|
const whatInput = document.getElementById('what');
|
|
if (whatInput && window.initializeEventTypeAutocomplete) {
|
|
initializeEventTypeAutocomplete(whatInput);
|
|
}
|
|
}
|
|
|
|
// Function to populate the properties table
|
|
function populatePropertiesTable(properties) {
|
|
const tableBody = document.getElementById('propertiesTableBody');
|
|
if (!tableBody) return;
|
|
|
|
// Clear existing rows
|
|
tableBody.innerHTML = '';
|
|
|
|
// Sort properties alphabetically
|
|
const sortedProperties = Object.keys(properties).sort();
|
|
|
|
sortedProperties.forEach(key => {
|
|
const value = properties[key];
|
|
const row = document.createElement('tr');
|
|
|
|
// Determine value type and format
|
|
let displayValue;
|
|
let valueType;
|
|
|
|
if (value === null) {
|
|
displayValue = '<em style="color: #999;">null</em>';
|
|
valueType = 'null';
|
|
} else if (typeof value === 'object') {
|
|
displayValue = `<pre style="margin: 0; font-size: 12px;">${JSON.stringify(value, null, 2)}</pre>`;
|
|
valueType = 'object';
|
|
} else if (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/)) {
|
|
displayValue = value + ` <small style="color: #666;">(${new Date(value).toLocaleString()})</small>`;
|
|
valueType = 'datetime';
|
|
} else if (typeof value === 'string' && value.startsWith('http')) {
|
|
displayValue = `<a href="${value}" target="_blank">${value}</a>`;
|
|
valueType = 'url';
|
|
} else {
|
|
displayValue = String(value);
|
|
valueType = typeof value;
|
|
}
|
|
|
|
row.innerHTML = `
|
|
<td style="padding: 6px; border-bottom: 1px solid #eee; font-weight: bold; color: #333;">${key}</td>
|
|
<td style="padding: 6px; border-bottom: 1px solid #eee; word-break: break-word;">${displayValue}</td>
|
|
<td style="padding: 6px; border-bottom: 1px solid #eee; color: #666; font-size: 12px;">${valueType}</td>
|
|
`;
|
|
|
|
// Add alternating row colors
|
|
if (tableBody.children.length % 2 === 0) {
|
|
row.style.backgroundColor = '#f9f9f9';
|
|
}
|
|
|
|
tableBody.appendChild(row);
|
|
});
|
|
}
|
|
|
|
// Attendre que les données soient disponibles avant de peupler le formulaire
|
|
function initializeForm(retryCount = 0) {
|
|
console.log(`🔄 Tentative d'initialisation ${retryCount + 1}/10`);
|
|
|
|
if (typeof window.eventData !== 'undefined' && window.eventData !== null) {
|
|
console.log('📄 Données disponibles, initialisation du formulaire...');
|
|
populateForm();
|
|
} else if (retryCount < 10) {
|
|
console.log('⏳ En attente des données, nouvelle tentative dans 200ms...');
|
|
setTimeout(() => initializeForm(retryCount + 1), 200);
|
|
} else {
|
|
console.error('❌ Timeout: Impossible de récupérer les données après 10 tentatives');
|
|
showResult('Impossible de charger les données de l\'événement après plusieurs tentatives', 'error');
|
|
}
|
|
}
|
|
|
|
// Démarrer l'initialisation
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('🚀 DOM chargé, démarrage de l\'initialisation...');
|
|
// Attendre un peu pour laisser le temps au script du template de s'exécuter
|
|
setTimeout(() => initializeForm(), 100);
|
|
});
|
|
|
|
// Show fixed result message at bottom of screen
|
|
function showFixedResult(message, type) {
|
|
let resultElement = document.getElementById('result');
|
|
|
|
if (!resultElement) {
|
|
// Create result element if it doesn't exist
|
|
resultElement = document.createElement('div');
|
|
resultElement.id = 'result';
|
|
document.body.appendChild(resultElement);
|
|
}
|
|
|
|
// Style the element as fixed at bottom
|
|
resultElement.style.cssText = `
|
|
position: fixed;
|
|
bottom: 20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
z-index: 10000;
|
|
max-width: 90%;
|
|
width: auto;
|
|
min-width: 300px;
|
|
padding: 15px 45px 15px 15px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
font-family: Arial, sans-serif;
|
|
font-size: 14px;
|
|
line-height: 1.4;
|
|
display: block;
|
|
`;
|
|
|
|
// Set colors based on type
|
|
let bgColor, textColor, borderColor;
|
|
switch (type) {
|
|
case 'success':
|
|
bgColor = '#d4edda';
|
|
textColor = '#155724';
|
|
borderColor = '#c3e6cb';
|
|
break;
|
|
case 'error':
|
|
bgColor = '#f8d7da';
|
|
textColor = '#721c24';
|
|
borderColor = '#f5c6cb';
|
|
break;
|
|
case 'loading':
|
|
bgColor = '#d1ecf1';
|
|
textColor = '#0c5460';
|
|
borderColor = '#bee5eb';
|
|
break;
|
|
default:
|
|
bgColor = '#e2e3e5';
|
|
textColor = '#383d41';
|
|
borderColor = '#d6d8db';
|
|
}
|
|
|
|
resultElement.style.backgroundColor = bgColor;
|
|
resultElement.style.color = textColor;
|
|
resultElement.style.border = `1px solid ${borderColor}`;
|
|
|
|
// Add close button
|
|
const closeButton = document.createElement('span');
|
|
closeButton.innerHTML = '×';
|
|
closeButton.style.cssText = `
|
|
position: absolute;
|
|
top: 8px;
|
|
right: 12px;
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
color: ${textColor};
|
|
opacity: 0.7;
|
|
line-height: 1;
|
|
`;
|
|
|
|
closeButton.addEventListener('click', function() {
|
|
resultElement.style.display = 'none';
|
|
});
|
|
|
|
closeButton.addEventListener('mouseenter', function() {
|
|
this.style.opacity = '1';
|
|
});
|
|
|
|
closeButton.addEventListener('mouseleave', function() {
|
|
this.style.opacity = '0.7';
|
|
});
|
|
|
|
// Set message content
|
|
resultElement.innerHTML = message;
|
|
resultElement.appendChild(closeButton);
|
|
|
|
console.log(`📢 Message fixe affiché (${type}):`, message);
|
|
}
|
|
|
|
// Add marker on map click
|
|
map.on('click', function(e) {
|
|
marker.setLngLat(e.lngLat).addTo(map);
|
|
});
|
|
|
|
// Add functionality for swapping coordinates button
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const swapButton = document.getElementById('swapCoordinatesButton');
|
|
if (swapButton) {
|
|
swapButton.addEventListener('click', function() {
|
|
if (!marker || !marker.getLngLat()) {
|
|
showResult('Veuillez d\'abord placer un marqueur sur la carte', 'error');
|
|
return;
|
|
}
|
|
|
|
const currentLngLat = marker.getLngLat();
|
|
const swappedLngLat = [currentLngLat.lat, currentLngLat.lng];
|
|
|
|
// Update marker position
|
|
marker.setLngLat(swappedLngLat);
|
|
|
|
// Show confirmation message
|
|
showResult(`Coordonnées inversées: ${currentLngLat.lng.toFixed(6)}, ${currentLngLat.lat.toFixed(6)} → ${swappedLngLat[0].toFixed(6)}, ${swappedLngLat[1].toFixed(6)}`, 'success');
|
|
|
|
// Auto-hide success message after 3 seconds
|
|
setTimeout(() => {
|
|
const resultElement = document.getElementById('result');
|
|
if (resultElement && resultElement.className === 'success') {
|
|
resultElement.style.display = 'none';
|
|
}
|
|
}, 3000);
|
|
});
|
|
}
|
|
});
|
|
|
|
// Function to show result message
|
|
function showResult(message, type) {
|
|
const resultElement = document.getElementById('result');
|
|
resultElement.textContent = message;
|
|
resultElement.className = type;
|
|
resultElement.style.display = 'block';
|
|
|
|
// Scroll to result
|
|
resultElement.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
|
|
// Handle form submission
|
|
document.getElementById('eventForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
// Disable any ongoing validation during submission
|
|
window.validationEnabled = false;
|
|
console.log('🔒 Validation désactivée pendant la modification');
|
|
|
|
// Get event ID
|
|
const eventId = document.getElementById('eventId').value;
|
|
|
|
// Get form values
|
|
const label = document.getElementById('label').value;
|
|
const type = document.getElementById('type').value;
|
|
const what = document.getElementById('what').value;
|
|
const what_series = document.getElementById('what_series').value;
|
|
const where = document.getElementById('where').value;
|
|
const start = document.getElementById('start').value;
|
|
const stop = document.getElementById('stop').value;
|
|
|
|
// Check if marker is set
|
|
if (!marker.getLngLat()) {
|
|
showResult('Please set a location by clicking on the map', 'error');
|
|
return;
|
|
}
|
|
|
|
// Get marker coordinates
|
|
const lngLat = marker.getLngLat();
|
|
|
|
// Create event object
|
|
const event = {
|
|
type: 'Feature',
|
|
geometry: {
|
|
type: 'Point',
|
|
coordinates: [lngLat.lng, lngLat.lat]
|
|
},
|
|
properties: {
|
|
label: label,
|
|
type: type,
|
|
what: what,
|
|
start: start,
|
|
stop: stop
|
|
}
|
|
};
|
|
|
|
// Add optional properties if provided
|
|
if (what_series) {
|
|
event.properties['what:series'] = what_series;
|
|
}
|
|
|
|
if (where) {
|
|
event.properties.where = where;
|
|
}
|
|
|
|
// Submit event to OEDB API
|
|
fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(event)
|
|
})
|
|
.then(response => {
|
|
if (response.ok) {
|
|
return response.json();
|
|
} else {
|
|
return response.text().then(text => {
|
|
throw new Error(text || response.statusText);
|
|
});
|
|
}
|
|
})
|
|
.then(data => {
|
|
console.log('📅 Réponse API de modification:', data);
|
|
|
|
// Extract event ID from response (handle different response structures)
|
|
let eventId = null;
|
|
if (data.properties && data.properties.id) {
|
|
eventId = data.properties.id;
|
|
} else if (data.id) {
|
|
eventId = data.id;
|
|
} else if (typeof data === 'string') {
|
|
eventId = data;
|
|
} else {
|
|
// Fallback: use the eventId from the form
|
|
eventId = document.getElementById('eventId').value;
|
|
}
|
|
|
|
console.log('🆔 ID événement pour les liens:', eventId);
|
|
|
|
let successMessage = `✅ Événement mis à jour avec succès !${eventId ? ` ID: ${eventId}` : ''}`;
|
|
|
|
if (eventId) {
|
|
successMessage += `<br><br><a href="/demo/by_id/${eventId}" style="color: #0078ff; text-decoration: none; font-weight: bold;">
|
|
<i class="fas fa-eye"></i> Voir l'événement
|
|
</a> | `;
|
|
}
|
|
|
|
successMessage += `<a href="/demo" style="color: #0078ff; text-decoration: none; font-weight: bold;">
|
|
<i class="fas fa-map"></i> Retour à la carte
|
|
</a>`;
|
|
|
|
showFixedResult(successMessage, 'success');
|
|
})
|
|
.catch(error => {
|
|
console.error('❌ Erreur lors de la modification:', error);
|
|
showFixedResult(`❌ Erreur lors de la modification<br><small>${error.message}</small>`, 'error');
|
|
})
|
|
.finally(() => {
|
|
// Re-enable validation after operation is complete
|
|
setTimeout(() => {
|
|
window.validationEnabled = true;
|
|
console.log('🔓 Validation réactivée');
|
|
}, 1000);
|
|
});
|
|
});
|
|
|
|
// Handle delete button click
|
|
document.getElementById('deleteButton').addEventListener('click', function() {
|
|
// Get event ID
|
|
const eventId = document.getElementById('eventId').value;
|
|
|
|
// Show confirmation dialog
|
|
if (confirm('Êtes-vous sûr de vouloir supprimer cet événement ? Cette action ne peut pas être annulée.')) {
|
|
// Show loading message
|
|
showResult('Suppression en cours...', 'info');
|
|
|
|
// Submit delete request to external API
|
|
fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
})
|
|
.then(response => {
|
|
if (response.ok || response.status === 204) {
|
|
showResult('✅ Événement supprimé avec succès !', 'success');
|
|
|
|
// Add link to go back to map
|
|
const resultElement = document.getElementById('result');
|
|
resultElement.innerHTML += `<p><a href="/demo">Retour à la carte</a></p>`;
|
|
|
|
// Disable form controls
|
|
const formElements = document.querySelectorAll('#eventForm input, #eventForm select, #eventForm button');
|
|
formElements.forEach(element => {
|
|
element.disabled = true;
|
|
});
|
|
|
|
// Redirect to demo page after 3 seconds
|
|
setTimeout(() => {
|
|
window.location.href = '/demo';
|
|
}, 3000);
|
|
} else if (response.status === 404) {
|
|
throw new Error('Événement non trouvé sur l\'API externe');
|
|
} else if (response.status === 403) {
|
|
throw new Error('Accès non autorisé - un secret pourrait être requis pour supprimer cet événement');
|
|
} else {
|
|
return response.text().then(text => {
|
|
throw new Error(text || `Erreur HTTP ${response.status}: ${response.statusText}`);
|
|
});
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Erreur lors de la suppression:', error);
|
|
if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
|
|
showResult('❌ Erreur de connexion : Impossible de joindre l\'API api.openeventdatabase.org', 'error');
|
|
} else {
|
|
showResult(`❌ Erreur lors de la suppression : ${error.message}`, 'error');
|
|
}
|
|
});
|
|
}
|
|
}); |