Añade la función arc() para capturar el componente

Recibe un componente mutable que podría modificarse justo antes de ser
añadido a un contenedor. Es una posible solución para poder desarrollar
un mecanismo aceptable de Triggers/Hooks/Actions (THA) para PageTop.
This commit is contained in:
Manuel Cillero 2022-04-02 09:21:43 +02:00
parent 69139f2a62
commit 53dd1f24c7
14 changed files with 50 additions and 36 deletions

View file

@ -38,17 +38,18 @@ pub async fn summary() -> app::Result<Markup> {
.with_title("Admin") .with_title("Admin")
.add_to("top-menu", top_menu) .add_to("top-menu", top_menu.arc())
.add_to("content", grid::Row::new() .add_to("content", grid::Row::new()
.add_column(grid::Column::new() .add_column(grid::Column::new()
.add(side_menu) .add(side_menu.arc())
) )
.add_column(grid::Column::new() .add_column(grid::Column::new()
.add(Chunck::with(html! { .add(Chunck::with(html! {
p { "Columna 2"} p { "Columna 2"}
})) }).arc())
) )
.arc()
) )

View file

@ -31,7 +31,7 @@ impl ModuleTrait for UserModule {
} }
} }
fn form_login() -> impl PageComponent { fn form_login() -> ArcComponent {
Form::new() Form::new()
.with_id("user-login") .with_id("user-login")
.add(form::Input::textfield() .add(form::Input::textfield()
@ -41,13 +41,16 @@ fn form_login() -> impl PageComponent {
"app" => SETTINGS.app.name.to_owned() "app" => SETTINGS.app.name.to_owned()
]).as_str()) ]).as_str())
.with_autofocus(true) .with_autofocus(true)
.arc()
) )
.add(form::Input::password() .add(form::Input::password()
.with_name("pass") .with_name("pass")
.with_label(l("password").as_str()) .with_label(l("password").as_str())
.with_help_text(l("password_help").as_str()) .with_help_text(l("password_help").as_str())
.arc()
) )
.add(form::Button::submit(l("login").as_str())) .add(form::Button::submit(l("login").as_str()).arc())
.arc()
} }
async fn login() -> app::Result<Markup> { async fn login() -> app::Result<Markup> {
@ -58,6 +61,7 @@ async fn login() -> app::Result<Markup> {
.add_to("content", Container::new() .add_to("content", Container::new()
.with_id("welcome") .with_id("welcome")
.add(form_login()) .add(form_login())
.arc()
) )
.render() .render()
} }

View file

@ -109,7 +109,7 @@ impl Container {
self self
} }
pub fn add(mut self, component: impl PageComponent) -> Self { pub fn add(mut self, component: ArcComponent) -> Self {
self.components.add(component); self.components.add(component);
self self
} }

View file

@ -85,7 +85,7 @@ impl Form {
self self
} }
pub fn add(mut self, element: impl PageComponent) -> Self { pub fn add(mut self, element: ArcComponent) -> Self {
self.elements.add(element); self.elements.add(element);
self self
} }

View file

@ -56,7 +56,7 @@ impl Column {
self self
} }
pub fn add(mut self, component: impl PageComponent) -> Self { pub fn add(mut self, component: ArcComponent) -> Self {
self.components.add(component); self.components.add(component);
self self
} }

View file

@ -57,7 +57,7 @@ impl Row {
} }
pub fn add_column(mut self, column: grid::Column) -> Self { pub fn add_column(mut self, column: grid::Column) -> Self {
self.columns.add(column); self.columns.add(column.arc());
self self
} }

View file

@ -222,7 +222,7 @@ impl Menu {
} }
pub fn add(mut self, item: MenuItem) -> Self { pub fn add(mut self, item: MenuItem) -> Self {
self.items.add(item); self.items.add(item.arc());
self self
} }

View file

@ -35,7 +35,7 @@ async fn demo() -> app::Result<Markup> {
.render() .render()
} }
fn hello_world() -> Container { fn hello_world() -> ArcComponent {
Container::header() Container::header()
.add(grid::Row::new() .add(grid::Row::new()
.add_column(grid::Column::new() .add_column(grid::Column::new()
@ -68,15 +68,17 @@ fn hello_world() -> Container {
i class="fas fa-paper-plane" {} i class="fas fa-paper-plane" {}
"Get quote" "Get quote"
} }
})) }).arc())
) )
.add_column(grid::Column::new() .add_column(grid::Column::new()
.add(Image::image("/bootsier/images/demo-header.svg")) .add(Image::image("/bootsier/images/demo-header.svg").arc())
) )
.arc()
) )
.arc()
} }
fn hello_world_original() -> Chunck { fn hello_world_original() -> ArcComponent {
Chunck::with(html! { Chunck::with(html! {
header id="header" class="header" { header id="header" class="header" {
div class="container" { div class="container" {
@ -121,10 +123,10 @@ fn hello_world_original() -> Chunck {
} }
} }
} }
}) }).arc()
} }
fn just_visiting() -> Chunck { fn just_visiting() -> ArcComponent {
Chunck::with(html! { Chunck::with(html! {
div id="details" class="basic-1" { div id="details" class="basic-1" {
div class="container" { div class="container" {
@ -151,10 +153,10 @@ fn just_visiting() -> Chunck {
} }
} }
} }
}) }).arc()
} }
fn about_pagetop() -> Chunck { fn about_pagetop() -> ArcComponent {
Chunck::with(html! { Chunck::with(html! {
div id="pagetop" class="basic-2" { div id="pagetop" class="basic-2" {
div class="container" { div class="container" {
@ -175,10 +177,10 @@ fn about_pagetop() -> Chunck {
} }
} }
} }
}) }).arc()
} }
fn promo_pagetop() -> Chunck { fn promo_pagetop() -> ArcComponent {
Chunck::with(html! { Chunck::with(html! {
div id="promo" class="basic-3" { div id="promo" class="basic-3" {
div class="container" { div class="container" {
@ -200,10 +202,10 @@ fn promo_pagetop() -> Chunck {
} }
} }
} }
}) }).arc()
} }
fn reporting_problems() -> Chunck { fn reporting_problems() -> ArcComponent {
Chunck::with(html! { Chunck::with(html! {
div id="reporting" class="basic-4" { div id="reporting" class="basic-4" {
div class="container" { div class="container" {
@ -223,5 +225,5 @@ fn reporting_problems() -> Chunck {
} }
} }
} }
}) }).arc()
} }

