🎨 Convierte el ciclo de renderizado en async
`prepare()` de `Component`, `render()` de `Region` y `Template`, y la implementación de `ComponentRender` pasan a ser funciones async. Se actualizan todos los componentes base, helpers, tests y ejemplos.
This commit is contained in:
parent
9acd8cc51a
commit
9354894b3a
48 changed files with 436 additions and 365 deletions
|
|
@ -14,6 +14,7 @@ pub struct Block {
|
|||
children: Children,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Block {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -31,8 +32,8 @@ impl Component for Block {
|
|||
self.alter_prop(PropsOp::prepend_classes("block"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let block_body = self.children().render(cx);
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let block_body = self.children().render(cx).await;
|
||||
|
||||
if block_body.is_empty() {
|
||||
return Ok(html! {});
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ pub struct Button {
|
|||
disabled: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Button {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -94,7 +95,7 @@ impl Component for Button {
|
|||
self.alter_prop(PropsOp::prepend_classes("button"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
Ok(html! {
|
||||
button
|
||||
type=(self.kind())
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ pub struct Field {
|
|||
inline: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Field {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -145,7 +146,7 @@ impl Component for Field {
|
|||
self.alter_prop(PropsOp::prepend_classes("form-field form-field-checkboxes"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ pub struct Checkbox {
|
|||
reverse: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Checkbox {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -95,7 +96,7 @@ impl Component for Checkbox {
|
|||
self.alter_prop(PropsOp::prepend_classes(classes));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ pub struct Form {
|
|||
children: Children,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Form {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -70,7 +71,7 @@ impl Component for Form {
|
|||
self.alter_prop(PropsOp::prepend_classes("form"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let method = match self.method() {
|
||||
form::Method::Post => Some("post"),
|
||||
form::Method::Get => None,
|
||||
|
|
@ -82,7 +83,7 @@ impl Component for Form {
|
|||
method=[method]
|
||||
accept-charset=[self.charset().get()]
|
||||
{
|
||||
(self.children().render(cx))
|
||||
(self.children().render(cx).await)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub struct Fieldset {
|
|||
children: Children,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Fieldset {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -45,8 +46,8 @@ impl Component for Fieldset {
|
|||
self.props.get_id()
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let children = self.children().render(cx);
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let children = self.children().render(cx).await;
|
||||
|
||||
if children.is_empty() {
|
||||
return Ok(html! {});
|
||||
|
|
|
|||
|
|
@ -35,12 +35,13 @@ pub struct Hidden {
|
|||
value: AttrValue,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Hidden {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn prepare(&self, _cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, _cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
Ok(html! {
|
||||
input
|
||||
type="hidden"
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ pub struct Field {
|
|||
inputmode: Attr<Mode>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Field {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -181,7 +182,7 @@ impl Component for Field {
|
|||
)));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let container_id = self.id();
|
||||
let input_id = container_id.as_deref().map(|id| util::join!(id, "-input"));
|
||||
let input_class = if *self.plaintext() {
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ pub struct Field {
|
|||
inline: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Field {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -136,7 +137,7 @@ impl Component for Field {
|
|||
self.alter_prop(PropsOp::prepend_classes("form-field form-field-radios"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
// En `setup()` se garantiza que `name` e `id` están definidos antes del renderizado.
|
||||
let name = self.name().get().unwrap();
|
||||
let container_id = self.id().unwrap();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ pub struct Range {
|
|||
disabled: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Range {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -74,7 +75,7 @@ impl Component for Range {
|
|||
self.alter_prop(PropsOp::prepend_classes("form-field form-field-range"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let container_id = self.id();
|
||||
let range_id = container_id.as_deref().map(|id| util::join!(id, "-range"));
|
||||
Ok(html! {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ pub struct Field {
|
|||
disabled: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Field {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -233,7 +234,7 @@ impl Component for Field {
|
|||
self.alter_prop(PropsOp::prepend_classes("form-field form-field-select"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let container_id = self.id();
|
||||
let select_id = container_id.as_deref().map(|id| util::join!(id, "-select"));
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ pub struct Textarea {
|
|||
disabled: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Textarea {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
|
|
@ -84,7 +85,7 @@ impl Component for Textarea {
|
|||
self.alter_prop(PropsOp::prepend_classes("form-field form-field-textarea"));
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
let container_id = self.id();
|
||||
let textarea_id = container_id
|
||||
.as_deref()
|
||||
|
|
|
|||
|
|
@ -49,12 +49,13 @@ impl Default for Html {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Html {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
Ok(self.html(cx))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,12 +107,13 @@ impl Default for Intro {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for Intro {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
cx.alter_assets(AssetsOp::AddStyleSheet(
|
||||
StyleSheet::from("/pagetop/css/intro.css").with_version(PAGETOP_VERSION),
|
||||
));
|
||||
|
|
@ -146,7 +147,7 @@ impl Component for Intro {
|
|||
}
|
||||
aside class="intro-header-img" aria-hidden="true" {
|
||||
div class="intro-header-mascot" {
|
||||
(PageTopSvg::Color.render(cx))
|
||||
(PageTopSvg::Color.markup(cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +192,7 @@ impl Component for Intro {
|
|||
(L10n::l("intro_text2").using(cx))
|
||||
}
|
||||
}
|
||||
(self.children().render(cx))
|
||||
(self.children().render(cx).await)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -199,7 +200,7 @@ impl Component for Intro {
|
|||
div class="intro-footer" {
|
||||
section class="intro-footer-body" {
|
||||
div class="intro-footer-logo" {
|
||||
(PageTopSvg::LineLight.render(cx))
|
||||
(PageTopSvg::LineLight.markup(cx))
|
||||
}
|
||||
div class="intro-footer-links" {
|
||||
a href="https://crates.io/crates/pagetop" target="_blank" rel="noopener noreferrer" { ("Crates.io") }
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ pub struct PoweredBy {
|
|||
copyright: Option<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Component for PoweredBy {
|
||||
/// Crea una nueva instancia de `PoweredBy`.
|
||||
///
|
||||
|
|
@ -25,7 +26,7 @@ impl Component for PoweredBy {
|
|||
PoweredBy { copyright: Some(c) }
|
||||
}
|
||||
|
||||
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||
Ok(html! {
|
||||
div id=[self.id()] class="poweredby" {
|
||||
@if let Some(c) = self.copyright() {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::prelude::*;
|
|||
/// Resulta útil en demos o para comprobar rápidamente que el servidor ha arrancado correctamente.
|
||||
pub struct Welcome;
|
||||
|
||||
#[async_trait]
|
||||
impl Extension for Welcome {
|
||||
fn name(&self) -> L10n {
|
||||
L10n::l("welcome_extension_name")
|
||||
|
|
@ -62,4 +63,5 @@ async fn home(request: HttpRequest) -> Result<Markup, ErrorPage> {
|
|||
),
|
||||
)
|
||||
.render()
|
||||
.await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,14 @@ use crate::prelude::*;
|
|||
/// Tema básico por defecto que extiende el funcionamiento predeterminado de [`Theme`].
|
||||
pub struct Basic;
|
||||
|
||||
#[async_trait]
|
||||
impl Extension for Basic {
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
Some(&Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Theme for Basic {
|
||||
fn before_render_page_body(&self, page: &mut Page) {
|
||||
page.alter_assets(AssetsOp::AddStyleSheet(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue