use crate::base::component::{Html, Intro, IntroOpening};
use crate::core::component::{ChildOp, Component, ComponentError, Context, Contextual};
use crate::core::extension::Extension;
use crate::core::theme::{DefaultRegion, DefaultTemplate, TemplateRef};
use crate::global;
use crate::html::{html, Markup};
use crate::locale::L10n;
use crate::response::page::Page;
use crate::service::http::StatusCode;
pub trait Theme: Extension + Send + Sync {
fn parent(&self) -> Option<ThemeRef> {
None
}
#[inline]
fn default_template(&self) -> TemplateRef {
self.parent().map_or(&DefaultTemplate::Standard, |parent| {
parent.default_template()
})
}
#[allow(unused_variables)]
fn before_render_page_body(&self, page: &mut Page) {
if let Some(parent) = self.parent() {
parent.before_render_page_body(page);
}
}
#[inline]
fn render_page_body(&self, page: &mut Page) -> Markup {
if let Some(parent) = self.parent() {
parent.render_page_body(page)
} else {
page.template().render(page.context())
}
}
#[allow(unused_variables)]
fn after_render_page_body(&self, page: &mut Page) {
if let Some(parent) = self.parent() {
parent.after_render_page_body(page);
}
}
fn render_page_head(&self, page: &mut Page) -> Markup {
if let Some(parent) = self.parent() {
return parent.render_page_head(page);
}
let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no";
html! {
meta charset="utf-8";
@if let Some(title) = page.title() {
title { (global::SETTINGS.app.name) (" | ") (title) }
} @else {
title { (global::SETTINGS.app.name) }
}
@if let Some(description) = page.description() {
meta name="description" content=(description);
}
meta name="viewport" content=(viewport);
@for (name, content) in page.metadata() {
meta name=(name) content=(content) {}
}
meta http-equiv="X-UA-Compatible" content="IE=edge";
@for (property, content) in page.properties() {
meta property=(property) content=(content) {}
}
(page.context().render_assets())
}
}
#[allow(unused_variables)]
fn handle_component(
&self,
component: &mut dyn Component,
cx: &mut Context,
) -> Option<Result<Markup, ComponentError>> {
None
}
fn error_403(&self, page: &mut Page) {
if let Some(parent) = self.parent() {
return parent.error_403(page);
}
page.alter_title(L10n::l("error403_title"))
.alter_template(&DefaultTemplate::Error)
.alter_child_in(
&DefaultRegion::Content,
ChildOp::Prepend(
Html::with(move |cx| {
html! {
div {
h1 { (L10n::l("error403_alert").using(cx)) }
p { (L10n::l("error403_help").using(cx)) }
}
}
})
.into(),
),
);
}
fn error_404(&self, page: &mut Page) {
if let Some(parent) = self.parent() {
return parent.error_404(page);
}
page.alter_title(L10n::l("error404_title"))
.alter_template(&DefaultTemplate::Error)
.alter_child_in(
&DefaultRegion::Content,
ChildOp::Prepend(
Html::with(move |cx| {
html! {
div {
h1 { (L10n::l("error404_alert").using(cx)) }
p { (L10n::l("error404_help").using(cx)) }
}
}
})
.into(),
),
);
}
fn error_fatal(&self, page: &mut Page, code: StatusCode, title: L10n, alert: L10n, help: L10n) {
if let Some(parent) = self.parent() {
return parent.error_fatal(page, code, title, alert, help);
}
page.alter_title(title)
.alter_template(&DefaultTemplate::Error)
.alter_child_in(
&DefaultRegion::Content,
ChildOp::Prepend(
Intro::new()
.with_title(L10n::l("error_code").with_arg("code", code.to_string()))
.with_slogan(L10n::n(code.to_string()))
.with_button(None)
.with_opening(IntroOpening::Custom)
.with_child(Html::with(move |cx| {
html! {
h1 { (alert.using(cx)) }
p { (help.using(cx)) }
}
}))
.into(),
),
);
}
}
pub type ThemeRef = &'static dyn Theme;