#[macro_use]
extern crate rocket;
use maud::{html, Markup, PreEscaped, DOCTYPE};
use rocket::response::stream::{Event, EventStream};
use rocket::tokio::time::{interval, Duration};
struct SsePayload {
}
#[get("/sse")]
async fn sse() -> EventStream![] {
EventStream! {
let mut interval = interval(Duration::from_secs(2));
loop {
interval.tick().await;
yield Event::data(format!("Updated time: {:?}", chrono::Utc::now()));
}
}
}
#[get("/")]
fn index() -> Markup {
html! {
(DOCTYPE)
html lang="en" {
head {
meta charset="utf-8";
title { "Live Updates with SSE" }
style {
"body {
color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background: rgb(34,187,195);
background: linear-gradient(0deg, rgba(34,187,195,1) 0%, rgba(102,45,253,1) 100%);
font-family: sans-serif;
}
.glassy {
background: rgba(255, 255, 255, 0.2);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(2.8px);
-webkit-backdrop-filter: blur(2.8px);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.data-grid {
margin: 2em;
padding: 2em;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 18px;
}
.data-cell {
margin: 0.5em 1em;
padding: 1em;
border-radius: 18px;
display: flex;
flex-direction: column;
width: 100%;
}
"
}
script {
(PreEscaped("const eventSource = new EventSource('/sse');
eventSource.onmessage = (event) => {
document.getElementById('updates').innerText = event.data;
};"))
}
}
body style="" {
h1 style="align-items: center;" { "willdaten dashboard" }
div class="glassy data-grid" {
div class="glassy data-cell" {
h3 { "Fetcher" }
div id="updates" { "Waiting for updates..." }
}
div class="glassy data-cell" {
h3 { "Database" }
div id="updates" { "Waiting for updates..." }
}
div class="glassy data-cell" {
h3 { "Statistics" }
div id="updates" { "Waiting for updates..." }
}
}
}
}
}
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index, sse])
}