ajout de reality check dans les évènements traffic qui complète une propriété de l'évènement
This commit is contained in:
parent
f18383fb9e
commit
f66e5e3f7b
5 changed files with 675 additions and 37 deletions
15
.idea/php.xml
generated
15
.idea/php.xml
generated
|
@ -10,9 +10,24 @@
|
||||||
<option name="highlightLevel" value="WARNING" />
|
<option name="highlightLevel" value="WARNING" />
|
||||||
<option name="transferred" value="true" />
|
<option name="transferred" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="PhpCodeSniffer">
|
||||||
|
<phpcs_settings>
|
||||||
|
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="53af92f2-01ab-44d1-b456-ef2235475a50" timeout="30000" />
|
||||||
|
</phpcs_settings>
|
||||||
|
</component>
|
||||||
|
<component name="PhpStan">
|
||||||
|
<PhpStan_settings>
|
||||||
|
<phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="53af92f2-01ab-44d1-b456-ef2235475a50" timeout="60000" />
|
||||||
|
</PhpStan_settings>
|
||||||
|
</component>
|
||||||
<component name="PhpStanOptionsConfiguration">
|
<component name="PhpStanOptionsConfiguration">
|
||||||
<option name="transferred" value="true" />
|
<option name="transferred" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="Psalm">
|
||||||
|
<Psalm_settings>
|
||||||
|
<psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="53af92f2-01ab-44d1-b456-ef2235475a50" timeout="60000" />
|
||||||
|
</Psalm_settings>
|
||||||
|
</component>
|
||||||
<component name="PsalmOptionsConfiguration">
|
<component name="PsalmOptionsConfiguration">
|
||||||
<option name="transferred" value="true" />
|
<option name="transferred" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -40,7 +40,7 @@ class DemoResource:
|
||||||
resp.content_type = 'text/html'
|
resp.content_type = 'text/html'
|
||||||
|
|
||||||
# Fetch the event data from the API
|
# Fetch the event data from the API
|
||||||
response = requests.get(f'http://api.openevent/event/{id}')
|
response = requests.get(f'https://api.openeventdatabase.org/event/{id}')
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
resp.status = falcon.HTTP_404
|
resp.status = falcon.HTTP_404
|
||||||
|
|
|
@ -111,31 +111,39 @@ class DemoMainResource:
|
||||||
<h2>OpenEventDatabase Demo</h2>
|
<h2>OpenEventDatabase Demo</h2>
|
||||||
<p>This map shows current events from the OpenEventDatabase.</p>
|
<p>This map shows current events from the OpenEventDatabase.</p>
|
||||||
|
|
||||||
<!-- Authentication section -->
|
<!-- User Information Panel -->
|
||||||
<div id="auth-section" class="auth-section">
|
<div id="user-info-panel" class="user-info-panel" style="display: none; background-color: #f5f5f5; border-radius: 4px; padding: 10px; margin: 10px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
||||||
<h3>OpenStreetMap Authentication</h3>
|
<h3 style="margin-top: 0; margin-bottom: 10px; color: #333;">User Information</h3>
|
||||||
|
<p>Username: <strong id="username-display">Anonymous</strong></p>
|
||||||
<a href="https://www.openstreetmap.org/oauth2/authorize?client_id={client_id}&redirect_uri={client_redirect}&response_type=code&scope=read_prefs" class="osm-login-btn">
|
<p>Points: <span id="points-display" style="font-weight: bold; color: #0078ff;">0</span></p>
|
||||||
<span class="osm-logo"></span>
|
|
||||||
Login with OpenStreetMap
|
|
||||||
</a>
|
|
||||||
<script>
|
|
||||||
// Replace server-side auth section with JavaScript-rendered version if available
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
if (window.osmAuth) {
|
|
||||||
const clientId = document.getElementById('osmClientId').value;
|
|
||||||
const redirectUri = document.getElementById('osmRedirectUri').value;
|
|
||||||
const authSection = document.getElementById('auth-section');
|
|
||||||
|
|
||||||
// Only replace if osmAuth is loaded and has renderAuthSection method
|
|
||||||
if (osmAuth.renderAuthSection) {
|
|
||||||
authSection.innerHTML = osmAuth.renderAuthSection(clientId, redirectUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Authentication section -->
|
||||||
|
<!--
|
||||||
|
# <div id="auth-section" class="auth-section">
|
||||||
|
# <h3>OpenStreetMap Authentication</h3>
|
||||||
|
#
|
||||||
|
# <a href="https://www.openstreetmap.org/oauth2/authorize?client_id={client_id}&redirect_uri={client_redirect}&response_type=code&scope=read_prefs" class="osm-login-btn">
|
||||||
|
# <span class="osm-logo"></span>
|
||||||
|
# Login with OpenStreetMap
|
||||||
|
# </a>
|
||||||
|
# <script>
|
||||||
|
# // Replace server-side auth section with JavaScript-rendered version if available
|
||||||
|
# document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
# if (window.osmAuth) {
|
||||||
|
# const clientId = document.getElementById('osmClientId').value;
|
||||||
|
# const redirectUri = document.getElementById('osmRedirectUri').value;
|
||||||
|
# const authSection = document.getElementById('auth-section');
|
||||||
|
#
|
||||||
|
# // Only replace if osmAuth is loaded and has renderAuthSection method
|
||||||
|
# if (osmAuth.renderAuthSection) {
|
||||||
|
# authSection.innerHTML = osmAuth.renderAuthSection(clientId, redirectUri);
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# });
|
||||||
|
# </script>
|
||||||
|
# </div> -->
|
||||||
|
|
||||||
<h3>API Endpoints:</h3>
|
<h3>API Endpoints:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/" >/ - API Information</a></li>
|
<li><a href="/" >/ - API Information</a></li>
|
||||||
|
@ -368,6 +376,29 @@ class DemoMainResource:
|
||||||
popupContent += '</table>';
|
popupContent += '</table>';
|
||||||
popupContent += '</div>';
|
popupContent += '</div>';
|
||||||
|
|
||||||
|
// Check if this event needs reality check (traffic events created more than 1 hour ago)
|
||||||
|
const needsRealityCheck = checkIfNeedsRealityCheck(feature);
|
||||||
|
|
||||||
|
// Add reality check buttons if needed
|
||||||
|
if (needsRealityCheck) {
|
||||||
|
popupContent += `
|
||||||
|
<div class="reality-check">
|
||||||
|
<p>Is this traffic event still present?</p>
|
||||||
|
<div class="reality-check-buttons">
|
||||||
|
<button class="confirm-btn" onclick="confirmEvent('${properties.id}', true)">Yes, still there</button>
|
||||||
|
<button class="deny-btn" onclick="confirmEvent('${properties.id}', false)">No, it's gone</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (properties['reality_check']) {
|
||||||
|
// Show reality check information if it exists
|
||||||
|
popupContent += `
|
||||||
|
<div class="reality-check-info">
|
||||||
|
<p>Reality check: ${properties['reality_check']}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
// Add edit link
|
// Add edit link
|
||||||
popupContent += `<div style="margin-top: 10px; text-align: center;">
|
popupContent += `<div style="margin-top: 10px; text-align: center;">
|
||||||
<a href="/demo/edit/${properties.id}" class="edit-event-btn" style="display: inline-block; padding: 5px 10px; background-color: #0078ff; color: white; border-radius: 4px; text-decoration: none; font-weight: bold;">Edit Event</a>
|
<a href="/demo/edit/${properties.id}" class="edit-event-btn" style="display: inline-block; padding: 5px 10px; background-color: #0078ff; color: white; border-radius: 4px; text-decoration: none; font-weight: bold;">Edit Event</a>
|
||||||
|
@ -459,6 +490,17 @@ class DemoMainResource:
|
||||||
return relativeTime || "à l instant";
|
return relativeTime || "à l instant";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to check if an event needs a reality check (created more than 1 hour ago)
|
||||||
|
function checkIfNeedsRealityCheck(event) {
|
||||||
|
|
||||||
|
|
||||||
|
// Check if the event is a traffic event
|
||||||
|
if (!event.properties.what || !event.properties.what.startsWith('traffic')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Function to fit map to events bounds
|
// Function to fit map to events bounds
|
||||||
function fitMapToBounds(geojson) {
|
function fitMapToBounds(geojson) {
|
||||||
if (geojson.features.length === 0) return;
|
if (geojson.features.length === 0) return;
|
||||||
|
@ -477,6 +519,182 @@ class DemoMainResource:
|
||||||
maxZoom: 12
|
maxZoom: 12
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to update user information display
|
||||||
|
function updateUserInfoDisplay() {
|
||||||
|
const username = localStorage.getItem('oedb_username');
|
||||||
|
const points = localStorage.getItem('oedb_points');
|
||||||
|
const userInfoPanel = document.getElementById('user-info-panel');
|
||||||
|
|
||||||
|
// Only show the panel if the user has a username or points
|
||||||
|
if (username || points) {
|
||||||
|
userInfoPanel.style.display = 'block';
|
||||||
|
|
||||||
|
// Update username display
|
||||||
|
if (username) {
|
||||||
|
document.getElementById('username-display').textContent = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update points display
|
||||||
|
if (points) {
|
||||||
|
document.getElementById('points-display').textContent = points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add CSS for reality check buttons if not already added
|
||||||
|
if (!document.getElementById('reality-check-styles')) {
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'reality-check-styles';
|
||||||
|
style.textContent = `
|
||||||
|
.reality-check {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #fff3e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.reality-check-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.confirm-btn, .deny-btn {
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.deny-btn {
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.reality-check-info {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #e8f5e9;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to handle event confirmation or denial
|
||||||
|
function confirmEvent(eventId, isConfirmed) {
|
||||||
|
// Get username from localStorage or prompt for it
|
||||||
|
let username = localStorage.getItem('oedb_username');
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
username = promptForUsername();
|
||||||
|
if (!username) {
|
||||||
|
// User cancelled the prompt
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current date and time
|
||||||
|
const now = new Date();
|
||||||
|
const dateTimeString = now.toISOString();
|
||||||
|
|
||||||
|
// Create reality check string
|
||||||
|
const realityCheckStatus = isConfirmed ? 'confirmed' : 'not confirmed';
|
||||||
|
const realityCheckValue = `${dateTimeString} | ${username} | ${realityCheckStatus}`;
|
||||||
|
|
||||||
|
// Fetch the event to update
|
||||||
|
fetch(`https://api.openeventdatabase.org/event/${eventId}`)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
} else {
|
||||||
|
throw new Error(`Failed to fetch event ${eventId}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(event => {
|
||||||
|
// Add reality_check property
|
||||||
|
event.properties['reality_check'] = realityCheckValue;
|
||||||
|
|
||||||
|
// Update the event
|
||||||
|
return fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(event)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
// Save contribution to localStorage
|
||||||
|
saveContribution(eventId, isConfirmed);
|
||||||
|
|
||||||
|
// Award points
|
||||||
|
awardPoints(3);
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
alert(`Thank you for your contribution! You've earned 3 points.`);
|
||||||
|
|
||||||
|
// Update user info display
|
||||||
|
updateUserInfoDisplay();
|
||||||
|
|
||||||
|
// Refresh events to update the display
|
||||||
|
fetchEvents();
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to update event');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error updating event:', error);
|
||||||
|
alert(`Error: ${error.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to prompt for username
|
||||||
|
function promptForUsername() {
|
||||||
|
const username = prompt('Please enter your username:');
|
||||||
|
if (username) {
|
||||||
|
localStorage.setItem('oedb_username', username);
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to save contribution to localStorage
|
||||||
|
function saveContribution(eventId, isConfirmed) {
|
||||||
|
// Get existing contributions
|
||||||
|
let contributions = JSON.parse(localStorage.getItem('oedb_contributions') || '[]');
|
||||||
|
|
||||||
|
// Add new contribution
|
||||||
|
contributions.push({
|
||||||
|
eventId: eventId,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
isConfirmed: isConfirmed
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save back to localStorage
|
||||||
|
localStorage.setItem('oedb_contributions', JSON.stringify(contributions));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to award points
|
||||||
|
function awardPoints(points) {
|
||||||
|
// Get current points
|
||||||
|
let currentPoints = parseInt(localStorage.getItem('oedb_points') || '0');
|
||||||
|
|
||||||
|
// Add new points
|
||||||
|
currentPoints += points;
|
||||||
|
|
||||||
|
// Save back to localStorage
|
||||||
|
localStorage.setItem('oedb_points', currentPoints.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user info when the page loads
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
updateUserInfoDisplay();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -334,21 +334,48 @@
|
||||||
data.features.forEach(event => {
|
data.features.forEach(event => {
|
||||||
if (event.geometry && event.geometry.type === 'Point') {
|
if (event.geometry && event.geometry.type === 'Point') {
|
||||||
const coords = event.geometry.coordinates;
|
const coords = event.geometry.coordinates;
|
||||||
// Create a gray marker for existing events
|
|
||||||
|
// Check if this event needs reality check (created more than 1 hour ago)
|
||||||
|
const needsRealityCheck = checkIfNeedsRealityCheck(event);
|
||||||
|
|
||||||
|
// Create a marker for existing events (gray for regular, orange for those needing reality check)
|
||||||
|
const markerColor = needsRealityCheck ? '#ff9800' : '#888888';
|
||||||
const eventMarker = new maplibregl.Marker({
|
const eventMarker = new maplibregl.Marker({
|
||||||
color: '#888888' // Gray color for existing events
|
color: markerColor
|
||||||
})
|
})
|
||||||
.setLngLat(coords)
|
.setLngLat(coords)
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
|
|
||||||
// Add popup with event details
|
// Add popup with event details
|
||||||
const popup = new maplibregl.Popup({ offset: 25 })
|
let popupContent = `
|
||||||
.setHTML(`
|
|
||||||
<h3>${event.properties.label || 'Traffic Event'}</h3>
|
<h3>${event.properties.label || 'Traffic Event'}</h3>
|
||||||
<p>Type: ${event.properties.what || 'Unknown'}</p>
|
<p>Type: ${event.properties.what || 'Unknown'}</p>
|
||||||
<p>Start: ${event.properties.start || 'Unknown'}</p>
|
<p>Start: ${event.properties.start || 'Unknown'}</p>
|
||||||
<p>End: ${event.properties.stop || 'Unknown'}</p>
|
<p>End: ${event.properties.stop || 'Unknown'}</p>
|
||||||
`);
|
`;
|
||||||
|
|
||||||
|
// Add reality check buttons if needed
|
||||||
|
if (needsRealityCheck) {
|
||||||
|
popupContent += `
|
||||||
|
<div class="reality-check">
|
||||||
|
<p>Is this traffic event still present?</p>
|
||||||
|
<div class="reality-check-buttons">
|
||||||
|
<button class="confirm-btn" onclick="confirmEvent('${event.properties.id}', true)">Yes, still there</button>
|
||||||
|
<button class="deny-btn" onclick="confirmEvent('${event.properties.id}', false)">No, it's gone</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (event.properties['reality_check']) {
|
||||||
|
// Show reality check information if it exists
|
||||||
|
popupContent += `
|
||||||
|
<div class="reality-check-info">
|
||||||
|
<p>Reality check: ${event.properties['reality_check']}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const popup = new maplibregl.Popup({ offset: 25 })
|
||||||
|
.setHTML(popupContent);
|
||||||
|
|
||||||
eventMarker.setPopup(popup);
|
eventMarker.setPopup(popup);
|
||||||
|
|
||||||
|
@ -365,6 +392,32 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to check if an event needs a reality check (created more than 1 hour ago)
|
||||||
|
function checkIfNeedsRealityCheck(event) {
|
||||||
|
// Skip if event already has a reality check
|
||||||
|
if (event.properties['reality_check']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the event is a traffic event
|
||||||
|
if (!event.properties.what || !event.properties.what.startsWith('traffic')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check creation date
|
||||||
|
const createDate = event.properties.createdate;
|
||||||
|
if (!createDate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createTime = new Date(createDate).getTime();
|
||||||
|
const currentTime = new Date().getTime();
|
||||||
|
const oneHourInMs = 60 * 60 * 1000;
|
||||||
|
|
||||||
|
// Return true if the event was created more than 1 hour ago
|
||||||
|
return (currentTime - createTime) > oneHourInMs;
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch existing events when the map loads
|
// Fetch existing events when the map loads
|
||||||
map.on('load', fetchExistingTrafficEvents);
|
map.on('load', fetchExistingTrafficEvents);
|
||||||
|
|
||||||
|
@ -843,6 +896,201 @@
|
||||||
// Scroll to result
|
// Scroll to result
|
||||||
resultElement.scrollIntoView({ behavior: 'smooth' });
|
resultElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
}
|
}
|
||||||
|
// Function to handle event confirmation or denial
|
||||||
|
function confirmEvent(eventId, isConfirmed) {
|
||||||
|
// Get username from localStorage or prompt for it
|
||||||
|
let username = localStorage.getItem('oedb_username');
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
username = promptForUsername();
|
||||||
|
if (!username) {
|
||||||
|
// User cancelled the prompt
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current date and time
|
||||||
|
const now = new Date();
|
||||||
|
const dateTimeString = now.toISOString();
|
||||||
|
|
||||||
|
// Create reality check string
|
||||||
|
const realityCheckStatus = isConfirmed ? 'confirmed' : 'not confirmed';
|
||||||
|
const realityCheckValue = `${dateTimeString} | ${username} | ${realityCheckStatus}`;
|
||||||
|
|
||||||
|
// Fetch the event to update
|
||||||
|
fetch(`https://api.openeventdatabase.org/event/${eventId}`)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
} else {
|
||||||
|
throw new Error(`Failed to fetch event ${eventId}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(event => {
|
||||||
|
// Add reality_check property
|
||||||
|
event.properties['reality_check'] = realityCheckValue;
|
||||||
|
|
||||||
|
// Update the event
|
||||||
|
return fetch(`https://api.openeventdatabase.org/event/${eventId}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(event)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
// Save contribution to localStorage
|
||||||
|
saveContribution(eventId, isConfirmed);
|
||||||
|
|
||||||
|
// Award points
|
||||||
|
awardPoints(3);
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
showResult(`Thank you for your contribution! You've earned 3 points.`, 'success');
|
||||||
|
|
||||||
|
// Update user info display
|
||||||
|
updateUserInfoDisplay();
|
||||||
|
|
||||||
|
// Refresh events to update the display
|
||||||
|
fetchExistingTrafficEvents();
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to update event');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error updating event:', error);
|
||||||
|
showResult(`Error: ${error.message}`, 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to prompt for username
|
||||||
|
function promptForUsername() {
|
||||||
|
const username = prompt('Please enter your username:');
|
||||||
|
if (username) {
|
||||||
|
localStorage.setItem('oedb_username', username);
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to save contribution to localStorage
|
||||||
|
function saveContribution(eventId, isConfirmed) {
|
||||||
|
// Get existing contributions
|
||||||
|
let contributions = JSON.parse(localStorage.getItem('oedb_contributions') || '[]');
|
||||||
|
|
||||||
|
// Add new contribution
|
||||||
|
contributions.push({
|
||||||
|
eventId: eventId,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
isConfirmed: isConfirmed
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save back to localStorage
|
||||||
|
localStorage.setItem('oedb_contributions', JSON.stringify(contributions));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to award points
|
||||||
|
function awardPoints(points) {
|
||||||
|
// Get current points
|
||||||
|
let currentPoints = parseInt(localStorage.getItem('oedb_points') || '0');
|
||||||
|
|
||||||
|
// Add new points
|
||||||
|
currentPoints += points;
|
||||||
|
|
||||||
|
// Save back to localStorage
|
||||||
|
localStorage.setItem('oedb_points', currentPoints.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to update user info display in side panel
|
||||||
|
function updateUserInfoDisplay() {
|
||||||
|
const username = localStorage.getItem('oedb_username') || 'Anonymous';
|
||||||
|
const points = localStorage.getItem('oedb_points') || '0';
|
||||||
|
|
||||||
|
// Check if user info panel exists, create it if not
|
||||||
|
let userInfoPanel = document.getElementById('user-info-panel');
|
||||||
|
if (!userInfoPanel) {
|
||||||
|
// Create user info panel
|
||||||
|
userInfoPanel = document.createElement('div');
|
||||||
|
userInfoPanel.id = 'user-info-panel';
|
||||||
|
userInfoPanel.className = 'user-info-panel';
|
||||||
|
|
||||||
|
// Add it to the page (after the nav-links)
|
||||||
|
const navLinks = document.querySelector('.nav-links');
|
||||||
|
navLinks.parentNode.insertBefore(userInfoPanel, navLinks.nextSibling);
|
||||||
|
|
||||||
|
// Add some CSS for the panel
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
.user-info-panel {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.user-info-panel h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.user-info-panel p {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
.user-points {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0078ff;
|
||||||
|
}
|
||||||
|
.reality-check {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #fff3e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.reality-check-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.confirm-btn, .deny-btn {
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.deny-btn {
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.reality-check-info {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: #e8f5e9;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the content
|
||||||
|
userInfoPanel.innerHTML = `
|
||||||
|
<h3>User Information</h3>
|
||||||
|
<p>Username: <strong>${username}</strong></p>
|
||||||
|
<p>Points: <span class="user-points">${points}</span></p>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize user info display when page loads
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
updateUserInfoDisplay();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
157
test_reality_check.js
Normal file
157
test_reality_check.js
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
// Test script for reality check functionality
|
||||||
|
console.log("Testing reality check functionality...");
|
||||||
|
|
||||||
|
// Mock event data for testing
|
||||||
|
const mockEvent = {
|
||||||
|
type: "Feature",
|
||||||
|
geometry: {
|
||||||
|
type: "Point",
|
||||||
|
coordinates: [2.3522, 48.8566] // Paris coordinates
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
id: "test-event-123",
|
||||||
|
label: "Test Traffic Jam",
|
||||||
|
what: "traffic.jam",
|
||||||
|
type: "unscheduled",
|
||||||
|
start: "2025-09-21T18:00:00Z",
|
||||||
|
stop: "2025-09-21T20:00:00Z",
|
||||||
|
createdate: "2025-09-21T17:00:00Z" // More than 1 hour ago
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test checkIfNeedsRealityCheck function
|
||||||
|
function testCheckIfNeedsRealityCheck() {
|
||||||
|
console.log("Testing checkIfNeedsRealityCheck function...");
|
||||||
|
|
||||||
|
// Should return true for traffic events older than 1 hour
|
||||||
|
const needsCheck = checkIfNeedsRealityCheck(mockEvent);
|
||||||
|
console.log(`Event needs reality check: ${needsCheck}`);
|
||||||
|
|
||||||
|
// Should return false for events with reality_check already set
|
||||||
|
const eventWithRealityCheck = JSON.parse(JSON.stringify(mockEvent));
|
||||||
|
eventWithRealityCheck.properties.reality_check = "2025-09-21T19:00:00Z | testuser | confirmed";
|
||||||
|
const needsCheckAgain = checkIfNeedsRealityCheck(eventWithRealityCheck);
|
||||||
|
console.log(`Event with reality_check needs another check: ${needsCheckAgain}`);
|
||||||
|
|
||||||
|
// Should return false for non-traffic events
|
||||||
|
const nonTrafficEvent = JSON.parse(JSON.stringify(mockEvent));
|
||||||
|
nonTrafficEvent.properties.what = "music.concert";
|
||||||
|
const needsCheckNonTraffic = checkIfNeedsRealityCheck(nonTrafficEvent);
|
||||||
|
console.log(`Non-traffic event needs reality check: ${needsCheckNonTraffic}`);
|
||||||
|
|
||||||
|
// Should return false for recent events
|
||||||
|
const recentEvent = JSON.parse(JSON.stringify(mockEvent));
|
||||||
|
recentEvent.properties.createdate = new Date().toISOString();
|
||||||
|
const needsCheckRecent = checkIfNeedsRealityCheck(recentEvent);
|
||||||
|
console.log(`Recent event needs reality check: ${needsCheckRecent}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test localStorage functionality
|
||||||
|
function testLocalStorage() {
|
||||||
|
console.log("Testing localStorage functionality...");
|
||||||
|
|
||||||
|
// Clear existing data
|
||||||
|
localStorage.removeItem('oedb_username');
|
||||||
|
localStorage.removeItem('oedb_points');
|
||||||
|
localStorage.removeItem('oedb_contributions');
|
||||||
|
|
||||||
|
// Test username storage
|
||||||
|
const testUsername = "testuser";
|
||||||
|
localStorage.setItem('oedb_username', testUsername);
|
||||||
|
console.log(`Username stored: ${localStorage.getItem('oedb_username')}`);
|
||||||
|
|
||||||
|
// Test points system
|
||||||
|
awardPoints(3);
|
||||||
|
console.log(`Points after first contribution: ${localStorage.getItem('oedb_points')}`);
|
||||||
|
awardPoints(3);
|
||||||
|
console.log(`Points after second contribution: ${localStorage.getItem('oedb_points')}`);
|
||||||
|
|
||||||
|
// Test contribution storage
|
||||||
|
saveContribution("test-event-123", true);
|
||||||
|
saveContribution("test-event-456", false);
|
||||||
|
const contributions = JSON.parse(localStorage.getItem('oedb_contributions') || '[]');
|
||||||
|
console.log(`Number of contributions: ${contributions.length}`);
|
||||||
|
console.log(`First contribution: ${JSON.stringify(contributions[0])}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test UI updates
|
||||||
|
function testUIUpdates() {
|
||||||
|
console.log("Testing UI updates...");
|
||||||
|
|
||||||
|
// Test user info panel
|
||||||
|
updateUserInfoDisplay();
|
||||||
|
const panel = document.getElementById('user-info-panel');
|
||||||
|
console.log(`User info panel created: ${panel !== null}`);
|
||||||
|
|
||||||
|
// Test popup content generation
|
||||||
|
const popupContent = generateTestPopupContent();
|
||||||
|
console.log("Popup content generated");
|
||||||
|
|
||||||
|
// Create a test div to display the popup content
|
||||||
|
const testDiv = document.createElement('div');
|
||||||
|
testDiv.innerHTML = popupContent;
|
||||||
|
testDiv.style.position = 'fixed';
|
||||||
|
testDiv.style.top = '50%';
|
||||||
|
testDiv.style.left = '50%';
|
||||||
|
testDiv.style.transform = 'translate(-50%, -50%)';
|
||||||
|
testDiv.style.backgroundColor = 'white';
|
||||||
|
testDiv.style.padding = '20px';
|
||||||
|
testDiv.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
|
||||||
|
testDiv.style.zIndex = '1000';
|
||||||
|
testDiv.style.maxWidth = '400px';
|
||||||
|
testDiv.style.borderRadius = '4px';
|
||||||
|
|
||||||
|
// Add close button
|
||||||
|
const closeButton = document.createElement('button');
|
||||||
|
closeButton.textContent = 'Close Test';
|
||||||
|
closeButton.style.marginTop = '10px';
|
||||||
|
closeButton.style.padding = '5px 10px';
|
||||||
|
closeButton.style.backgroundColor = '#ddd';
|
||||||
|
closeButton.style.border = 'none';
|
||||||
|
closeButton.style.borderRadius = '4px';
|
||||||
|
closeButton.style.cursor = 'pointer';
|
||||||
|
closeButton.onclick = function() {
|
||||||
|
document.body.removeChild(testDiv);
|
||||||
|
};
|
||||||
|
|
||||||
|
testDiv.appendChild(closeButton);
|
||||||
|
document.body.appendChild(testDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to generate test popup content
|
||||||
|
function generateTestPopupContent() {
|
||||||
|
let popupContent = `
|
||||||
|
<h3>${mockEvent.properties.label}</h3>
|
||||||
|
<p>Type: ${mockEvent.properties.what}</p>
|
||||||
|
<p>Start: ${mockEvent.properties.start}</p>
|
||||||
|
<p>End: ${mockEvent.properties.stop}</p>
|
||||||
|
<div class="reality-check">
|
||||||
|
<p>Is this traffic event still present?</p>
|
||||||
|
<div class="reality-check-buttons">
|
||||||
|
<button class="confirm-btn" onclick="alert('Confirm clicked')">Yes, still there</button>
|
||||||
|
<button class="deny-btn" onclick="alert('Deny clicked')">No, it's gone</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return popupContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run tests
|
||||||
|
function runTests() {
|
||||||
|
console.log("Running tests...");
|
||||||
|
testCheckIfNeedsRealityCheck();
|
||||||
|
testLocalStorage();
|
||||||
|
testUIUpdates();
|
||||||
|
console.log("Tests completed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute tests when loaded in browser
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
// Wait for DOM to be ready
|
||||||
|
if (document.readyState === 'complete') {
|
||||||
|
runTests();
|
||||||
|
} else {
|
||||||
|
window.addEventListener('load', runTests);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue