styling popup title

This commit is contained in:
Tykayn 2025-09-23 12:53:52 +02:00 committed by tykayn
parent c194862e00
commit 114bcca24e
3 changed files with 171 additions and 90 deletions

View file

@ -69,18 +69,48 @@ class DemoMainResource:
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
max-width: 300px;
transition: all 0.3s ease;
z-index: 10;
}
/* Styles pour listes dépliantes */
#endpoints_list, #demo_pages_list {
/* Responsive styles for the menu */
@media (max-width: 768px) {
.map-overlay {
max-width: 85%;
width: 85%;
font-size: 0.9em;
}
.map-overlay h2 {
font-size: 1.2em;
}
}
@media (max-width: 480px) {
.map-overlay {
max-width: 90%;
width: 90%;
font-size: 0.85em;
}
}
/* Styles pour listes dépliantes et sections collapsibles */
#endpoints_list, #demo_pages_list, .collapsible-content {
display: none;
overflow: hidden;
transition: all 0.3s ease;
}
#endpoints_list_header, #demo_pages_list_header {
#endpoints_list_header, #demo_pages_list_header, .collapsible-header {
cursor: pointer;
user-select: none;
position: relative;
padding-right: 20px;
margin-top: 15px;
margin-bottom: 10px;
}
.toggle-icon {
position: absolute;
right: 0;
font-size: 0.8em;
transition: transform 0.3s ease;
}
#endpoints_list_header:after, #demo_pages_list_header:after {
content: '';
@ -89,7 +119,8 @@ class DemoMainResource:
font-size: 0.8em;
transition: transform 0.3s ease;
}
#endpoints_list_header.active:after, #demo_pages_list_header.active:after {
#endpoints_list_header.active:after, #demo_pages_list_header.active:after,
.collapsible-header.active .toggle-icon {
transform: rotate(180deg);
}
.map-style-control {
@ -213,79 +244,84 @@ class DemoMainResource:
<img src="/static/oedb.png" class="logo" />
OpenEventDatabase Demo</h2>
<p>This map shows current events from the OpenEventDatabase.</p>
<!-- Event addition buttons - always visible -->
<p><a href="/demo/traffic" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Traffic event</a></p>
<p><a href="/demo/add" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Any Event</a></p>
<p><a href="/demo/add" class="add-event-btn" style="display: block; text-align: center; margin-top: 15px; padding: 8px; background-color: #0078ff; color: white; border-radius: 4px; font-weight: bold;">+ Any Event</a></p>
<!-- User Information Panel -->
<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 style="margin-top: 0; margin-bottom: 10px; color: #333;">User Information</h3>
<p>Username: <strong id="username-display">Anonymous</strong></p>
<p>Points: <span id="points-display" style="font-weight: bold; color: #0078ff;">0</span></p>
</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() {
fetchEvents();
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);
<!-- Collapsible information section -->
<h3 id="info_panel_header" class="collapsible-header">Information Panel <span class="toggle-icon"></span></h3>
<div id="info_panel_content" class="collapsible-content">
<!-- User Information Panel -->
<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 style="margin-top: 0; margin-bottom: 10px; color: #333;">User Information</h3>
<p>Username: <strong id="username-display">Anonymous</strong></p>
<p>Points: <span id="points-display" style="font-weight: bold; color: #0078ff;">0</span></p>
</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() {
fetchEvents();
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 id="endpoints_list_header">API Endpoints:</h3>
<ul id="endpoints_list">
<li><a href="/" >/ - API Information</a></li>
<li><a href="/event" >/event - Get Events</a></li>
<li><a href="/stats" >/stats - Database Statistics</a></li>
</ul>
<h3 id="demo_pages_list_header">Demo Pages:</h3>
<ul id="demo_pages_list">
<li><a href="/demo/search" >/demo/search - Advanced Search</a></li>
<li><a href="/demo/by-what" >/demo/by-what - Events by Type</a></li>
<li><a href="/demo/map-by-what" >/demo/map-by-what - Map by Event Type</a></li>
<li><a href="/demo/traffic" >/demo/traffic - Report Traffic Jam</a></li>
<li><a href="/demo/view-events" >/demo/view-events - View Saved Events</a></li>
<li><a href="/event?what=music" >Search Music Events</a></li>
<li><a href="/event?what=sport" >Search Sport Events</a></li>
</ul>
<p class="sources" style="text-align: center; margin-top: 10px;">
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" title="View Source Code on Cipherbliss" style="font-size: 24px;">
<i class="fas fa-code-branch"></i> sources
</a>
</p>
});
</script>
</div> -->
<h3 id="endpoints_list_header">API Endpoints:</h3>
<ul id="endpoints_list">
<li><a href="/" >/ - API Information</a></li>
<li><a href="/event" >/event - Get Events</a></li>
<li><a href="/stats" >/stats - Database Statistics</a></li>
</ul>
<h3 id="demo_pages_list_header">Demo Pages:</h3>
<ul id="demo_pages_list">
<li><a href="/demo/search" >/demo/search - Advanced Search</a></li>
<li><a href="/demo/by-what" >/demo/by-what - Events by Type</a></li>
<li><a href="/demo/map-by-what" >/demo/map-by-what - Map by Event Type</a></li>
<li><a href="/demo/traffic" >/demo/traffic - Report Traffic Jam</a></li>
<li><a href="/demo/view-events" >/demo/view-events - View Saved Events</a></li>
<li><a href="/event?what=music" >Search Music Events</a></li>
<li><a href="/event?what=sport" >Search Sport Events</a></li>
</ul>
<p class="sources" style="text-align: center; margin-top: 10px;">
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" title="View Source Code on Cipherbliss" style="font-size: 24px;">
<i class="fas fa-code-branch"></i> sources
</a>
</p>
</div>
</div>
<script>
// Fonction pour gérer les listes dépliantes
// Fonction pour gérer les listes dépliantes et sections collapsibles
document.addEventListener('DOMContentLoaded', function() {
const endpointsHeader = document.getElementById('endpoints_list_header');
const endpointsList = document.getElementById('endpoints_list');
const demoPagesHeader = document.getElementById('demo_pages_list_header');
const demoPagesList = document.getElementById('demo_pages_list');
const infoPanelHeader = document.getElementById('info_panel_header');
const infoPanelContent = document.getElementById('info_panel_content');
// Fonction pour basculer l'affichage d'une liste
// Fonction pour basculer l'affichage d'une liste ou section
function toggleList(header, list) {
header.addEventListener('click', function() {
if (list.style.display === 'none' || list.style.display === '') {
@ -298,13 +334,15 @@ class DemoMainResource:
});
}
// Initialiser les listes comme repliées
// Initialiser les listes et sections comme repliées
endpointsList.style.display = 'none';
demoPagesList.style.display = 'none';
infoPanelContent.style.display = 'none';
// Ajouter les écouteurs d'événements
toggleList(endpointsHeader, endpointsList);
toggleList(demoPagesHeader, demoPagesList);
toggleList(infoPanelHeader, infoPanelContent);
});
// Map style URLs
@ -346,6 +384,15 @@ class DemoMainResource:
// Add navigation controls
map.addControl(new maplibregl.NavigationControl());
// Add geolocation control
map.addControl(new maplibregl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true,
showUserHeading: true
}));
// Add attribution control with OpenStreetMap attribution
map.addControl(new maplibregl.AttributionControl({
customAttribution: '© <a href="https://www.openstreetmap.org/copyright" >OpenStreetMap</a> contributors'
@ -354,12 +401,21 @@ class DemoMainResource:
// Style switcher functionality
let currentStyle = 'default';
let eventsData = null;
// Array to store markers so they can be removed on refresh
let currentMarkers = [];
// Fetch events when the map is loaded
// Fetch events when the map is loaded and every 30 seconds thereafter
map.on('load', function() {
// Initial fetch
fetchEvents();
// Set up interval to fetch events every 30 seconds
setInterval(fetchEvents, 30000);
console.log('Event refresh interval set: events will update every 30 seconds');
});
// Function to fetch events from the API
@ -387,24 +443,39 @@ class DemoMainResource:
// Function to add events to the map
function addEventsToMap(geojson) {
// Add a GeoJSON source for events
map.addSource('events', {
type: 'geojson',
data: geojson
});
// Remove all existing markers
if (currentMarkers.length > 0) {
currentMarkers.forEach(marker => marker.remove());
currentMarkers = [];
console.log('Removed existing markers');
}
// Add a circle layer for events
map.addLayer({
id: 'events-circle',
type: 'circle',
source: 'events',
paint: {
'circle-radius': 8,
'circle-color': '#FF5722',
'circle-stroke-width': 2,
'circle-stroke-color': '#FFFFFF'
}
});
// Check if the source already exists
if (map.getSource('events')) {
// Update the existing source with new data
map.getSource('events').setData(geojson);
console.log('Updated existing events source with new data');
} else {
// Add a new GeoJSON source for events
map.addSource('events', {
type: 'geojson',
data: geojson
});
// Add a circle layer for events
map.addLayer({
id: 'events-circle',
type: 'circle',
source: 'events',
paint: {
'circle-radius': 8,
'circle-color': '#FF5722',
'circle-stroke-width': 2,
'circle-stroke-color': '#FFFFFF'
}
});
console.log('Added new events source and layer');
}
// Add popups for events
geojson.features.forEach(feature => {
@ -531,11 +602,14 @@ class DemoMainResource:
<i class="fas fa-${iconClass}" style="color: ${iconColor}; font-size: 16px;"></i>
</span>`;
// Add marker with popup
new maplibregl.Marker(el)
.setLngLat(coordinates)
.setPopup(popup)
.addTo(map);
// Add marker with popup and store reference
const marker = new maplibregl.Marker(el)
.setLngLat(coordinates)
.setPopup(popup)
.addTo(map);
// Store marker reference for later removal
currentMarkers.push(marker);
});
}

View file

@ -515,4 +515,12 @@ select:invalid {
.maplibregl-popup-content{
min-width: 300px;
max-width: 95vw;
}
.event-popup h3{
font-size: 1.5rem !important;
}
.add-event-btn{
float: left;
width: 130px;
}

View file

@ -96,4 +96,3 @@
font-size: 12px;
color: #555;
}