feat: station search in side panel; DB stats cover HII tables
CI/CD Pipeline - Northern Thailand Ping River Monitor / Test Suite (3.11) (push) Failing after 38s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Build Docker Image (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Integration Test with Services (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Staging (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Production (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Performance Test (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Code Quality (push) Successful in 16s
Documentation / Validate Documentation (push) Failing after 9s
Documentation / Generate API Documentation (push) Successful in 10s
Documentation / Build Sphinx Documentation (push) Successful in 16s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Cleanup (push) Successful in 0s
Documentation / Documentation Summary (push) Successful in 2s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Test Suite (3.11) (push) Failing after 38s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Build Docker Image (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Integration Test with Services (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Staging (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Deploy to Production (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Performance Test (push) Skipped
CI/CD Pipeline - Northern Thailand Ping River Monitor / Code Quality (push) Successful in 16s
Documentation / Validate Documentation (push) Failing after 9s
Documentation / Generate API Documentation (push) Successful in 10s
Documentation / Build Sphinx Documentation (push) Successful in 16s
CI/CD Pipeline - Northern Thailand Ping River Monitor / Cleanup (push) Successful in 0s
Documentation / Documentation Summary (push) Successful in 2s
A search box above the station lists filters both the RID flow list and the basin-station list by code, name (Thai included), or river, and persists across refreshes. /api/stats now reports whole-DB totals — RID + hii_rainfall + hii_waterlevel counts, combined station count, and a date range spanning all sources — with per-source breakdown fields the stats strip shows as tile notes. Sensor section renamed to 'Additional basin stations · ThaiWater/HII'.
This commit is contained in:
+52
-2
@@ -762,11 +762,61 @@ async def get_database_stats():
|
||||
if stats is None:
|
||||
raise HTTPException(status_code=503, detail="Database statistics unavailable")
|
||||
|
||||
def hii_totals():
|
||||
engine = _hii_engine()
|
||||
if engine is None:
|
||||
return None
|
||||
from sqlalchemy import text
|
||||
|
||||
with engine.connect() as conn:
|
||||
return conn.execute(
|
||||
text(
|
||||
"""
|
||||
SELECT (SELECT COUNT(*) FROM hii_rainfall) AS rain_n,
|
||||
(SELECT COUNT(*) FROM hii_waterlevel) AS wl_n,
|
||||
(SELECT COUNT(*) FROM hii_rain_stations) AS rain_s,
|
||||
(SELECT COUNT(*) FROM hii_wl_stations) AS wl_s,
|
||||
(SELECT MIN(timestamp) FROM hii_rainfall) AS rain_lo,
|
||||
(SELECT MAX(timestamp) FROM hii_rainfall) AS rain_hi,
|
||||
(SELECT MIN(timestamp) FROM hii_waterlevel) AS wl_lo,
|
||||
(SELECT MAX(timestamp) FROM hii_waterlevel) AS wl_hi
|
||||
"""
|
||||
)
|
||||
).one()
|
||||
|
||||
hii = None
|
||||
try:
|
||||
hii = await asyncio.to_thread(hii_totals)
|
||||
except Exception as e:
|
||||
logger.warning(f"HII stats unavailable: {e}")
|
||||
|
||||
def as_dt(value):
|
||||
if isinstance(value, str):
|
||||
return datetime.fromisoformat(value)
|
||||
return value
|
||||
|
||||
first_ts = stats["first_timestamp"]
|
||||
last_ts = stats["last_timestamp"]
|
||||
rain_n = wl_n = hii_stations = 0
|
||||
if hii is not None:
|
||||
rain_n, wl_n = hii.rain_n or 0, hii.wl_n or 0
|
||||
hii_stations = (hii.rain_s or 0) + (hii.wl_s or 0)
|
||||
for lo in (as_dt(hii.rain_lo), as_dt(hii.wl_lo)):
|
||||
if lo is not None and lo < first_ts:
|
||||
first_ts = lo
|
||||
for hi in (as_dt(hii.rain_hi), as_dt(hii.wl_hi)):
|
||||
if hi is not None and hi > last_ts:
|
||||
last_ts = hi
|
||||
|
||||
data = {
|
||||
"total_measurements": stats["total_measurements"],
|
||||
"station_count": stats["station_count"],
|
||||
# Whole-DB totals (RID + HII feeds); breakdown fields alongside
|
||||
"total_measurements": stats["total_measurements"] + rain_n + wl_n,
|
||||
"rid_measurements": stats["total_measurements"],
|
||||
"hii_rainfall_measurements": rain_n,
|
||||
"hii_waterlevel_measurements": wl_n,
|
||||
"station_count": stats["station_count"] + hii_stations,
|
||||
"rid_station_count": stats["station_count"],
|
||||
"hii_station_count": hii_stations,
|
||||
"first_timestamp": first_ts.isoformat(),
|
||||
"last_timestamp": last_ts.isoformat(),
|
||||
"days_spanned": (last_ts.date() - first_ts.date()).days + 1,
|
||||
|
||||
Reference in New Issue
Block a user