This commit is contained in:
JMARyA 2025-01-21 16:39:47 +01:00
parent e02def6bc1
commit f3880d77d2
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
8 changed files with 265 additions and 85 deletions

View file

@ -1,5 +1,10 @@
use maud::{PreEscaped, html};
use crate::{
request::{RequestContext, StringResponse},
ui::UIWidget,
};
// TODO : refactor shell
/// Represents the HTML structure of a page shell, including the head, body class, and body content.
@ -9,9 +14,10 @@ pub struct Shell {
/// The HTML content for the `<head>` section of the page.
head: PreEscaped<String>,
/// An optional class attribute for the `<body>` element.
body_class: Option<String>,
body_class: String,
/// The HTML content for the static body portion.
body_content: PreEscaped<String>,
ui: bool,
}
impl Shell {
@ -25,18 +31,24 @@ impl Shell {
/// # Returns
/// A `Shell` instance encapsulating the provided HTML content and attributes.
#[must_use]
pub const fn new(
head: PreEscaped<String>,
body_content: PreEscaped<String>,
body_class: Option<String>,
pub fn new<T: UIWidget + 'static, C: UIWidget + 'static, B: UIWidget + 'static>(
head: T,
body_content: B,
body_class: C,
) -> Self {
Self {
head,
body_class,
body_content,
head: head.render(),
body_class: body_class.extended_class().join(" "),
body_content: body_content.render(),
ui: false,
}
}
pub fn use_ui(mut self) -> Self {
self.ui = true;
self
}
/// Renders the full HTML page using the shell structure, with additional content and a title.
///
/// # Arguments
@ -51,10 +63,15 @@ impl Shell {
html {
head {
title { (title) };
@if self.ui {
script src="https://cdn.tailwindcss.com" {};
script src="/assets/htmx.min.js" {};
meta name="viewport" content="width=device-width, initial-scale=1.0";
};
(self.head)
};
@if self.body_class.is_some() {
body class=(self.body_class.as_ref().unwrap()) {
@if !self.body_class.is_empty() {
body class=(self.body_class) {
(self.body_content);
div id="main_content" {
@ -73,4 +90,38 @@ impl Shell {
}
}
}
/// Renders a full page or an HTMX-compatible fragment based on the request context.
///
/// If the request is not an HTMX request, this function uses the provided shell to generate
/// a full HTML page. If it is an HTMX request, only the provided content is rendered.
///
/// # Arguments
/// * `content` - The HTML content to render.
/// * `title` - The title of the page for full-page rendering.
/// * `ctx` - The `RequestContext` containing request metadata.
///
/// # Returns
/// A `StringResponse`
pub async fn render_page(
&self,
content: PreEscaped<String>,
title: &str,
ctx: RequestContext,
) -> StringResponse {
if ctx.is_htmx {
(
rocket::http::Status::Ok,
(rocket::http::ContentType::HTML, content.into_string()),
)
} else {
(
rocket::http::Status::Ok,
(
rocket::http::ContentType::HTML,
self.render(content, title).into_string(),
),
)
}
}
}