use crate::health::HealthState; use crate::health::HealthStatus; use chrono::Utc; use rocket::{get, State}; use rocket_contrib::templates::Template; use serde::Serialize; use std::sync::Arc; #[get("/")] pub async fn dashboard(state: State<'_, Arc>) -> Template { #[derive(Debug, Serialize)] struct Service { name: String, status_text: &'static str, status_color: &'static str, } #[derive(Debug, Serialize)] struct TemplateContext { last_update: String, services: Vec, } let last_update = *state.last_update.lock().await; let mut context = TemplateContext { last_update: last_update .map(|last_update| { let now = Utc::now(); if now.date() == last_update.date() { format!("UTC {}", last_update.format("%H:%M:%S")) } else { format!("UTC {}", last_update.format("%Y-%m-%d %H:%M:%S")) } }) .unwrap_or_else(|| "never".to_string()), services: vec![], }; for (id, status) in &state.health { let (status_color, status_text) = match *status.lock().await { Some(HealthStatus::Up) => ("green", "UP"), Some(HealthStatus::Down) => ("red", "DOWN"), Some(HealthStatus::Errored) => ("orange", "ERRORED"), None => ("#5b5b5b", "UNKNOWN"), } .into(); context.services.push(Service { name: id.clone(), status_color, status_text, }) } Template::render("dashboard", &context) }