feat(gps-tracks): ET-008 публичные GPS-треки с публичных платформ
Backend:
- Миграция gps_tracks_001_init.sql: таблицы tracks + pipeline_runs
- Пакет src/api/gps_tracks/: models, db (WAL+upsert с dedup), dedup
(bbox+length+date bucket-hash), mvt (LRU-кэш 1024 тайла), endpoint
(GET /api/gps-tracks, GET /api/gps-tracks/tiles/{z}/{x}/{y}.mvt,
GET /api/gps-tracks/health, POST /api/gps-tracks/cache/clear), config
- Парсеры: osm (split_bbox, haversine, defusedxml XXE-защита),
enduro_russia + ttrails — заглушки (ADR-010/011 proposed, блокированы)
- Licensing guard: pipeline проверяет status ADR-файла до запуска источника
- scripts/gps_collect.py: CLI с --region/--source/--dry-run/--gc
Frontend:
- src/web/gps_tracks.js: двухрежимный слой (MVT z≤11, GeoJSON z≥12),
debounced fetch + AbortController, фильтры активности/источника,
цветовая палитра by-source/by-activity, halo на спутнике, popup трека,
restorePublicTracksState(), localStorage persistence
- index.html: чекбокс «Публичные треки» в terrain-popup, #sheet-gps-filters
- app.css: .terrain-link-btn, .gps-filter-grid, .track-popup
- app.js: вызов restorePublicTracksState() в rebuildMapOverlays(),
applyGpsHaloVisibility() в applyBaseLayer()
Конфиги:
- config/gps_sources.yaml: osm (enabled), enduro_russia/ttrails (disabled)
- config/gps_regions.yaml: ЦФО+Чувашия (enabled), Кавказ (disabled)
Docker:
- gps-collector service с profiles: [batch]
Тесты: 48 новых тестов (unit + integration), 125/125 pass
Refs: ET-008
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1227,3 +1227,76 @@ body.satellite-active #btn-basemap {
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* ─── ET-008: GPS-треки ──────────────────────────── */
|
||||
.terrain-link-btn {
|
||||
display: block;
|
||||
margin: 4px 0 0 24px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--accent, #ff8c1a);
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
padding: 2px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.gps-filter-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 6px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.gps-filter-chip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.gps-filter-chip input[type=checkbox] {
|
||||
accent-color: var(--accent, #ff8c1a);
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.gps-stats-row {
|
||||
font-size: 12px;
|
||||
color: var(--text2);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Track popup */
|
||||
.track-popup {
|
||||
font-size: 13px;
|
||||
color: var(--text, #fff);
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.track-popup-name {
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.track-popup-row {
|
||||
margin: 3px 0;
|
||||
color: var(--text2, #ccc);
|
||||
}
|
||||
|
||||
.track-popup-sources {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.track-popup-sources a {
|
||||
color: var(--accent, #ff8c1a);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.track-popup-sources a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user