- 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.
7.9 KiB
Seismo Fleet Manager - Frontend Documentation
Overview
This is the MVP frontend scaffold for Seismo Fleet Manager, built with:
- FastAPI (backend framework)
- HTMX (dynamic updates without JavaScript frameworks)
- TailwindCSS (utility-first styling)
- Jinja2 (server-side templating)
- Leaflet (interactive maps)
No React, Vue, or other frontend frameworks are used.
Project Structure
seismo-fleet-manager/
├── backend/
│ ├── main.py # FastAPI app entry point
│ ├── routers/
│ │ ├── roster.py # Fleet roster endpoints
│ │ ├── units.py # Individual unit endpoints
│ │ └── photos.py # Photo management endpoints
│ ├── services/
│ │ └── snapshot.py # Mock status snapshot (replace with real logic)
│ ├── static/
│ │ └── style.css # Custom CSS
│ ├── database.py # SQLAlchemy database setup
│ ├── models.py # Database models
│ └── routes.py # Legacy API routes
├── templates/
│ ├── base.html # Base layout with sidebar & dark mode
│ ├── dashboard.html # Main dashboard page
│ ├── roster.html # Fleet roster page
│ ├── unit_detail.html # Unit detail page
│ └── partials/
│ └── roster_table.html # HTMX partial for roster table
├── data/
│ └── photos/ # Photo storage (organized by unit_id)
└── requirements.txt
Running the Application
Install Dependencies
pip install -r requirements.txt
Run the Server
uvicorn backend.main:app --host 0.0.0.0 --port 8001 --reload
The application will be available at:
- Web UI: http://localhost:8001/
- API Docs: http://localhost:8001/docs
- Health Check: http://localhost:8001/health
Features
1. Dashboard (/)
The main dashboard provides an at-a-glance view of the fleet:
- Fleet Summary Card: Total units, deployed units, status breakdown
- Recent Alerts Card: Shows units with Missing or Pending status
- Recent Photos Card: Placeholder for photo gallery
- Fleet Status Preview: Quick view of first 5 units
Auto-refresh: Dashboard updates every 10 seconds via HTMX
2. Fleet Roster (/roster)
A comprehensive table view of all seismograph units:
Columns:
- Status indicator (colored dot: green=OK, yellow=Pending, red=Missing)
- Deployment indicator (blue dot if deployed)
- Unit ID
- Last seen timestamp
- Age since last contact
- Notes
- Actions (View detail button)
Features:
- Auto-refresh every 10 seconds
- Sorted by priority (Missing > Pending > OK)
- Click any row to view unit details
3. Unit Detail Page (/unit/{unit_id})
Split-screen layout with detailed information:
Left Column:
- Status card with real-time updates
- Deployment status
- Last contact time and file
- Notes section
- Editable metadata (mock form)
Right Column - Tabbed Interface:
- Photos Tab: Primary photo with thumbnail gallery
- Map Tab: Interactive Leaflet map showing unit location
- History Tab: Placeholder for event history
Auto-refresh: Unit data updates every 10 seconds
4. Dark/Light Mode
Toggle button in sidebar switches between themes:
- Uses Tailwind's
dark:classes - Preference saved to localStorage
- Smooth transitions on theme change
API Endpoints
Status & Fleet Data
GET /api/status-snapshot
Returns complete fleet status snapshot with statistics.
GET /api/roster
Returns sorted list of all units for roster table.
GET /api/unit/{unit_id}
Returns detailed information for a single unit including coordinates.
Photo Management
GET /api/unit/{unit_id}/photos
Returns list of photos for a unit, sorted by recency.
GET /api/unit/{unit_id}/photo/{filename}
Serves a specific photo file.
Legacy Endpoints
POST /emitters/report
Endpoint for emitters to report status (from original backend).
GET /fleet/status
Returns database-backed fleet status (from original backend).
Mock Data
Location: backend/services/snapshot.py
The emit_status_snapshot() function currently returns mock data with 8 units:
- BE1234: OK, deployed (San Francisco)
- BE5678: Pending, deployed (Los Angeles)
- BE9012: Missing, deployed (New York)
- BE3456: OK, benched (Chicago)
- BE7890: OK, deployed (Houston)
- BE2468: Pending, deployed
- BE1357: OK, benched
- BE8642: Missing, deployed
To replace with real data: Update the emit_status_snapshot() function to call your Series3 emitter logic.
Styling
Color Palette
The application uses your brand colors:
orange: #f48b1c
navy: #142a66
burgundy: #7d234d
These are configured in the Tailwind config as seismo-orange, seismo-navy, seismo-burgundy.
Cards
All cards use the consistent styling:
<div class="rounded-xl shadow-lg bg-white dark:bg-slate-800 p-6">
Status Indicators
- Green dot: OK status
- Yellow dot: Pending status
- Red dot: Missing status
- Blue dot: Deployed
- Gray dot: Benched
HTMX Usage
HTMX enables dynamic updates without writing JavaScript:
Auto-refresh Example (Dashboard)
<div hx-get="/api/status-snapshot"
hx-trigger="load, every 10s"
hx-swap="none"
hx-on::after-request="updateDashboard(event)">
This fetches the snapshot on page load and every 10 seconds, then calls a JavaScript function to update the DOM.
Partial Template Loading (Roster)
<div hx-get="/partials/roster-table"
hx-trigger="load, every 10s"
hx-swap="innerHTML">
This replaces the entire inner HTML with the server-rendered roster table every 10 seconds.
Adding Photos
To add photos for a unit:
- Create a directory:
data/photos/{unit_id}/ - Add image files (jpg, jpeg, png, gif, webp)
- Photos will automatically appear on the unit detail page
- Most recent file becomes the primary photo
Example:
mkdir -p data/photos/BE1234
cp my-photo.jpg data/photos/BE1234/deployment-site.jpg
Customization
Adding New Pages
- Create a template in
templates/ - Add a route in
backend/main.py:
@app.get("/my-page", response_class=HTMLResponse)
async def my_page(request: Request):
return templates.TemplateResponse("my_page.html", {"request": request})
- Add a navigation link in
templates/base.html
Adding New API Endpoints
- Create a router file in
backend/routers/ - Include the router in
backend/main.py:
from backend.routers import my_router
app.include_router(my_router.router)
Docker Deployment
The project includes Docker configuration:
docker-compose up
This will start the application on port 8001 (configured to avoid conflicts with port 8000).
Next Steps
- Replace Mock Data: Update
backend/services/snapshot.pywith real Series3 emitter logic - Database Integration: The existing SQLAlchemy models can store historical data
- Photo Upload: Add a form to upload photos from the UI
- Projects Management: Implement the "Projects" page
- Settings: Add user preferences and configuration
- Event History: Populate the History tab with real event data
- Authentication: Add user login/authentication if needed
- Notifications: Add real-time alerts for critical status changes
Development Tips
- The
--reloadflag auto-reloads the server when code changes - Use browser DevTools to debug HTMX requests (look for
HX-Requestheaders) - Check
/docsfor interactive API documentation (Swagger UI) - Dark mode state persists in browser localStorage
- All timestamps are currently mock data - replace with real values
License
See main README.md for license information.