Add MVP frontend scaffold with FastAPI + HTMX + TailwindCSS
- Created complete frontend structure with Jinja2 templates - Implemented three main pages: Dashboard, Fleet Roster, and Unit Detail - Added HTMX auto-refresh for real-time updates (10s interval) - Integrated dark/light mode toggle with localStorage persistence - Built responsive card-based UI with sidebar navigation - Created API endpoints for status snapshot, roster, unit details, and photos - Added mock data service for development (emit_status_snapshot) - Implemented tabbed interface on unit detail page (Photos, Map, History) - Integrated Leaflet maps for unit location visualization - Configured static file serving and photo management - Updated requirements.txt with Jinja2 and aiofiles - Reorganized backend structure into routers and services - Added comprehensive FRONTEND_README.md documentation Frontend features: - Auto-refreshing dashboard with fleet summary and alerts - Sortable fleet roster table (prioritizes Missing > Pending > OK) - Unit detail view with status, deployment info, and notes - Photo gallery with thumbnail navigation - Interactive maps showing unit coordinates - Consistent styling with brand colors (orange, navy, burgundy) Ready for integration with real Series3 emitter data.
This commit is contained in:
96
backend/services/snapshot.py
Normal file
96
backend/services/snapshot.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Mock implementation of emit_status_snapshot().
|
||||
This will be replaced with real Series3 emitter logic by the user.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
|
||||
|
||||
def emit_status_snapshot():
|
||||
"""
|
||||
Mock function that returns fleet status snapshot.
|
||||
In production, this will call the real Series3 emitter logic.
|
||||
|
||||
Returns a dictionary with unit statuses, ages, deployment status, etc.
|
||||
"""
|
||||
|
||||
# Mock data for demonstration
|
||||
mock_units = {
|
||||
"BE1234": {
|
||||
"status": "OK",
|
||||
"age": "1h 12m",
|
||||
"last": "2025-11-22 12:32:10",
|
||||
"fname": "evt_1234.mlg",
|
||||
"deployed": True,
|
||||
"note": "Bridge monitoring project - Golden Gate"
|
||||
},
|
||||
"BE5678": {
|
||||
"status": "Pending",
|
||||
"age": "2h 45m",
|
||||
"last": "2025-11-22 11:05:33",
|
||||
"fname": "evt_5678.mlg",
|
||||
"deployed": True,
|
||||
"note": "Dam structural analysis"
|
||||
},
|
||||
"BE9012": {
|
||||
"status": "Missing",
|
||||
"age": "5d 3h",
|
||||
"last": "2025-11-17 09:15:00",
|
||||
"fname": "evt_9012.mlg",
|
||||
"deployed": True,
|
||||
"note": "Tunnel excavation site"
|
||||
},
|
||||
"BE3456": {
|
||||
"status": "OK",
|
||||
"age": "30m",
|
||||
"last": "2025-11-22 13:20:45",
|
||||
"fname": "evt_3456.mlg",
|
||||
"deployed": False,
|
||||
"note": "Benched for maintenance"
|
||||
},
|
||||
"BE7890": {
|
||||
"status": "OK",
|
||||
"age": "15m",
|
||||
"last": "2025-11-22 13:35:22",
|
||||
"fname": "evt_7890.mlg",
|
||||
"deployed": True,
|
||||
"note": "Pipeline monitoring"
|
||||
},
|
||||
"BE2468": {
|
||||
"status": "Pending",
|
||||
"age": "4h 20m",
|
||||
"last": "2025-11-22 09:30:15",
|
||||
"fname": "evt_2468.mlg",
|
||||
"deployed": True,
|
||||
"note": "Building foundation survey"
|
||||
},
|
||||
"BE1357": {
|
||||
"status": "OK",
|
||||
"age": "45m",
|
||||
"last": "2025-11-22 13:05:00",
|
||||
"fname": "evt_1357.mlg",
|
||||
"deployed": False,
|
||||
"note": "Awaiting deployment"
|
||||
},
|
||||
"BE8642": {
|
||||
"status": "Missing",
|
||||
"age": "2d 12h",
|
||||
"last": "2025-11-20 01:30:00",
|
||||
"fname": "evt_8642.mlg",
|
||||
"deployed": True,
|
||||
"note": "Offshore platform - comms issue suspected"
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"units": mock_units,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"total_units": len(mock_units),
|
||||
"deployed_units": sum(1 for u in mock_units.values() if u["deployed"]),
|
||||
"status_summary": {
|
||||
"OK": sum(1 for u in mock_units.values() if u["status"] == "OK"),
|
||||
"Pending": sum(1 for u in mock_units.values() if u["status"] == "Pending"),
|
||||
"Missing": sum(1 for u in mock_units.values() if u["status"] == "Missing")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user