diff options
author | metamuffin <metamuffin@disroot.org> | 2024-05-03 19:34:45 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-05-03 19:34:45 +0200 |
commit | d60bedc20dc0cc54cb697f3a45e5b222de6f1479 (patch) | |
tree | be310b8ca7075cef3676d4b05ac99f9267692b95 /src/web.rs | |
download | statuspage-d60bedc20dc0cc54cb697f3a45e5b222de6f1479.tar statuspage-d60bedc20dc0cc54cb697f3a45e5b222de6f1479.tar.bz2 statuspage-d60bedc20dc0cc54cb697f3a45e5b222de6f1479.tar.zst |
works
Diffstat (limited to 'src/web.rs')
-rw-r--r-- | src/web.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/web.rs b/src/web.rs new file mode 100644 index 0000000..0080697 --- /dev/null +++ b/src/web.rs @@ -0,0 +1,86 @@ +use crate::{Check, Config, Service, Success, STATUS}; +use anyhow::Result; +use axum::response::Html; +use markup::{doctype, Render}; +use std::{collections::BTreeMap, ops::Deref, sync::Arc, time::Duration}; + +pub async fn send_html_page(config: Arc<Config>) -> Html<String> { + let mut out = String::new(); + let status = STATUS.read().await; + let status = status.deref(); + + #[cfg(not(debug_assertions))] + let css = include_str!("style.css"); + #[cfg(debug_assertions)] + let css = tokio::fs::read_to_string("src/style.css").await.unwrap(); + + markup::new! { + @doctype() + html { + head { + meta[charset="UTF-8"]; + meta[name="viewport", content="width=device-width, initial-scale=1.0"]; + title { "Status Page" } + style { @css } + } + body { + main { + h1 { @config.title } + @for (i, service) in config.services.iter().enumerate() { + @ServiceCard { i, status, service } + } + } + } + } + } + .render(&mut out) + .unwrap(); + Html(out) +} + +markup::define!( + ServiceCard<'a>(status: &'a BTreeMap<(usize, usize), Result<Success>>, service: &'a Service, i: usize) { + @let any_err = status.range((*i,usize::MIN)..(*i,usize::MAX)).any(|(_,v)|v.is_err()); + div.service.{if any_err { "error" } else { "ok" }} { + h2 { @service.title } + div.checks { + @for (j, check) in service.checks.iter().enumerate() { + @if let Some(status) = status.get(&(*i, j)) { + span.name { @check.display() } + @match status { + Ok(Success { latency, updated }) => { + span.status.ok { "Ok" } + span.details.ok { + "Checked " @format_duration(updated.elapsed().unwrap_or_default()) " ago" + @if let Some(latency) = latency { ", took " @format_duration(*latency) } "." + } + } + Err(e) => { + span.status.error { "Error" } + span.details { @format!("{e}") } + } + } + } + } + } + } + } +); + +impl Check { + pub fn display(&self) -> String { + match self { + Check::Systemd(_) => "Service".to_string(), + Check::Http { title, .. } => title.clone().unwrap_or("HTTP".to_string()), + Check::Shell { title, .. } => title.to_owned(), + } + } +} + +fn format_duration(d: Duration) -> String { + if d.as_millis() < 1500 { + format!("{}ms", d.as_millis()) + } else { + format!("{}s", d.as_secs()) + } +} |