51 lines
1.4 KiB
Rust
51 lines
1.4 KiB
Rust
mod plants;
|
|
|
|
use axum::{
|
|
extract::State,
|
|
http::{header::VARY, HeaderMap, HeaderValue},
|
|
response::Html,
|
|
routing::get,
|
|
Router,
|
|
};
|
|
use tera::Context;
|
|
use tower_http::set_header::SetResponseHeaderLayer;
|
|
|
|
use crate::db;
|
|
|
|
const HX_REQUEST_HEADER: &str = "HX-Request";
|
|
|
|
pub fn is_htmx_req(headers: &HeaderMap) -> bool {
|
|
headers.get(HX_REQUEST_HEADER).is_some()
|
|
}
|
|
|
|
pub fn app(ctx: crate::Context) -> axum::Router {
|
|
let mut router = Router::new()
|
|
.route("/", get(get_index))
|
|
.with_state(ctx.clone())
|
|
.nest("/plants", plants::app(ctx.clone()));
|
|
|
|
for (name, content) in crate::STATIC_FILES {
|
|
router = router.route(&format!("/static/{}", name), get(content))
|
|
}
|
|
|
|
// Routes return either partial or full pages depending on whether the request is done using
|
|
// HTMX or just as a plain HTTP request. Adding the Vary header ensures caches don't mix
|
|
// partial and full responses.
|
|
// https://htmx.org/docs/#caching
|
|
router.layer(SetResponseHeaderLayer::appending(
|
|
VARY,
|
|
HeaderValue::from_static(HX_REQUEST_HEADER),
|
|
))
|
|
}
|
|
|
|
async fn get_index(State(ctx): State<crate::Context>) -> Html<String> {
|
|
let plants = tokio::task::spawn_blocking(move || db::list_plants(&ctx.pool))
|
|
.await
|
|
.unwrap()
|
|
.unwrap();
|
|
|
|
let mut context = Context::new();
|
|
context.insert("plants", &plants);
|
|
Html(ctx.tera.render("index.html", &context).unwrap())
|
|
}
|