Move dashboard HTML out of web_api into a static file
Extract the inline root() dashboard markup into src/static/dashboard.html, loaded once at import. Keeps HTML out of the Python module (web_api 616 -> 576 lines) with a defensive fallback if the file is missing. Full <500 compliance for web_api still needs the endpoints split into APIRouter modules; tracked as remaining #4 work.
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Northern Thailand Ping River Monitor</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; margin: 40px; }
|
||||||
|
.header { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
|
||||||
|
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
|
||||||
|
.status-healthy { color: #27ae60; }
|
||||||
|
.status-degraded { color: #f39c12; }
|
||||||
|
.status-unhealthy { color: #e74c3c; }
|
||||||
|
.endpoint { background: #f8f9fa; padding: 10px; margin: 5px 0; border-radius: 3px; }
|
||||||
|
.endpoint code { color: #2c3e50; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="header">
|
||||||
|
<h1>🏔️ Northern Thailand Ping River Monitor API</h1>
|
||||||
|
<p>Real-time water level monitoring system for the Ping River Basin in Northern Thailand</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>📊 Quick Status</h2>
|
||||||
|
<p>API is running and monitoring 16 water stations along the Ping River</p>
|
||||||
|
<p>Coverage: From Chiang Dao to Nakhon Sawan</p>
|
||||||
|
<p>Data collection interval: Every hour</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>🔗 API Endpoints</h2>
|
||||||
|
<div class="endpoint"><code>GET /health</code> - System health status</div>
|
||||||
|
<div class="endpoint"><code>GET /metrics</code> - Application metrics</div>
|
||||||
|
<div class="endpoint"><code>GET /stations</code> - List all monitoring stations</div>
|
||||||
|
<div class="endpoint"><code>POST /stations</code> - Add new monitoring station</div>
|
||||||
|
<div class="endpoint"><code>PUT /stations/{station_id}</code> - Update station information</div>
|
||||||
|
<div class="endpoint"><code>GET /measurements/latest</code> - Latest measurements</div>
|
||||||
|
<div class="endpoint"><code>GET /measurements/station/{station_code}</code> - Station-specific data</div>
|
||||||
|
<div class="endpoint"><code>POST /scrape/trigger</code> - Trigger manual data collection</div>
|
||||||
|
<div class="endpoint"><code>GET /scraping/status</code> - Scraping status</div>
|
||||||
|
<div class="endpoint"><code>GET /docs</code> - Interactive API documentation</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2>📈 Monitoring</h2>
|
||||||
|
<p>• Grafana dashboards available for data visualization</p>
|
||||||
|
<p>• Health checks monitor database, API, and system resources</p>
|
||||||
|
<p>• Metrics collection for performance monitoring</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+11
-53
@@ -4,6 +4,7 @@ FastAPI web interface for water monitoring system
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
@@ -29,6 +30,15 @@ from .water_scraper_v3 import EnhancedWaterMonitorScraper
|
|||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
# Dashboard HTML is loaded once at import from src/static/dashboard.html.
|
||||||
|
_DASHBOARD_HTML_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static", "dashboard.html")
|
||||||
|
try:
|
||||||
|
with open(_DASHBOARD_HTML_PATH, encoding="utf-8") as _dashboard_file:
|
||||||
|
DASHBOARD_HTML = _dashboard_file.read()
|
||||||
|
except OSError as _dashboard_error: # pragma: no cover - defensive fallback
|
||||||
|
logger.error(f"Could not load dashboard HTML: {_dashboard_error}")
|
||||||
|
DASHBOARD_HTML = "<h1>Northern Thailand Ping River Monitor API</h1><p>See <code>/docs</code>.</p>"
|
||||||
|
|
||||||
|
|
||||||
# Global application state
|
# Global application state
|
||||||
app_state = {
|
app_state = {
|
||||||
@@ -176,59 +186,7 @@ async def background_scraping_task():
|
|||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
async def root():
|
async def root():
|
||||||
"""Root endpoint with basic dashboard"""
|
"""Root endpoint with basic dashboard"""
|
||||||
html_content = """
|
return HTMLResponse(content=DASHBOARD_HTML)
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Northern Thailand Ping River Monitor</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: Arial, sans-serif; margin: 40px; }
|
|
||||||
.header { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
|
|
||||||
.section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
|
|
||||||
.status-healthy { color: #27ae60; }
|
|
||||||
.status-degraded { color: #f39c12; }
|
|
||||||
.status-unhealthy { color: #e74c3c; }
|
|
||||||
.endpoint { background: #f8f9fa; padding: 10px; margin: 5px 0; border-radius: 3px; }
|
|
||||||
.endpoint code { color: #2c3e50; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="header">
|
|
||||||
<h1>🏔️ Northern Thailand Ping River Monitor API</h1>
|
|
||||||
<p>Real-time water level monitoring system for the Ping River Basin in Northern Thailand</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h2>📊 Quick Status</h2>
|
|
||||||
<p>API is running and monitoring 16 water stations along the Ping River</p>
|
|
||||||
<p>Coverage: From Chiang Dao to Nakhon Sawan</p>
|
|
||||||
<p>Data collection interval: Every hour</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h2>🔗 API Endpoints</h2>
|
|
||||||
<div class="endpoint"><code>GET /health</code> - System health status</div>
|
|
||||||
<div class="endpoint"><code>GET /metrics</code> - Application metrics</div>
|
|
||||||
<div class="endpoint"><code>GET /stations</code> - List all monitoring stations</div>
|
|
||||||
<div class="endpoint"><code>POST /stations</code> - Add new monitoring station</div>
|
|
||||||
<div class="endpoint"><code>PUT /stations/{station_id}</code> - Update station information</div>
|
|
||||||
<div class="endpoint"><code>GET /measurements/latest</code> - Latest measurements</div>
|
|
||||||
<div class="endpoint"><code>GET /measurements/station/{station_code}</code> - Station-specific data</div>
|
|
||||||
<div class="endpoint"><code>POST /scrape/trigger</code> - Trigger manual data collection</div>
|
|
||||||
<div class="endpoint"><code>GET /scraping/status</code> - Scraping status</div>
|
|
||||||
<div class="endpoint"><code>GET /docs</code> - Interactive API documentation</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h2>📈 Monitoring</h2>
|
|
||||||
<p>• Grafana dashboards available for data visualization</p>
|
|
||||||
<p>• Health checks monitor database, API, and system resources</p>
|
|
||||||
<p>• Metrics collection for performance monitoring</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
return HTMLResponse(content=html_content)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health", response_model=HealthResponse)
|
@app.get("/health", response_model=HealthResponse)
|
||||||
|
|||||||
Reference in New Issue
Block a user