🏷️ PageContext pasa a ser RenderResources

Ahora los componentes no tendrán acceso al contexto de la página
(PageContext) porque podrían usarse en otros tipos de respuesta que no
sean sólo páginas. En su lugar se usará RenderResources que formarán
también parte de la página.
This commit is contained in:
Manuel Cillero 2022-12-18 14:09:53 +01:00
parent a687c646f2
commit b0446c7206
30 changed files with 263 additions and 252 deletions

View file

@ -41,7 +41,7 @@ pub async fn summary() -> ResultPage<Markup, FatalError> {
.with_item(MenuItem::label("Opción 4")); .with_item(MenuItem::label("Opción 4"));
Page::new() Page::new()
.with_context(PageOp::SetTheme("Bootsier")) .with_resource(ResourceOp::SetTheme("Bootsier"))
.with_title("Admin") .with_title("Admin")
.add_to("top-menu", top_menu) .add_to("top-menu", top_menu)
.add_to( .add_to(

View file

@ -51,12 +51,12 @@ impl ComponentTrait for Anchor {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
#[rustfmt::skip] #[rustfmt::skip]
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let target = match &self.target() { let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"), AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Parent => Some("_parent"), AnchorTarget::Parent => Some("_parent"),
@ -71,9 +71,9 @@ impl ComponentTrait for Anchor {
href=[self.href().get()] href=[self.href().get()]
target=[target] target=[target]
{ {
(self.left_icon().render(context)) (self.left_icon().render(rsx))
span { (*self.html()) } span { (*self.html()) }
(self.right_icon().render(context)) (self.right_icon().render(rsx))
} }
} }
} }

View file

@ -29,23 +29,23 @@ impl ComponentTrait for Block {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let id = context.required_id::<Block>(self.id()); let id = rsx.required_id::<Block>(self.id());
html! { html! {
div id=(id) class=[self.classes().get()] { div id=(id) class=[self.classes().get()] {
@if let Some(title) = self.title().get() { @if let Some(title) = self.title().get() {
h2 class="block-title" { (title) } h2 class="block-title" { (title) }
} }
div class="block-body" { div class="block-body" {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
} }

View file

@ -42,47 +42,47 @@ impl ComponentTrait for Container {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
match self.container_type() { match self.container_type() {
ContainerType::Header => html! { ContainerType::Header => html! {
header id=[self.id().get()] class=[self.classes().get()] { header id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] { div class=[self.inner_classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
}, },
ContainerType::Footer => html! { ContainerType::Footer => html! {
footer id=[self.id().get()] class=[self.classes().get()] { footer id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] { div class=[self.inner_classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
}, },
ContainerType::Main => html! { ContainerType::Main => html! {
main id=[self.id().get()] class=[self.classes().get()] { main id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] { div class=[self.inner_classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
}, },
ContainerType::Section => html! { ContainerType::Section => html! {
section id=[self.id().get()] class=[self.classes().get()] { section id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] { div class=[self.inner_classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
}, },
_ => html! { _ => html! {
div id=[self.id().get()] class=[self.classes().get()] { div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
}, },
} }

View file

@ -39,11 +39,11 @@ impl ComponentTrait for Button {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
let button_type = match self.button_type() { let button_type = match self.button_type() {
ButtonType::Button => "button", ButtonType::Button => "button",
ButtonType::Submit => "submit", ButtonType::Submit => "submit",

View file

@ -36,11 +36,11 @@ impl ComponentTrait for Date {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.name().get().map(|name| concat_string!("edit-", name)); let id = self.name().get().map(|name| concat_string!("edit-", name));
html! { html! {
div class=[self.classes().get()] { div class=[self.classes().get()] {

View file

@ -40,15 +40,15 @@ impl ComponentTrait for Form {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
let method = match self.method() { let method = match self.method() {
FormMethod::Post => Some("post".to_owned()), FormMethod::Post => Some("post".to_owned()),
FormMethod::Get => None, FormMethod::Get => None,
@ -61,7 +61,7 @@ impl ComponentTrait for Form {
method=[method] method=[method]
accept-charset=[self.charset().get()] accept-charset=[self.charset().get()]
{ {
div { (self.elements().render(context)) } div { (self.elements().render(rsx)) }
} }
} }
} }

View file

@ -23,7 +23,7 @@ impl ComponentTrait for Hidden {
self.weight self.weight
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.name().get().map(|name| concat_string!("value-", name)); let id = self.name().get().map(|name| concat_string!("value-", name));
html! { html! {
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()]; input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()];

View file

@ -53,12 +53,12 @@ impl ComponentTrait for Input {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
#[rustfmt::skip] #[rustfmt::skip]
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
let type_input = match self.input_type() { let type_input = match self.input_type() {
InputType::Textfield => "text", InputType::Textfield => "text",
InputType::Password => "password", InputType::Password => "password",

View file

@ -61,18 +61,18 @@ impl ComponentTrait for Column {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! { html! {
div id=[self.id().get()] class=[self.classes().get()] { div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
} }

View file

@ -28,18 +28,18 @@ impl ComponentTrait for Row {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! { html! {
div id=[self.id().get()] class=[self.classes().get()] { div id=[self.id().get()] class=[self.classes().get()] {
(self.columns().render(context)) (self.columns().render(rsx))
} }
} }
} }

View file

@ -51,11 +51,11 @@ impl ComponentTrait for Heading {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
let id = self.id().get(); let id = self.id().get();
let classes = self.classes().get(); let classes = self.classes().get();
html! { @match &self.heading_type() { html! { @match &self.heading_type() {

View file

@ -24,11 +24,11 @@ impl ComponentTrait for Html {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
html! { (*self.html()) } html! { (*self.html()) }
} }

View file

@ -24,17 +24,17 @@ impl ComponentTrait for Icon {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
context.alter(PageOp::AddStyleSheet( rsx.alter(ResourceOp::AddStyleSheet(
StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"), StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"),
)); ));
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
html! { i class=[self.classes().get()] {}; } html! { i class=[self.classes().get()] {}; }
} }

View file

@ -26,11 +26,11 @@ impl ComponentTrait for Image {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, _: &mut PageContext) -> Markup { fn default_render(&self, _: &mut RenderResources) -> Markup {
html! { html! {
img img
src=[self.source().get()] src=[self.source().get()]

View file

@ -37,11 +37,11 @@ impl ComponentTrait for MenuItem {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
match self.item_type() { match self.item_type() {
MenuItemType::Void => html! {}, MenuItemType::Void => html! {},
@ -63,7 +63,7 @@ impl ComponentTrait for MenuItem {
li class="submenu" { li class="submenu" {
a href="#" { (label) } a href="#" { (label) }
ul { ul {
(menu.items().render(context)) (menu.items().render(rsx))
} }
} }
}, },
@ -186,32 +186,31 @@ impl ComponentTrait for Menu {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn before_render(&mut self, context: &mut PageContext) { fn before_render(&mut self, rsx: &mut RenderResources) {
before_render_inline(self, context); before_render_inline(self, rsx);
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
context rsx.alter(ResourceOp::AddStyleSheet(
.alter(PageOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"), StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"),
)) ))
.alter(PageOp::AddStyleSheet( .alter(ResourceOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"), StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"),
)) ))
.alter(PageOp::AddJavaScript( .alter(ResourceOp::AddJavaScript(
JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"), JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"),
)) ))
.alter(PageOp::AddJQuery); .alter(ResourceOp::AddJQuery);
let id = context.required_id::<Menu>(self.id()); let id = rsx.required_id::<Menu>(self.id());
html! { html! {
ul id=(id) class=[self.classes().get()] { ul id=(id) class=[self.classes().get()] {
(self.items().render(context)) (self.items().render(rsx))
} }
script type="text/javascript" defer { script type="text/javascript" defer {
"jQuery(function(){jQuery('#" (id) "').smartmenus({" "jQuery(function(){jQuery('#" (id) "').smartmenus({"

View file

@ -38,17 +38,17 @@ impl ComponentTrait for Paragraph {
self.weight self.weight
} }
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
(self.renderable.check)(context) (self.renderable.check)(rsx)
} }
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! { html! {
p p
id=[self.id().get()] id=[self.id().get()]
class=[self.classes().get()] class=[self.classes().get()]
{ {
(self.components().render(context)) (self.components().render(rsx))
} }
} }
} }

View file

@ -27,7 +27,7 @@ impl ModuleTrait for DefaultHomePage {
async fn demo() -> ResultPage<Markup, FatalError> { async fn demo() -> ResultPage<Markup, FatalError> {
Page::new() Page::new()
.with_title(l("page_title").as_str()) .with_title(l("page_title").as_str())
.with_context(PageOp::AddStyleSheet(StyleSheet::located( .with_resource(ResourceOp::AddStyleSheet(StyleSheet::located(
"/theme/module/homepage/styles.css", "/theme/module/homepage/styles.css",
))) )))
.with_body_classes(ClassesOp::AddFirst, "default-homepage") .with_body_classes(ClassesOp::AddFirst, "default-homepage")

View file

@ -16,10 +16,8 @@ impl ThemeTrait for Aliner {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon( page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
Favicon::new().with_icon("/theme/favicon.ico"), .alter_resource(ResourceOp::AddStyleSheet(
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/aliner/css/styles.css").with_weight(-99), StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
)); ));
} }

View file

@ -18,20 +18,18 @@ impl ThemeTrait for Bootsier {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon( page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
Favicon::new().with_icon("/theme/favicon.ico"), .alter_resource(ResourceOp::AddStyleSheet(
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/bootsier/css/bootstrap.min.css") StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3") .with_version("5.1.3")
.with_weight(-99), .with_weight(-99),
)) ))
.alter_context(PageOp::AddJavaScript( .alter_resource(ResourceOp::AddJavaScript(
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js") JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3") .with_version("5.1.3")
.with_weight(-99), .with_weight(-99),
)) ))
.alter_context(PageOp::AddJQuery); .alter_resource(ResourceOp::AddJQuery);
} }
fn error_404_not_found(&self) -> Container { fn error_404_not_found(&self) -> Container {

View file

@ -16,22 +16,20 @@ impl ThemeTrait for Bulmix {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon( page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
Favicon::new().with_icon("/theme/favicon.ico"), .alter_resource(ResourceOp::AddStyleSheet(
))
.alter_context(PageOp::AddStyleSheet(
StyleSheet::located("/bulmix/css/bulma.min.css") StyleSheet::located("/bulmix/css/bulma.min.css")
.with_version("0.9.4") .with_version("0.9.4")
.with_weight(-99), .with_weight(-99),
)) ))
.alter_context(PageOp::AddJQuery); .alter_resource(ResourceOp::AddJQuery);
} }
#[rustfmt::skip] #[rustfmt::skip]
fn before_render_component( fn before_render_component(
&self, &self,
component: &mut dyn ComponentTrait, component: &mut dyn ComponentTrait,
_context: &mut PageContext, _rsx: &mut RenderResources,
) { ) {
match component.handle() { match component.handle() {
COMPONENT_ANCHOR => { COMPONENT_ANCHOR => {
@ -110,7 +108,7 @@ impl ThemeTrait for Bulmix {
fn render_component( fn render_component(
&self, &self,
component: &dyn ComponentTrait, component: &dyn ComponentTrait,
_context: &mut PageContext, _rsx: &mut RenderResources,
) -> Option<Markup> { ) -> Option<Markup> {
match component.handle() { match component.handle() {
COMPONENT_ICON => { COMPONENT_ICON => {

View file

@ -1,3 +1,6 @@
mod resources;
pub use resources::{RenderResources, ResourceOp};
mod definition; mod definition;
pub use definition::{component_mut, component_ref, AnyComponent, BaseComponent, ComponentTrait}; pub use definition::{component_mut, component_ref, AnyComponent, BaseComponent, ComponentTrait};

View file

@ -1,6 +1,6 @@
use super::ComponentTrait; use super::{ComponentTrait, RenderResources};
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::response::page::PageContext;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -26,12 +26,12 @@ impl ComponentsBundle {
self.0.clear(); self.0.clear();
} }
pub fn render(&self, context: &mut PageContext) -> Markup { pub fn render(&self, rsx: &mut RenderResources) -> Markup {
let mut components = self.0.clone(); let mut components = self.0.clone();
components.sort_by_key(|c| c.read().unwrap().weight()); components.sort_by_key(|c| c.read().unwrap().weight());
html! { html! {
@for c in components.iter() { @for c in components.iter() {
(" ")(c.write().unwrap().render(context))(" ") (" ")(c.write().unwrap().render(rsx))(" ")
} }
} }
} }

View file

@ -1,11 +1,12 @@
use super::RenderResources;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::response::page::PageContext;
use crate::util::{single_type_name, Handle}; use crate::util::{single_type_name, Handle};
pub use std::any::Any as AnyComponent; pub use std::any::Any as AnyComponent;
pub trait BaseComponent { pub trait BaseComponent {
fn render(&mut self, context: &mut PageContext) -> Markup; fn render(&mut self, rsx: &mut RenderResources) -> Markup;
} }
pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
@ -28,15 +29,15 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn is_renderable(&self, context: &PageContext) -> bool { fn is_renderable(&self, rsx: &RenderResources) -> bool {
true true
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render(&mut self, context: &mut PageContext) {} fn before_render(&mut self, rsx: &mut RenderResources) {}
#[allow(unused_variables)] #[allow(unused_variables)]
fn default_render(&self, context: &mut PageContext) -> Markup { fn default_render(&self, rsx: &mut RenderResources) -> Markup {
html! {} html! {}
} }
@ -46,17 +47,17 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
} }
impl<C: ComponentTrait> BaseComponent for C { impl<C: ComponentTrait> BaseComponent for C {
fn render(&mut self, context: &mut PageContext) -> Markup { fn render(&mut self, rsx: &mut RenderResources) -> Markup {
// Acciones del componente antes de renderizar. // Acciones del componente antes de renderizar.
self.before_render(context); self.before_render(rsx);
// Acciones del tema antes de renderizar el componente. // Acciones del tema antes de renderizar el componente.
context.theme().before_render_component(self, context); rsx.theme().before_render_component(self, rsx);
match self.is_renderable(context) { match self.is_renderable(rsx) {
true => match context.theme().render_component(self, context) { true => match rsx.theme().render_component(self, rsx) {
Some(html) => html, Some(html) => html,
None => self.default_render(context), None => self.default_render(rsx),
}, },
false => html! {}, false => html! {},
} }
@ -77,7 +78,7 @@ macro_rules! hook_before_render_component {
paste::paste! { paste::paste! {
$crate::pub_handle!($ACTION_HANDLE); $crate::pub_handle!($ACTION_HANDLE);
type Action = fn(&$Component, &mut PageContext); type Action = fn(&$Component, &mut RenderResources);
pub struct [< BeforeRender $Component >] { pub struct [< BeforeRender $Component >] {
action: Option<Action>, action: Option<Action>,
@ -118,18 +119,18 @@ macro_rules! hook_before_render_component {
self self
} }
pub fn run(&self, component: &mut $Component, context: &mut PageContext) { pub fn run(&self, component: &mut $Component, rsx: &mut RenderResources) {
if let Some(action) = self.action { if let Some(action) = self.action {
action(component, context) action(component, rsx)
} }
} }
} }
#[inline(always)] #[inline(always)]
fn before_render_inline(component: &mut $Component, context: &mut PageContext) { fn before_render_inline(component: &mut $Component, rsx: &mut RenderResources) {
run_actions($ACTION_HANDLE, |action| run_actions($ACTION_HANDLE, |action|
action_ref::<[< BeforeRender $Component >]>(&**action) action_ref::<[< BeforeRender $Component >]>(&**action)
.run(component, context) .run(component, rsx)
); );
} }
} }

View file

@ -1,6 +1,6 @@
use crate::response::page::PageContext; use crate::core::component::RenderResources;
pub type IsRenderable = fn(&PageContext) -> bool; pub type IsRenderable = fn(&RenderResources) -> bool;
pub struct Renderable { pub struct Renderable {
pub check: IsRenderable, pub check: IsRenderable,
@ -14,6 +14,6 @@ impl Default for Renderable {
} }
} }
fn render_always(_: &PageContext) -> bool { fn render_always(_: &RenderResources) -> bool {
true true
} }

View file

@ -1,7 +1,5 @@
use super::PageOp;
use crate::core::theme::{all::theme_by_single_name, ThemeStaticRef}; use crate::core::theme::{all::theme_by_single_name, ThemeStaticRef};
use crate::html::{html, Assets, Favicon, IdentifierValue, JavaScript, Markup, ModeJS, StyleSheet}; use crate::html::{html, Assets, IdentifierValue, JavaScript, Markup, ModeJS, StyleSheet};
use crate::{base, concat_string, config, util, LazyStatic}; use crate::{base, concat_string, config, util, LazyStatic};
static DEFAULT_THEME: LazyStatic<ThemeStaticRef> = static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
@ -10,26 +8,29 @@ static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
None => &base::theme::bootsier::Bootsier, None => &base::theme::bootsier::Bootsier,
}); });
pub enum ResourceOp {
SetTheme(&'static str),
AddStyleSheet(StyleSheet),
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery,
}
#[rustfmt::skip] #[rustfmt::skip]
pub struct PageContext { pub struct RenderResources {
theme : ThemeStaticRef, theme : ThemeStaticRef,
favicon : Option<Favicon>,
metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
stylesheets: Assets<StyleSheet>, stylesheets: Assets<StyleSheet>,
javascripts: Assets<JavaScript>, javascripts: Assets<JavaScript>,
with_jquery: bool, with_jquery: bool,
id_counter : usize, id_counter : usize,
} }
impl Default for PageContext { impl Default for RenderResources {
#[rustfmt::skip] #[rustfmt::skip]
fn default() -> Self { fn default() -> Self {
PageContext { RenderResources {
theme : *DEFAULT_THEME, theme : *DEFAULT_THEME,
favicon : None,
metadata : Vec::new(),
properties : Vec::new(),
stylesheets: Assets::<StyleSheet>::new(), stylesheets: Assets::<StyleSheet>::new(),
javascripts: Assets::<JavaScript>::new(), javascripts: Assets::<JavaScript>::new(),
with_jquery: false, with_jquery: false,
@ -38,45 +39,29 @@ impl Default for PageContext {
} }
} }
impl PageContext { impl RenderResources {
pub fn new() -> Self { pub fn new() -> Self {
PageContext::default() RenderResources::default()
} }
pub fn alter(&mut self, op: PageOp) -> &mut Self { pub fn alter(&mut self, op: ResourceOp) -> &mut Self {
match op { match op {
PageOp::SetTheme(theme_name) => { ResourceOp::SetTheme(theme_name) => {
self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
} }
ResourceOp::AddStyleSheet(css) => {
PageOp::AddFavicon(favicon) => {
self.favicon = Some(favicon);
}
PageOp::RemoveFavicon => {
self.favicon = None;
}
PageOp::AddMetadata(name, content) => {
self.metadata.push((name, content));
}
PageOp::AddProperty(property, content) => {
self.properties.push((property, content));
}
PageOp::AddStyleSheet(css) => {
self.stylesheets.add(css); self.stylesheets.add(css);
} }
PageOp::RemoveStyleSheet(source) => { ResourceOp::RemoveStyleSheet(source) => {
self.stylesheets.remove(source); self.stylesheets.remove(source);
} }
ResourceOp::AddJavaScript(js) => {
PageOp::AddJavaScript(js) => {
self.javascripts.add(js); self.javascripts.add(js);
} }
PageOp::RemoveJavaScript(source) => { ResourceOp::RemoveJavaScript(source) => {
self.javascripts.remove(source); self.javascripts.remove(source);
} }
PageOp::AddJQuery => { ResourceOp::AddJQuery => {
if !self.with_jquery { if !self.with_jquery {
self.javascripts.add( self.javascripts.add(
JavaScript::located("/theme/js/jquery.min.js") JavaScript::located("/theme/js/jquery.min.js")
@ -91,32 +76,22 @@ impl PageContext {
self self
} }
/// PageContext GETTERS. /// Resources GETTERS.
pub(crate) fn theme(&mut self) -> ThemeStaticRef { pub(crate) fn theme(&mut self) -> ThemeStaticRef {
self.theme self.theme
} }
/// PageContext RENDER. /// Resources RENDER.
pub fn render(&mut self) -> Markup { pub fn render(&mut self) -> Markup {
html! { html! {
@match &self.favicon {
Some(favicon) => (favicon.render()),
None => "",
}
@for (name, content) in &self.metadata {
meta name=(name) content=(content) {}
}
@for (property, content) in &self.properties {
meta property=(property) content=(content) {}
}
(self.stylesheets.render()) (self.stylesheets.render())
(self.javascripts.render()) (self.javascripts.render())
} }
} }
// PageContext EXTRAS. // Resources EXTRAS.
pub fn required_id<T>(&mut self, id: &IdentifierValue) -> String { pub fn required_id<T>(&mut self, id: &IdentifierValue) -> String {
match id.get() { match id.get() {

View file

@ -1,7 +1,7 @@
use crate::base::component::{Container, Html}; use crate::base::component::{Container, Html};
use crate::core::component::ComponentTrait; use crate::core::component::{ComponentTrait, RenderResources};
use crate::html::{html, Favicon, Markup}; use crate::html::{html, Favicon, Markup};
use crate::response::page::{Page, PageContext, PageOp}; use crate::response::page::Page;
use crate::util::{single_type_name, Handle}; use crate::util::{single_type_name, Handle};
use crate::{concat_string, config, server}; use crate::{concat_string, config, server};
@ -28,9 +28,9 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(PageOp::AddFavicon( if page.favicon().is_none() {
Favicon::new().with_icon("/theme/favicon.ico"), page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")));
)); }
} }
fn render_page_head(&self, page: &mut Page) -> Markup { fn render_page_head(&self, page: &mut Page) -> Markup {
@ -49,10 +49,22 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
@if let Some(d) = page.description().get() { @if let Some(d) = page.description().get() {
meta name="description" content=(d); meta name="description" content=(d);
} }
meta http-equiv="X-UA-Compatible" content="IE=edge";
meta name="viewport" content=(viewport);
(page.context().render()) 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) {}
}
@if let Some(f) = page.favicon() {
(f.render())
}
(page.resources().render())
} }
} }
} }
@ -84,7 +96,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn before_render_component( fn before_render_component(
&self, &self,
component: &mut dyn ComponentTrait, component: &mut dyn ComponentTrait,
context: &mut PageContext, rsx: &mut RenderResources,
) { ) {
/* /*
Cómo usarlo: Cómo usarlo:
@ -99,11 +111,12 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
*/ */
} }
#[rustfmt::skip]
#[allow(unused_variables)] #[allow(unused_variables)]
fn render_component( fn render_component(
&self, &self,
component: &dyn ComponentTrait, component: &dyn ComponentTrait,
context: &mut PageContext, rsx: &mut RenderResources,
) -> Option<Markup> { ) -> Option<Markup> {
None None
/* /*

View file

@ -25,7 +25,7 @@ impl fmt::Display for FatalError {
// Error 403. // Error 403.
FatalError::AccessDenied => { FatalError::AccessDenied => {
let mut error_page = Page::new(); let mut error_page = Page::new();
let error_content = error_page.context().theme().error_403_access_denied(); let error_content = error_page.resources().theme().error_403_access_denied();
if let Ok(page) = error_page if let Ok(page) = error_page
.with_title("Error FORBIDDEN") .with_title("Error FORBIDDEN")
.using_template("error") .using_template("error")
@ -40,7 +40,7 @@ impl fmt::Display for FatalError {
// Error 404. // Error 404.
FatalError::NotFound => { FatalError::NotFound => {
let mut error_page = Page::new(); let mut error_page = Page::new();
let error_content = error_page.context().theme().error_404_not_found(); let error_content = error_page.resources().theme().error_404_not_found();
if let Ok(page) = error_page if let Ok(page) = error_page
.with_title("Error RESOURCE NOT FOUND") .with_title("Error RESOURCE NOT FOUND")
.using_template("error") .using_template("error")

View file

@ -1,27 +1,5 @@
use crate::html::{Favicon, JavaScript, StyleSheet};
pub use actix_web::Result as ResultPage; pub use actix_web::Result as ResultPage;
pub enum PageOp {
SetTheme(&'static str),
AddFavicon(Favicon),
RemoveFavicon,
AddMetadata(&'static str, &'static str),
AddProperty(&'static str, &'static str),
AddStyleSheet(StyleSheet),
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery,
}
mod context;
pub use context::PageContext;
mod hook; mod hook;
pub use hook::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE}; pub use hook::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};

View file

@ -1,8 +1,8 @@
use super::{BeforeRenderPageHook, PageContext, PageOp, ResultPage, HOOK_BEFORE_RENDER_PAGE}; use super::{BeforeRenderPageHook, ResultPage, HOOK_BEFORE_RENDER_PAGE};
use crate::core::component::*; use crate::core::component::*;
use crate::core::hook::{action_ref, run_actions}; use crate::core::hook::{action_ref, run_actions};
use crate::html::{html, AttributeValue, Classes, ClassesOp, Markup, DOCTYPE}; use crate::html::{html, AttributeValue, Classes, ClassesOp, Favicon, Markup, DOCTYPE};
use crate::response::FatalError; use crate::response::FatalError;
use crate::{config, trace, LazyStatic}; use crate::{config, trace, LazyStatic};
@ -43,11 +43,14 @@ pub enum TextDirection {
#[rustfmt::skip] #[rustfmt::skip]
pub struct Page { pub struct Page {
context : PageContext,
language : AttributeValue, language : AttributeValue,
direction : AttributeValue, direction : AttributeValue,
title : AttributeValue, title : AttributeValue,
description : AttributeValue, description : AttributeValue,
metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
favicon : Option<Favicon>,
resources : RenderResources,
body_classes: Classes, body_classes: Classes,
regions : HashMap<&'static str, ComponentsBundle>, regions : HashMap<&'static str, ComponentsBundle>,
template : String, template : String,
@ -57,7 +60,6 @@ impl Default for Page {
#[rustfmt::skip] #[rustfmt::skip]
fn default() -> Self { fn default() -> Self {
Page { Page {
context : PageContext::new(),
language : match &*DEFAULT_LANGUAGE { language : match &*DEFAULT_LANGUAGE {
Some(language) => AttributeValue::new().with_value(language), Some(language) => AttributeValue::new().with_value(language),
_ => AttributeValue::new(), _ => AttributeValue::new(),
@ -68,6 +70,10 @@ impl Default for Page {
}, },
title : AttributeValue::new(), title : AttributeValue::new(),
description : AttributeValue::new(), description : AttributeValue::new(),
metadata : Vec::new(),
properties : Vec::new(),
favicon : None,
resources : RenderResources::new(),
body_classes: Classes::new().with_value(ClassesOp::SetDefault, "body"), body_classes: Classes::new().with_value(ClassesOp::SetDefault, "body"),
regions : common_components(), regions : common_components(),
template : "default".to_owned(), template : "default".to_owned(),
@ -82,11 +88,6 @@ impl Page {
// Page BUILDER. // Page BUILDER.
pub fn with_context(mut self, op: PageOp) -> Self {
self.alter_context(op);
self
}
pub fn with_language(mut self, language: &str) -> Self { pub fn with_language(mut self, language: &str) -> Self {
self.alter_language(language); self.alter_language(language);
self self
@ -107,6 +108,26 @@ impl Page {
self self
} }
pub fn with_metadata(mut self, name: &'static str, content: &'static str) -> Self {
self.alter_metadata(name, content);
self
}
pub fn with_property(mut self, property: &'static str, content: &'static str) -> Self {
self.alter_property(property, content);
self
}
pub fn with_favicon(mut self, favicon: Option<Favicon>) -> Self {
self.alter_favicon(favicon);
self
}
pub fn with_resource(mut self, op: ResourceOp) -> Self {
self.alter_resource(op);
self
}
pub fn with_body_classes(mut self, op: ClassesOp, classes: &str) -> Self { pub fn with_body_classes(mut self, op: ClassesOp, classes: &str) -> Self {
self.alter_body_classes(op, classes); self.alter_body_classes(op, classes);
self self
@ -129,11 +150,6 @@ impl Page {
// Page ALTER. // Page ALTER.
pub fn alter_context(&mut self, op: PageOp) -> &mut Self {
self.context.alter(op);
self
}
pub fn alter_language(&mut self, language: &str) -> &mut Self { pub fn alter_language(&mut self, language: &str) -> &mut Self {
self.language.alter_value(language); self.language.alter_value(language);
self self
@ -158,6 +174,26 @@ impl Page {
self self
} }
pub fn alter_metadata(&mut self, name: &'static str, content: &'static str) -> &mut Self {
self.metadata.push((name, content));
self
}
pub fn alter_property(&mut self, property: &'static str, content: &'static str) -> &mut Self {
self.metadata.push((property, content));
self
}
pub fn alter_favicon(&mut self, favicon: Option<Favicon>) -> &mut Self {
self.favicon = favicon;
self
}
pub fn alter_resource(&mut self, op: ResourceOp) -> &mut Self {
self.resources.alter(op);
self
}
pub fn alter_body_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self { pub fn alter_body_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.body_classes.alter_value(op, classes); self.body_classes.alter_value(op, classes);
self self
@ -170,10 +206,6 @@ impl Page {
// Page GETTERS. // Page GETTERS.
pub fn context(&mut self) -> &mut PageContext {
&mut self.context
}
pub fn language(&self) -> &AttributeValue { pub fn language(&self) -> &AttributeValue {
&self.language &self.language
} }
@ -190,6 +222,22 @@ impl Page {
&self.description &self.description
} }
pub fn metadata(&self) -> &Vec<(&str, &str)> {
&self.metadata
}
pub fn properties(&self) -> &Vec<(&str, &str)> {
&self.properties
}
pub fn favicon(&self) -> &Option<Favicon> {
&self.favicon
}
pub fn resources(&mut self) -> &mut RenderResources {
&mut self.resources
}
pub fn body_classes(&self) -> &Classes { pub fn body_classes(&self) -> &Classes {
&self.body_classes &self.body_classes
} }
@ -207,13 +255,13 @@ impl Page {
}); });
// Acciones del tema antes de renderizar la página. // Acciones del tema antes de renderizar la página.
self.context.theme().before_render_page(self); self.resources.theme().before_render_page(self);
// Primero, renderizar el cuerpo. // Primero, renderizar el cuerpo.
let body = self.context.theme().render_page_body(self); let body = self.resources.theme().render_page_body(self);
// Luego, renderizar la cabecera. // Luego, renderizar la cabecera.
let head = self.context.theme().render_page_head(self); let head = self.resources.theme().render_page_head(self);
// Finalmente, renderizar la página. // Finalmente, renderizar la página.
Ok(html! { Ok(html! {
@ -227,7 +275,7 @@ impl Page {
pub fn render_region(&mut self, region: &str) -> Option<Markup> { pub fn render_region(&mut self, region: &str) -> Option<Markup> {
match self.regions.get_mut(region) { match self.regions.get_mut(region) {
Some(components) => Some(components.render(&mut self.context)), Some(components) => Some(components.render(&mut self.resources)),
None => None, None => None,
} }
} }