97 lines
2.4 KiB
Rust
97 lines
2.4 KiB
Rust
use axum::http::{HeaderMap, HeaderValue};
|
|
use tera::Context;
|
|
|
|
use super::Template;
|
|
|
|
const HX_REQUEST_HEADER: &str = "HX-Request";
|
|
const HX_HISTORY_RESTORE_HEADER: &str = "HX-History-Restore-Request";
|
|
|
|
pub enum View {
|
|
Plant,
|
|
Images,
|
|
Index,
|
|
Login,
|
|
Other(Box<dyn Template>),
|
|
}
|
|
|
|
impl View {
|
|
pub fn other(tmpl: impl Template + 'static) -> Self {
|
|
View::Other(Box::new(tmpl))
|
|
}
|
|
|
|
pub fn headers(self, headers: &HeaderMap) -> ViewWrapper {
|
|
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);
|
|
|
|
let include_base = !is_htmx_req || is_hist_restore_req;
|
|
|
|
ViewWrapper {
|
|
view: self,
|
|
include_base,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Template for View {
|
|
fn template(&self) -> &'static str {
|
|
match self {
|
|
View::Plant => "views/plant.html",
|
|
View::Index => "views/index.html",
|
|
View::Images => "views/images.html",
|
|
View::Login => "views/login.html",
|
|
View::Other(tmpl) => tmpl.template(),
|
|
}
|
|
}
|
|
|
|
fn render(&self, tera: &tera::Tera) -> tera::Result<String> {
|
|
match self {
|
|
View::Other(tmpl) => tmpl.render(tera),
|
|
_ => tera.render(self.template(), &Context::new()),
|
|
}
|
|
}
|
|
|
|
fn render_ctx(&self, tera: &tera::Tera, ctx: &tera::Context) -> tera::Result<String> {
|
|
match self {
|
|
View::Other(tmpl) => tmpl.render_ctx(tera, ctx),
|
|
_ => tera.render(self.template(), ctx),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct ViewWrapper {
|
|
view: View,
|
|
include_base: bool,
|
|
}
|
|
|
|
impl ViewWrapper {
|
|
fn wrap(&self, tera: &tera::Tera, view: String) -> tera::Result<String> {
|
|
if self.include_base {
|
|
let mut ctx = tera::Context::new();
|
|
ctx.insert("view", &view);
|
|
|
|
tera.render("base.html", &ctx)
|
|
} else {
|
|
Ok(view)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Template for ViewWrapper {
|
|
fn template(&self) -> &'static str {
|
|
self.view.template()
|
|
}
|
|
|
|
fn render(&self, tera: &tera::Tera) -> tera::Result<String> {
|
|
let view = self.view.render(tera)?;
|
|
self.wrap(tera, view)
|
|
}
|
|
|
|
fn render_ctx(&self, tera: &tera::Tera, ctx: &tera::Context) -> tera::Result<String> {
|
|
let view = self.view.render_ctx(tera, ctx)?;
|
|
self.wrap(tera, view)
|
|
}
|
|
}
|