🎨 Revisa acciones de página y estructura de base

This commit is contained in:
Manuel Cillero 2024-12-05 09:41:08 +01:00
parent 8aef379973
commit 7bf89ca90d
13 changed files with 247 additions and 167 deletions

View file

@ -2,6 +2,8 @@ use crate::prelude::*;
pub type FnActionWithComponent<C> = fn(component: &mut C, cx: &mut Context); pub type FnActionWithComponent<C> = fn(component: &mut C, cx: &mut Context);
pub type FnActionWithPage = fn(page: &mut Page);
pub mod component; pub mod component;
pub mod layout; pub mod layout;

View file

@ -6,3 +6,9 @@ pub use after_render_component::*;
mod render_component; mod render_component;
pub use render_component::*; pub use render_component::*;
mod before_render_page_body;
pub use before_render_page_body::*;
mod after_render_page_body;
pub use after_render_page_body::*;

View file

@ -0,0 +1,37 @@
use crate::prelude::*;
use crate::base::action::FnActionWithPage;
pub struct AfterRenderBody {
f: FnActionWithPage,
layout_type_id: Option<TypeId>,
}
impl ActionTrait for AfterRenderBody {
fn layout_type_id(&self) -> Option<TypeId> {
self.layout_type_id
}
}
impl AfterRenderBody {
pub fn new(layout: LayoutRef, f: FnActionWithPage) -> Self {
AfterRenderBody {
f,
layout_type_id: Some(layout.type_id()),
}
}
#[inline(always)]
#[allow(clippy::inline_always)]
pub(crate) fn dispatch(page: &mut Page) {
dispatch_actions(
&ActionKey::new(
TypeId::of::<Self>(),
Some(page.context().layout().type_id()),
None,
None,
),
|action: &Self| (action.f)(page),
);
}
}

View file

@ -0,0 +1,37 @@
use crate::prelude::*;
use crate::base::action::FnActionWithPage;
pub struct BeforeRenderBody {
f: FnActionWithPage,
layout_type_id: Option<TypeId>,
}
impl ActionTrait for BeforeRenderBody {
fn layout_type_id(&self) -> Option<TypeId> {
self.layout_type_id
}
}
impl BeforeRenderBody {
pub fn new(layout: LayoutRef, f: FnActionWithPage) -> Self {
BeforeRenderBody {
f,
layout_type_id: Some(layout.type_id()),
}
}
#[inline(always)]
#[allow(clippy::inline_always)]
pub(crate) fn dispatch(page: &mut Page) {
dispatch_actions(
&ActionKey::new(
TypeId::of::<Self>(),
Some(page.context().layout().type_id()),
None,
None,
),
|action: &Self| (action.f)(page),
);
}
}

View file

