60 lines
1.8 KiB
Rust
60 lines
1.8 KiB
Rust
mod comments;
|
|
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::Plant;
|
|
|
|
const HX_REQUEST_HEADER: &str = "HX-Request";
|
|
const HX_HISTORY_RESTORE_HEADER: &str = "HX-History-Restore-Request";
|
|
|
|
pub fn render_partial(headers: &HeaderMap) -> bool {
|
|
let is_htmx_req = headers.get(HX_REQUEST_HEADER).is_some();
|
|
let is_hist_restore_req = headers
|
|
.get(HX_HISTORY_RESTORE_HEADER)
|
|
.map(|val| val == HeaderValue::from_static("true"))
|
|
.unwrap_or(false);
|
|
|
|
is_htmx_req && !is_hist_restore_req
|
|
}
|
|
|
|
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()))
|
|
.nest("/comments", comments::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 || Plant::all(&ctx.pool))
|
|
.await
|
|
.unwrap()
|
|
.unwrap();
|
|
|
|
let mut context = Context::new();
|
|
context.insert("plants", &plants);
|
|
Html(ctx.tera.render("index.html", &context).unwrap())
|
|
}
|