Fix pace sentinel, route map thumbnails, tiled segments, health/dashboard layout
- Pace: FIT 0xFFFF sentinel (65.535 m/s) was stored as avg_speed_ms on every activity and lap; add _sanitize_speed() to parser falling back to dist/dur, plus a startup SQL migration that fixed 120 activities and 688 laps in-place - Records: remove swimming from Distance PRs; Route Records rows are clickable (navigate to activity), View button removed, small SVG route map per row; Segment Records uses same tiled route-card layout as Segments page - Segments: replace route dropdown with responsive tile grid showing SVG map thumbnails; selecting a tile reveals the segment management panel below - RouteMiniMap: new pure-SVG component (no Leaflet) for route thumbnails, decodes polyline and normalises coords into a fixed viewBox - Health: rename "Avg Heart Rate (day)" → "Heart Rate"; weight chart now filters to non-null rows and enables connectNulls + dots for sparse data - Dashboard: 4-col layout at lg breakpoint so Body Battery sits between weekly chart and Health Today; Body Battery card gains a 24-hr sparkline from the values[] already present in the health summary response Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -106,6 +106,20 @@ async def init_db():
|
||||
except Exception as e:
|
||||
print(f"FK migration skipped: {e}")
|
||||
|
||||
# Fix avg_speed_ms stored as the FIT invalid sentinel (0xFFFF/1000 = 65.535 m/s)
|
||||
try:
|
||||
async with engine.begin() as conn:
|
||||
await conn.execute(text(
|
||||
"UPDATE activities SET avg_speed_ms = distance_m / duration_s "
|
||||
"WHERE avg_speed_ms > 30 AND distance_m > 0 AND duration_s > 0"
|
||||
))
|
||||
await conn.execute(text(
|
||||
"UPDATE activity_laps SET avg_speed_ms = distance_m / duration_s "
|
||||
"WHERE avg_speed_ms > 30 AND distance_m > 0 AND duration_s > 0"
|
||||
))
|
||||
except Exception as e:
|
||||
print(f"avg_speed_ms fix skipped: {e}")
|
||||
|
||||
# Seed admin user (only if password is configured)
|
||||
if not settings.admin_password:
|
||||
print("ADMIN_PASSWORD not set - skipping admin user seed")
|
||||
|
||||
Reference in New Issue
Block a user