💥 Diferencia entre renderizar y preparar página

This commit is contained in:
Manuel Cillero 2023-06-23 23:50:52 +02:00
parent 97b520340a
commit a33de4c92b
11 changed files with 111 additions and 46 deletions

View file

@ -30,7 +30,7 @@ impl ModuleTrait for Admin {
} }
fn actions(&self) -> Vec<Action> { fn actions(&self) -> Vec<Action> {
vec![action!(ActionBeforeRenderPage => before_render_page)] vec![action!(ActionBeforePreparePage => before_prepare_page)]
} }
fn configure_service(&self, cfg: &mut service::web::ServiceConfig) { fn configure_service(&self, cfg: &mut service::web::ServiceConfig) {
@ -40,6 +40,6 @@ impl ModuleTrait for Admin {
} }
} }
fn before_render_page(page: &mut Page) { fn before_prepare_page(page: &mut Page) {
page.alter_body_classes(ClassesOp::Add, "test-admin"); page.alter_body_classes(ClassesOp::Add, "test-admin");
} }

View file

@ -21,7 +21,7 @@ impl ModuleTrait for Aliner {
} }
impl ThemeTrait for Aliner { impl ThemeTrait for Aliner {
fn before_render_page(&self, page: &mut Page) { fn before_prepare_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico"))) page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet( .alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/aliner/css/styles.css").with_weight(-99), StyleSheet::located("/aliner/css/styles.css").with_weight(-99),

View file

@ -42,7 +42,7 @@ impl ThemeTrait for Bootsier {
] ]
} }
fn before_render_page(&self, page: &mut Page) { fn before_prepare_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico"))) page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet( .alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/bootsier/css/bootstrap.min.css") StyleSheet::located("/bootsier/css/bootstrap.min.css")
@ -57,7 +57,7 @@ impl ThemeTrait for Bootsier {
pagetop_jquery::JQuery::add_jquery(page.context()); pagetop_jquery::JQuery::add_jquery(page.context());
} }
fn render_page_body(&self, page: &mut Page) -> Markup { fn prepare_page_body(&self, page: &mut Page) -> Markup {
match page.template() { match page.template() {
"admin" => html! { "admin" => html! {
body class=[page.body_classes().get()] { body class=[page.body_classes().get()] {
@ -66,22 +66,22 @@ impl ThemeTrait for Bootsier {
"side-menu", "side-menu",
"content" "content"
] { ] {
@if let Some(content) = page.render_region(region) { @if let Some(content) = page.prepare_region(region) {
#(region) { (content) } #(region) { (content) }
} }
} }
} }
}, },
_ => { _ => {
let header = page.render_region("header"); let header = page.prepare_region("header");
let nav_branding = page.render_region("nav_branding"); let nav_branding = page.prepare_region("nav_branding");
let nav_main = page.render_region("nav_main"); let nav_main = page.prepare_region("nav_main");
let nav_additional = page.render_region("nav_additional"); let nav_additional = page.prepare_region("nav_additional");
let breadcrumb = page.render_region("breadcrumb"); let breadcrumb = page.prepare_region("breadcrumb");
let content = page.render_region("content"); let content = page.prepare_region("content");
let sidebar_first = page.render_region("sidebar_first"); let sidebar_first = page.prepare_region("sidebar_first");
let sidebar_second = page.render_region("sidebar_second"); let sidebar_second = page.prepare_region("sidebar_second");
let footer = page.render_region("footer"); let footer = page.prepare_region("footer");
html! { html! {
body class=[page.body_classes().get()] { body class=[page.body_classes().get()] {
@if header.is_some() { @if header.is_some() {

View file

@ -30,7 +30,7 @@ impl ModuleTrait for Bulmix {
} }
impl ThemeTrait for Bulmix { impl ThemeTrait for Bulmix {
fn before_render_page(&self, page: &mut Page) { fn before_prepare_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico"))) page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet( .alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/bulmix/css/bulma.min.css") StyleSheet::located("/bulmix/css/bulma.min.css")

View file

@ -27,7 +27,7 @@ impl ModuleTrait for Node {
} }
fn actions(&self) -> Vec<Action> { fn actions(&self) -> Vec<Action> {
vec![action!(ActionBeforeRenderPage => before_render_page, -1)] vec![action!(ActionBeforePreparePage => before_prepare_page, -1)]
} }
fn migrations(&self) -> Vec<MigrationItem> { fn migrations(&self) -> Vec<MigrationItem> {
@ -44,6 +44,6 @@ async fn node(request: service::HttpRequest) -> ResultPage<Markup, FatalError> {
Page::new(request).with_title(L10n::n("Nodo")).render() Page::new(request).with_title(L10n::n("Nodo")).render()
} }
fn before_render_page(page: &mut Page) { fn before_prepare_page(page: &mut Page) {
page.alter_body_classes(ClassesOp::Add, "test-node"); page.alter_body_classes(ClassesOp::Add, "test-node");
} }

View file

@ -21,7 +21,7 @@ impl ModuleTrait for Basic {
} }
impl ThemeTrait for Basic { impl ThemeTrait for Basic {
fn before_render_page(&self, page: &mut Page) { fn before_prepare_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico"))); page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")));
} }
} }

View file

@ -21,13 +21,9 @@ pub trait ThemeTrait: ModuleTrait + Send + Sync {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) { fn before_prepare_page(&self, page: &mut Page) {}
if page.favicon().is_none() {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")));
}
}
fn render_page_head(&self, page: &mut Page) -> Markup { fn prepare_page_head(&self, page: &mut Page) -> Markup {
let title = page.title(); let title = page.title();
let description = page.description(); let description = page.description();
let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no"; let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no";
@ -64,11 +60,11 @@ pub trait ThemeTrait: ModuleTrait + Send + Sync {
} }
} }
fn render_page_body(&self, page: &mut Page) -> Markup { fn prepare_page_body(&self, page: &mut Page) -> Markup {
html! { html! {
body class=[page.body_classes().get()] { body class=[page.body_classes().get()] {
@for (region, _) in self.regions().iter() { @for (region, _) in self.regions().iter() {
@if let Some(content) = page.render_region(region) { @if let Some(content) = page.prepare_region(region) {
#(region) { (content) } #(region) { (content) }
} }
} }
@ -76,6 +72,12 @@ pub trait ThemeTrait: ModuleTrait + Send + Sync {
} }
} }
fn after_prepare_page(&self, page: &mut Page) {
if page.favicon().is_none() {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")));
}
}
#[rustfmt::skip] #[rustfmt::skip]
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_component( fn before_render_component(

View file

@ -1,7 +1,10 @@
pub use actix_web::Result as ResultPage; pub use actix_web::Result as ResultPage;
mod action; mod before_prepare_page;
pub use action::{ActionBeforeRenderPage, ACTION_BEFORE_RENDER_PAGE}; pub use before_prepare_page::{ActionBeforePreparePage, ACTION_BEFORE_PREPARE_PAGE};
mod after_prepare_page;
pub use after_prepare_page::{ActionAfterPreparePage, ACTION_AFTER_PREPARE_PAGE};
mod definition; mod definition;
pub use definition::Page; pub use definition::Page;

View file

@ -2,25 +2,25 @@ use crate::core::action::{ActionTrait, AnyAction};
use crate::response::page::Page; use crate::response::page::Page;
use crate::{use_handle, Handle}; use crate::{use_handle, Handle};
use_handle!(ACTION_BEFORE_RENDER_PAGE); use_handle!(ACTION_AFTER_PREPARE_PAGE);
type Action = fn(&mut Page); type Action = fn(&mut Page);
pub struct ActionBeforeRenderPage { pub struct ActionAfterPreparePage {
action: Option<Action>, action: Option<Action>,
weight: isize, weight: isize,
} }
impl ActionTrait for ActionBeforeRenderPage { impl ActionTrait for ActionAfterPreparePage {
fn new() -> Self { fn new() -> Self {
ActionBeforeRenderPage { ActionAfterPreparePage {
action: None, action: None,
weight: 0, weight: 0,
} }
} }
fn handle(&self) -> Handle { fn handle(&self) -> Handle {
ACTION_BEFORE_RENDER_PAGE ACTION_AFTER_PREPARE_PAGE
} }
fn weight(&self) -> isize { fn weight(&self) -> isize {
@ -32,7 +32,7 @@ impl ActionTrait for ActionBeforeRenderPage {
} }
} }
impl ActionBeforeRenderPage { impl ActionAfterPreparePage {
pub fn with_action(mut self, action: Action) -> Self { pub fn with_action(mut self, action: Action) -> Self {
self.action = Some(action); self.action = Some(action);
self self

View file

@ -0,0 +1,51 @@
use crate::core::action::{ActionTrait, AnyAction};
use crate::response::page::Page;
use crate::{use_handle, Handle};
use_handle!(ACTION_BEFORE_PREPARE_PAGE);
type Action = fn(&mut Page);
pub struct ActionBeforePreparePage {
action: Option<Action>,
weight: isize,
}
impl ActionTrait for ActionBeforePreparePage {
fn new() -> Self {
ActionBeforePreparePage {
action: None,
weight: 0,
}
}
fn handle(&self) -> Handle {
ACTION_BEFORE_PREPARE_PAGE
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyAction {
self
}
}
impl ActionBeforePreparePage {
pub fn with_action(mut self, action: Action) -> Self {
self.action = Some(action);
self
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, page: &mut Page) {
if let Some(action) = self.action {
action(page)
}
}
}

View file

@ -5,8 +5,9 @@ use crate::core::theme::ComponentsRegions;
use crate::html::{html, Classes, ClassesOp, Favicon, Markup, DOCTYPE}; use crate::html::{html, Classes, ClassesOp, Favicon, Markup, DOCTYPE};
use crate::locale::{langid_for, LanguageIdentifier}; use crate::locale::{langid_for, LanguageIdentifier};
use crate::response::fatal_error::FatalError; use crate::response::fatal_error::FatalError;
use crate::response::page::action::{ActionBeforeRenderPage, ACTION_BEFORE_RENDER_PAGE};
use crate::response::page::ResultPage; use crate::response::page::ResultPage;
use crate::response::page::{ActionAfterPreparePage, ACTION_AFTER_PREPARE_PAGE};
use crate::response::page::{ActionBeforePreparePage, ACTION_BEFORE_PREPARE_PAGE};
use crate::{fn_builder, service}; use crate::{fn_builder, service};
use unic_langid::CharacterDirection; use unic_langid::CharacterDirection;
@ -154,19 +155,27 @@ impl Page {
// Page RENDER. // Page RENDER.
pub fn render(&mut self) -> ResultPage<Markup, FatalError> { pub fn render(&mut self) -> ResultPage<Markup, FatalError> {
// Acciones de los módulos antes de renderizar la página. // Acciones de los módulos antes de preparar la página.
run_actions(ACTION_BEFORE_RENDER_PAGE, |action| { run_actions(ACTION_BEFORE_PREPARE_PAGE, |action| {
action_ref::<ActionBeforeRenderPage>(&**action).run(self) action_ref::<ActionBeforePreparePage>(&**action).run(self)
}); });
// Acciones del tema antes de renderizar la página. // Acciones del tema antes de preparar la página.
self.context.theme().before_render_page(self); self.context.theme().before_prepare_page(self);
// Primero, renderizar el cuerpo. // Primero, preparar el cuerpo.
let body = self.context.theme().render_page_body(self); let body = self.context.theme().prepare_page_body(self);
// Luego, renderizar la cabecera. // Luego, preparar la cabecera.
let head = self.context.theme().render_page_head(self); let head = self.context.theme().prepare_page_head(self);
// Acciones de los módulos después de preparar la página.
run_actions(ACTION_AFTER_PREPARE_PAGE, |action| {
action_ref::<ActionAfterPreparePage>(&**action).run(self)
});
// Acciones del tema después de preparar la página.
self.context.theme().after_prepare_page(self);
// Finalmente, renderizar la página. // Finalmente, renderizar la página.
let lang = self.langid().language.as_str(); let lang = self.langid().language.as_str();
@ -183,7 +192,7 @@ impl Page {
}) })
} }
pub fn render_region(&mut self, region: &str) -> Option<Markup> { pub fn prepare_region(&mut self, region: &str) -> Option<Markup> {
let render = self let render = self
.regions .regions
.get_extended_bundle(self.context.theme().single_name(), region) .get_extended_bundle(self.context.theme().single_name(), region)