Refactor page structure: Update page classes for consistency

- Changed class from "ots-displays-page" to "ots-static-page ots-displays-page" in multiple Twig view files to standardize page layout.
- Enhanced schedule-page.twig with improved calendar navigation and dropdown management.
- Added global dropdown dismissal functionality to improve user experience across modals and dropdowns.
This commit is contained in:
Matt Batchelder
2026-02-11 20:47:09 -05:00
parent 29b56bef4f
commit b766487411
34 changed files with 4506 additions and 141 deletions

View File

@@ -65,7 +65,7 @@
{% endblock %}
{% block pageContent %}
<div class="ots-displays-page">
<div class="ots-static-page ots-displays-page">
<div class="page-header ots-page-header">
<h1>{% trans "Displays" %}</h1>
<p class="text-muted">{% trans "Manage your player fleet and status." %}</p>
@@ -337,7 +337,7 @@
</table>
<!-- Map -->
<div class="row">
<div class="row" id="map-view-container" style="display:none;">
<div class="col-sm-12">
<div class="map-legend" style="display:none; position: absolute; z-index: 500; right: 20px; top: 10px;">
<div class="display-map-legend" style="font-size: 12px;">
@@ -404,4 +404,96 @@
{# Add page source code bundle ( JS ) #}
<script src="{{ theme.rootUri() }}dist/leaflet.bundle.min.js?v={{ version }}&rev={{revision}}" nonce="{{ cspNonce }}"></script>
<script src="{{ theme.rootUri() }}dist/pages/display-page.bundle.min.js?v={{ version }}&rev={{revision}}" nonce="{{ cspNonce }}"></script>
{# Initialize map/list view toggle AFTER all other scripts load #}
<script type="text/javascript" nonce="{{ cspNonce }}">
function initMapListToggle() {
var mapBtn = document.getElementById('map_button');
var listBtn = document.getElementById('list_button');
var mapViewContainer = document.getElementById('map-view-container');
// DataTables wraps the <table> in a div with id "displays_wrapper"
var tableWrapper = document.getElementById('displays_wrapper');
// Fallback: if DataTables hasn't wrapped it yet, target the table itself
if (!tableWrapper) {
tableWrapper = document.getElementById('displays');
}
if (!mapBtn || !listBtn || !mapViewContainer || !tableWrapper) {
console.warn('Map/list toggle: required elements not found:', {
mapBtn: !!mapBtn,
listBtn: !!listBtn,
mapViewContainer: !!mapViewContainer,
tableWrapper: !!tableWrapper
});
return;
}
console.log('Map/list toggle initialized');
// Show list view by default
tableWrapper.style.display = '';
mapViewContainer.style.display = 'none';
listBtn.classList.add('active');
mapBtn.classList.remove('active');
// Map button click handler
mapBtn.addEventListener('click', function(e) {
e.preventDefault();
console.log('Map button clicked');
mapViewContainer.style.display = 'block';
tableWrapper.style.display = 'none';
mapBtn.classList.add('active');
listBtn.classList.remove('active');
// Leaflet can't size itself in a hidden container.
// After making the map visible, tell every Leaflet map
// instance inside it to recalculate its dimensions.
setTimeout(function() {
var mapEl = document.getElementById('display-map');
if (mapEl) {
// Leaflet stores its instance on the DOM element as _leaflet_map
var leafletKeys = Object.keys(mapEl).filter(function(k) {
return k.indexOf('_leaflet_map') === 0 || k === '_leaflet';
});
// Try the standard _leaflet_map key
if (mapEl._leaflet_map) {
mapEl._leaflet_map.invalidateSize();
console.log('Leaflet invalidateSize called via _leaflet_map');
}
// Also try iterating over Leaflet-stamped keys
for (var i = 0; i < leafletKeys.length; i++) {
var inst = mapEl[leafletKeys[i]];
if (inst && typeof inst.invalidateSize === 'function') {
inst.invalidateSize();
console.log('Leaflet invalidateSize called via', leafletKeys[i]);
}
}
// Fallback: dispatch a resize event so Leaflet picks it up
window.dispatchEvent(new Event('resize'));
}
}, 200);
});
// List button click handler
listBtn.addEventListener('click', function(e) {
e.preventDefault();
console.log('List button clicked');
tableWrapper.style.display = '';
mapViewContainer.style.display = 'none';
listBtn.classList.add('active');
mapBtn.classList.remove('active');
});
}
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
// Give the page bundle time to initialize DataTables
setTimeout(initMapListToggle, 500);
});
} else {
// Give the page bundle time to initialize DataTables
setTimeout(initMapListToggle, 500);
}
</script>
{% endblock %}