@ -1,9 +1,9 @@
use crate::prelude::*; use crate::prelude::*;
pub type FnAfterRenderBody = fn(page: &mut Page); use crate::base::action::FnActionWithPage;
pub struct AfterRenderBody { pub struct AfterRenderBody {
f: FnAfterRenderBody, f: FnActionWithPage,
weight: Weight, weight: Weight,
} }
@ -14,7 +14,7 @@ impl ActionTrait for AfterRenderBody {
} }
impl AfterRenderBody { impl AfterRenderBody {
pub fn new(f: FnAfterRenderBody) -> Self { pub fn new(f: FnActionWithPage) -> Self {
AfterRenderBody { f, weight: 0 } AfterRenderBody { f, weight: 0 }
} }

View file

@ -1,9 +1,9 @@
use crate::prelude::*; use crate::prelude::*;
pub type FnBeforeRenderBody = fn(page: &mut Page); use crate::base::action::FnActionWithPage;
pub struct BeforeRenderBody { pub struct BeforeRenderBody {
f: FnBeforeRenderBody, f: FnActionWithPage,
weight: Weight, weight: Weight,
} }
@ -14,7 +14,7 @@ impl ActionTrait for BeforeRenderBody {
} }
impl BeforeRenderBody { impl BeforeRenderBody {
pub fn new(f: FnBeforeRenderBody) -> Self { pub fn new(f: FnActionWithPage) -> Self {
BeforeRenderBody { f, weight: 0 } BeforeRenderBody { f, weight: 0 }
} }

View file

@ -1,11 +1,2 @@
use crate::prelude::*; mod basic;
pub use basic::Basic;
pub struct Basic;
impl PackageTrait for Basic {
fn layout(&self) -> Option<LayoutRef> {
Some(&Basic)
}
}
impl LayoutTrait for Basic {}

View file

@ -0,0 +1,11 @@
use crate::prelude::*;
pub struct Basic;
impl PackageTrait for Basic {
fn layout(&self) -> Option<LayoutRef> {
Some(&Basic)
}
}
impl LayoutTrait for Basic {}

View file

@ -1,133 +1,2 @@
use crate::prelude::*; mod welcome;
pub use welcome::Welcome;
pub struct Welcome;
impl PackageTrait for Welcome {
fn name(&self) -> L10n {
L10n::l("welcome_package_name")
}
fn description(&self) -> L10n {
L10n::l("welcome_package_description")
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
scfg.route("/", service::web::get().to(homepage));
}
}
async fn homepage(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
Page::new(request)
.with_title(L10n::l("welcome_page"))
.with_assets(AssetsOp::Layout("Basic"))
.with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##"
body {
background-color: #f3d060;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 20px;
}
.skip__to_content {
display: none;
}
.wrapper {
max-width: 1200px;
width: 100%;
margin: 0 auto;
padding: 0;
}
.container {
padding: 0 16px;
}
.title {
font-size: clamp(3rem, 10vw, 10rem);
letter-spacing: -0.05em;
line-height: 1.2;
margin: 0;
}
.subtitle {
font-size: clamp(1.8rem, 2vw, 3rem);
letter-spacing: -0.02em;
line-height: 1.2;
margin: 0;
}
.powered {
margin: .5em 0 1em;
}
.box-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: stretch;
gap: 1.5em;
}
.box {
flex: 1 1 280px;
border: 3px solid #25282a;
box-shadow: 5px 5px 0px #25282a;
box-sizing: border-box;
padding: 0 16px;
}
footer {
margin-top: 5em;
font-size: 14px;
font-weight: 500;
color: #a5282c;
}
"##)))
.with_component(Html::with(html! {
div class="wrapper" {
div class="container" {
h1 class="title" { (L10n::l("welcome_title").markup()) }
p class="subtitle" {
(L10n::l("welcome_intro").with_arg("app", format!(
"<span style=\"font-weight: bold;\">{}</span>",
&global::SETTINGS.app.name
)).markup())
}
p class="powered" {
(L10n::l("welcome_powered").with_arg("pagetop", format!(
"<a href=\"{}\" target=\"_blank\">{}</a>",
"https://crates.io/crates/pagetop", "PageTop"
)).markup())
}
h2 { (L10n::l("welcome_page").markup()) }
div class="box-container" {
section class="box" style="background-color: #5eb0e5;" {
h3 {
(L10n::l("welcome_subtitle")
.with_arg("app", &global::SETTINGS.app.name)
.markup())
}
p { (L10n::l("welcome_text1").markup()) }
p { (L10n::l("welcome_text2").markup()) }
}
section class="box" style="background-color: #aee1cd;" {
h3 {
(L10n::l("welcome_pagetop_title").markup())
}
p { (L10n::l("welcome_pagetop_text1").markup()) }
p { (L10n::l("welcome_pagetop_text2").markup()) }
p { (L10n::l("welcome_pagetop_text3").markup()) }
}
section class="box" style="background-color: #ebebe3;" {
h3 {
(L10n::l("welcome_issues_title").markup())
}
p { (L10n::l("welcome_issues_text1").markup()) }
p {
(L10n::l("welcome_issues_text2")
.with_arg("app", &global::SETTINGS.app.name)
.markup())
}
}
}
footer { "[ " (L10n::l("welcome_have_fun").markup()) " ]" }
}
}
}))
.render()
}

View file

@ -0,0 +1,133 @@
use crate::prelude::*;
pub struct Welcome;
impl PackageTrait for Welcome {
fn name(&self) -> L10n {
L10n::l("welcome_package_name")
}
fn description(&self) -> L10n {
L10n::l("welcome_package_description")
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
scfg.route("/", service::web::get().to(homepage));
}
}
async fn homepage(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
Page::new(request)
.with_title(L10n::l("welcome_page"))
.with_assets(AssetsOp::Layout("Basic"))
.with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##"
body {
background-color: #f3d060;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 20px;
}
.skip__to_content {
display: none;
}
.wrapper {
max-width: 1200px;
width: 100%;
margin: 0 auto;
padding: 0;
}
.container {
padding: 0 16px;
}
.title {
font-size: clamp(3rem, 10vw, 10rem);
letter-spacing: -0.05em;
line-height: 1.2;
margin: 0;
}
.subtitle {
font-size: clamp(1.8rem, 2vw, 3rem);
letter-spacing: -0.02em;
line-height: 1.2;
margin: 0;
}
.powered {
margin: .5em 0 1em;
}
.box-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: stretch;
gap: 1.5em;
}
.box {
flex: 1 1 280px;
border: 3px solid #25282a;
box-shadow: 5px 5px 0px #25282a;
box-sizing: border-box;
padding: 0 16px;
}
footer {
margin-top: 5em;
font-size: 14px;
font-weight: 500;
color: #a5282c;
}
"##)))
.with_component(Html::with(html! {
div class="wrapper" {
div class="container" {
h1 class="title" { (L10n::l("welcome_title").markup()) }
p class="subtitle" {
(L10n::l("welcome_intro").with_arg("app", format!(
"<span style=\"font-weight: bold;\">{}</span>",
&global::SETTINGS.app.name
)).markup())
}
p class="powered" {
(L10n::l("welcome_powered").with_arg("pagetop", format!(
"<a href=\"{}\" target=\"_blank\">{}</a>",
"https://crates.io/crates/pagetop", "PageTop"
)).markup())
}
h2 { (L10n::l("welcome_page").markup()) }
div class="box-container" {
section class="box" style="background-color: #5eb0e5;" {
h3 {
(L10n::l("welcome_subtitle")
.with_arg("app", &global::SETTINGS.app.name)
.markup())
}
p { (L10n::l("welcome_text1").markup()) }
p { (L10n::l("welcome_text2").markup()) }
}
section class="box" style="background-color: #aee1cd;" {
h3 {
(L10n::l("welcome_pagetop_title").markup())
}
p { (L10n::l("welcome_pagetop_text1").markup()) }
p { (L10n::l("welcome_pagetop_text2").markup()) }
p { (L10n::l("welcome_pagetop_text3").markup()) }
}
section class="box" style="background-color: #ebebe3;" {
h3 {
(L10n::l("welcome_issues_title").markup())
}
p { (L10n::l("welcome_issues_text1").markup()) }
p {
(L10n::l("welcome_issues_text2")
.with_arg("app", &global::SETTINGS.app.name)
.markup())
}
}
}
footer { "[ " (L10n::l("welcome_have_fun").markup()) " ]" }
}
}
}))
.render()
}

View file

@ -40,7 +40,7 @@ impl<C: ComponentTrait> ComponentBase for C {
// Comprueba el componente antes de prepararlo. // Comprueba el componente antes de prepararlo.
self.setup_before_prepare(cx); self.setup_before_prepare(cx);
// Acciones del diseño antes de renderizar el componente. // Acciones específicas del diseño antes de renderizar el componente.
action::layout::BeforeRender::dispatch(self, cx); action::layout::BeforeRender::dispatch(self, cx);
// Acciones de los paquetes antes de renderizar el componente. // Acciones de los paquetes antes de renderizar el componente.
@ -52,7 +52,7 @@ impl<C: ComponentTrait> ComponentBase for C {
None => self.prepare_component(cx).render(), None => self.prepare_component(cx).render(),
}; };
// Acciones del diseño después de renderizar el componente. // Acciones específicas del diseño después de renderizar el componente.
action::layout::AfterRender::dispatch(self, cx); action::layout::AfterRender::dispatch(self, cx);
// Acciones de los paquetes después de renderizar el componente. // Acciones de los paquetes después de renderizar el componente.

View file

@ -43,9 +43,6 @@ pub trait LayoutTrait: PackageTrait + Send + Sync {
} }
} }
#[allow(unused_variables)]
fn before_render_body(&self, page: &mut Page) {}
fn render_body(&self, page: &mut Page) -> Markup { fn render_body(&self, page: &mut Page) -> Markup {
html! { html! {
body id=[page.body_id().get()] class=[page.body_classes().get()] { body id=[page.body_id().get()] class=[page.body_classes().get()] {
@ -53,7 +50,4 @@ pub trait LayoutTrait: PackageTrait + Send + Sync {
} }
} }
} }
#[allow(unused_variables)]
fn after_render_body(&self, page: &mut Page) {}
} }

