124 lines
6.2 KiB
HTML
124 lines
6.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Data Sources — FR24</title>
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #0f1117; color: #e0e0e0; }
|
||
nav { background: #1a1d27; padding: 12px 24px; display: flex; gap: 24px; align-items: center; border-bottom: 1px solid #2a2d3a; }
|
||
nav a { color: #8b8fa8; text-decoration: none; font-size: 14px; }
|
||
nav a:hover, nav a.active { color: #fff; }
|
||
nav .brand { color: #fff; font-weight: 600; margin-right: 16px; }
|
||
.container { max-width: 1400px; margin: 0 auto; padding: 24px; }
|
||
h1 { font-size: 22px; font-weight: 600; margin-bottom: 4px; }
|
||
.subtitle { color: #8b8fa8; font-size: 14px; margin-bottom: 24px; }
|
||
.filters { display: flex; gap: 12px; margin-bottom: 24px; flex-wrap: wrap; align-items: center; }
|
||
.filters label { font-size: 13px; color: #8b8fa8; }
|
||
.filters input { background: #1a1d27; border: 1px solid #2a2d3a; color: #e0e0e0; padding: 6px 10px; border-radius: 6px; font-size: 13px; }
|
||
.filters button { background: #3b5bdb; color: #fff; border: none; padding: 7px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
||
.filters button:hover { background: #4c6ef5; }
|
||
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-bottom: 24px; }
|
||
.card { background: #1a1d27; border: 1px solid #2a2d3a; border-radius: 10px; padding: 20px; }
|
||
.card h3 { font-size: 13px; color: #8b8fa8; text-transform: uppercase; letter-spacing: .5px; margin-bottom: 12px; }
|
||
.stat-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; border-bottom: 1px solid #2a2d3a; font-size: 14px; }
|
||
.stat-row:last-child { border-bottom: none; }
|
||
.stat-val { font-weight: 600; }
|
||
.pct { font-size: 12px; color: #8b8fa8; margin-left: 6px; }
|
||
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
|
||
.badge-rtlsdr { background: #1c3a2a; color: #40c057; }
|
||
.badge-fr24 { background: #1c2a3a; color: #4dabf7; }
|
||
.badge-fa { background: #2a1c3a; color: #cc5de8; }
|
||
.badge-sched { background: #2a2a1c; color: #ffd43b; }
|
||
.section { background: #1a1d27; border: 1px solid #2a2d3a; border-radius: 10px; padding: 20px; margin-bottom: 16px; }
|
||
.section h3 { font-size: 13px; color: #8b8fa8; text-transform: uppercase; letter-spacing: .5px; margin-bottom: 16px; }
|
||
table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||
th { text-align: left; color: #8b8fa8; font-weight: 500; padding: 6px 10px; border-bottom: 1px solid #2a2d3a; }
|
||
td { padding: 8px 10px; border-bottom: 1px solid #1e2130; }
|
||
tr:last-child td { border-bottom: none; }
|
||
tr:hover td { background: #1e2130; }
|
||
.bar-wrap { background: #0f1117; border-radius: 4px; height: 8px; overflow: hidden; }
|
||
.bar { height: 100%; border-radius: 4px; transition: width .3s; }
|
||
.bar-rtlsdr { background: #40c057; }
|
||
.bar-fr24 { background: #4dabf7; }
|
||
.bar-fa { background: #cc5de8; }
|
||
.chart-wrap { overflow-x: auto; }
|
||
.stacked-chart { display: flex; flex-direction: column; gap: 6px; min-width: 600px; }
|
||
.chart-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
|
||
.chart-label { width: 80px; text-align: right; color: #8b8fa8; flex-shrink: 0; }
|
||
.chart-bars { flex: 1; display: flex; height: 20px; border-radius: 4px; overflow: hidden; }
|
||
.chart-bars span { display: block; height: 100%; transition: width .3s; }
|
||
.loading { color: #8b8fa8; font-size: 13px; padding: 20px 0; text-align: center; }
|
||
.error { color: #fa5252; font-size: 13px; padding: 8px; }
|
||
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||
@media (max-width: 768px) { .two-col { grid-template-columns: 1fr; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<nav>
|
||
<span class="brand">✈ FR24</span>
|
||
<a href="/">Карта</a>
|
||
<a href="/schedule">Расписание</a>
|
||
<a href="/monitoring">Мониторинг</a>
|
||
<a href="/data-sources" class="active">Источники</a>
|
||
</nav>
|
||
|
||
<div class="container">
|
||
<h1>Источники данных</h1>
|
||
<p class="subtitle">Покрытие треков, качество данных и статистика по аэропортам</p>
|
||
|
||
<div class="filters">
|
||
<label>С <input type="date" id="date_from"></label>
|
||
<label>По <input type="date" id="date_to"></label>
|
||
<button onclick="loadAll()">Обновить</button>
|
||
</div>
|
||
|
||
<!-- Coverage cards -->
|
||
<div class="grid" id="coverage-cards">
|
||
<div class="card"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
|
||
<!-- Stacked bar chart by day -->
|
||
<div class="section">
|
||
<h3>Покрытие по дням</h3>
|
||
<div class="chart-wrap">
|
||
<div class="stacked-chart" id="coverage-chart"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
<div style="display:flex;gap:16px;margin-top:12px;font-size:12px;">
|
||
<span><span class="badge badge-rtlsdr">RTL-SDR</span></span>
|
||
<span><span class="badge badge-fr24">FR24</span></span>
|
||
<span><span class="badge badge-fa">FlightAware</span></span>
|
||
<span><span class="badge badge-sched">Только расписание</span></span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quality + Airport load -->
|
||
<div class="two-col">
|
||
<div class="section">
|
||
<h3>Качество данных</h3>
|
||
<div id="quality-table"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
<div class="section">
|
||
<h3>Загрузка аэропортов по часам</h3>
|
||
<div id="airport-load"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Top airlines + routes -->
|
||
<div class="two-col">
|
||
<div class="section">
|
||
<h3>Топ авиакомпаний</h3>
|
||
<div id="top-airlines"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
<div class="section">
|
||
<h3>Топ маршрутов</h3>
|
||
<div id="top-routes"><div class="loading">Загрузка...</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/static/data_sources.js"></script>
|
||
</body>
|
||
</html>
|