View file

@ -77,7 +77,7 @@ impl ThemeTrait for BootsierTheme {
} }
} }
} }
})) }).arc())
.render() .render()
} }
} }

View file

@ -3,8 +3,11 @@ use crate::response::page::PageAssets;
use downcast_rs::{Downcast, impl_downcast}; use downcast_rs::{Downcast, impl_downcast};
use std::sync::Arc;
use std::any::type_name; use std::any::type_name;
pub type ArcComponent = Arc<dyn PageComponent>;
pub trait PageComponent: Downcast + Send + Sync { pub trait PageComponent: Downcast + Send + Sync {
fn new() -> Self where Self: Sized; fn new() -> Self where Self: Sized;
@ -33,6 +36,12 @@ pub trait PageComponent: Downcast + Send + Sync {
0 0
} }
#[allow(unused_mut)]
fn arc(mut self) -> ArcComponent where Self: Sized {
let component = self;
Arc::new(component)
}
#[allow(unused_variables)] #[allow(unused_variables)]
fn default_render(&self, assets: &mut PageAssets) -> Markup { fn default_render(&self, assets: &mut PageAssets) -> Markup {
html! {} html! {}

View file

@ -1,24 +1,22 @@
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use crate::response::page::{PageAssets, PageComponent, render_component}; use crate::response::page::{ArcComponent, PageAssets, render_component};
use std::sync::Arc;
#[derive(Clone)] #[derive(Clone)]
pub struct PageContainer(Vec<Arc<dyn PageComponent>>); pub struct PageContainer(Vec<ArcComponent>);
impl PageContainer { impl PageContainer {
pub fn new() -> Self { pub fn new() -> Self {
PageContainer(Vec::new()) PageContainer(Vec::new())
} }
pub fn new_with(component: impl PageComponent) -> Self { pub fn new_with(component: ArcComponent) -> Self {
let mut container = PageContainer::new(); let mut container = PageContainer::new();
container.add(component); container.add(component);
container container
} }
pub fn add(&mut self, component: impl PageComponent) { pub fn add(&mut self, component: ArcComponent) {
self.0.push(Arc::new(component)); self.0.push(component);
} }
pub fn render(&self, assets: &mut PageAssets) -> Markup { pub fn render(&self, assets: &mut PageAssets) -> Markup {

View file

@ -7,7 +7,7 @@ pub use assets::{
}; };
mod component; mod component;
pub use component::PageComponent; pub use component::{ArcComponent, PageComponent};
mod container; mod container;
pub use container::PageContainer; pub use container::PageContainer;

View file

@ -1,7 +1,7 @@
use crate::{Lazy, app, trace}; use crate::{Lazy, app, trace};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html}; use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html};
use crate::response::page::{PageAssets, PageComponent, PageContainer}; use crate::response::page::*;
use std::sync::RwLock; use std::sync::RwLock;
use std::collections::HashMap; use std::collections::HashMap;
@ -100,7 +100,7 @@ impl<'a> Page<'a> {
pub fn add_to( pub fn add_to(
&mut self, &mut self,
region: &'a str, region: &'a str,
component: impl PageComponent component: ArcComponent
) -> &mut Self { ) -> &mut Self {
if let Some(regions) = self.regions.get_mut(region) { if let Some(regions) = self.regions.get_mut(region) {
regions.add(component); regions.add(component);
@ -205,7 +205,7 @@ pub fn render_component(
} }
} }
pub fn add_component_to(region: &'static str, component: impl PageComponent) { pub fn add_component_to(region: &'static str, component: ArcComponent) {
let mut hmap = COMPONENTS.write().unwrap(); let mut hmap = COMPONENTS.write().unwrap();
if let Some(regions) = hmap.get_mut(region) { if let Some(regions) = hmap.get_mut(region) {
regions.add(component); regions.add(component);

View file

@ -104,7 +104,7 @@ pub trait ThemeTrait: Send + Sync {
div { div {
h1 { (s) } h1 { (s) }
} }
})) }).arc())
.render() .render()
} }
} }