View file

@ -156,25 +156,25 @@ impl Page {
// Page RENDER. // Page RENDER.
pub fn render(&mut self) -> ResultPage<Markup, ErrorPage> { pub fn render(&mut self) -> ResultPage<Markup, ErrorPage> {
// Layout-specific operations before rendering the page body. // Acciones específicas del diseño antes de renderizar el <body>.
self.context.layout().before_render_body(self); action::layout::BeforeRenderBody::dispatch(self);
// Execute package actions before rendering the page body. // Acciones de los paquetes antes de renderizar el <body>.
action::page::BeforeRenderBody::dispatch(self); action::page::BeforeRenderBody::dispatch(self);
// Render the page body. // Renderiza el <body>.
let body = self.context.layout().render_body(self); let body = self.context.layout().render_body(self);
// Layout-specific operations after rendering the page body. // Acciones específicas del diseño después de renderizar el <body>.
self.context.layout().after_render_body(self); action::layout::AfterRenderBody::dispatch(self);
// Execute package actions after rendering the page body. // Acciones de los paquetes después de renderizar el <body>.
action::page::AfterRenderBody::dispatch(self); action::page::AfterRenderBody::dispatch(self);
// Render the page head. // Renderiza el <head>.
let head = self.context.layout().render_head(self); let head = self.context.layout().render_head(self);
// Render the full page with language and direction attributes. // Compone la página completa incluyendo los atributos de idioma y dirección del texto.
let lang = &self.context.langid().language; let lang = &self.context.langid().language;
let dir = match self.context.langid().character_direction() { let dir = match self.context.langid().character_direction() {
CharacterDirection::LTR => "ltr", CharacterDirection::LTR => "ltr",