bethaus-app/templates/connections.html
2026-01-26 19:02:43 +00:00

163 lines
4.4 KiB
HTML

{# templates/connections.html #}
{% extends 'base.html' %}
{% block title %}Recent Connections{% endblock %}
{% block page_id %}connections{% endblock %}
{% block head_extra %}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" data-page-head />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" data-page-head></script>
<script src="https://cdn.socket.io/4.0.0/socket.io.min.js" data-page-head></script>
<style data-page-head>
/* page-specific styles */
.split-view {
display: flex;
gap: 20px;
height: 85vh;
}
.map-section {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
}
.table-section {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
#map {
width: 100%;
flex: 1;
height: auto;
min-height: 320px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.section-header {
background: white;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.page-content {
padding: 20px;
}
.stats {
display: flex;
gap: 20px;
flex-wrap: wrap;
margin-top: 10px;
}
.stat-item {
flex: 1;
min-width: 120px;
}
.stat-label {
font-size: 11px;
color: #666;
text-transform: uppercase;
}
.stat-value {
font-size: 20px;
font-weight: bold;
color: #333;
}
.table-container {
flex: 1;
overflow-y: auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#connectionsTableBody {
transition: transform 0.5s ease-out;
transform: translateY(0);
}
@keyframes slideIn {
0% { opacity: 0; transform: scale(0.8); }
100% { opacity: 1; transform: scale(1); }
}
.slide-in { animation: slideIn 0.5s ease-out; }
@keyframes slideOut {
0% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0.1); }
}
.slide-out { animation: slideOut 0.5s ease-in forwards; }
@media (max-width: 1200px) {
.split-view {
flex-direction: column;
height: auto;
}
.map-section, .table-section {
min-height: 400px;
}
}
</style>
{% endblock %}
{% block content %}
<div class="page-content">
<div class="section-header">
<h2 style="margin: 0;">
Verbindungen der letzten 10 Minuten (nur Audio)
<span class="text-muted" id="connectionsTotalHeader" style="font-size: 14px; margin-left: 8px;">0 Verbindungen</span>
</h2>
<p class="text-muted" style="margin: 4px 0 0 0;">Diese Ansicht listet ausschließlich Zugriffe auf Audio-Dateien.</p>
<div class="stats">
<div class="stat-item">
<div class="stat-label">Last Connection</div>
<div class="stat-value" id="last-connection" style="font-size: 14px;">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Total Connections</div>
<div class="stat-value" id="totalConnections">0</div>
</div>
<div class="stat-item">
<div class="stat-label">Total File Size</div>
<div class="stat-value" id="totalSize">0 B</div>
</div>
<div class="stat-item">
<div class="stat-label">Cached %</div>
<div class="stat-value" id="cachedPercent">0%</div>
</div>
</div>
</div>
<div class="split-view">
<!-- Map Section -->
<div class="map-section">
<div id="map"></div>
</div>
<!-- Table Section -->
<div class="table-section">
<div class="table-container">
<table class="table table-hover">
<thead class="table-secondary">
<tr>
<th>Timestamp</th>
<th>Location</th>
<th>User Agent</th>
<th>File Path</th>
<th>File Size</th>
<th>MIME-Typ</th>
<th>Cached</th>
</tr>
</thead>
<tbody id="connectionsTableBody">
{# dynamically populated via Socket.IO #}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}{% endblock %}