diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 7ef2ecf3..dd0b362b 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -40,7 +40,7 @@ fn form_login() -> impl PageComponent { .with_help_text(t("username_help", &args![ "app" => SETTINGS.app.name.to_owned() ]).as_str()) - .autofocus(true) + .with_autofocus(true) ) .add(form::Input::password() .with_name("pass") diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 5e5a7159..976c27bc 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -31,15 +31,15 @@ impl PageComponent for Block { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let id = assets.serial_id(self.name(), self.id.value()); - let title = self.title.value(); + let id = assets.serial_id(self.name(), self.id()); html! { div id=(id) class="block" { - @if !title.is_empty() { - h2 class="block-title" { (title) } + @match self.title() { + Some(title) => h2 class="block-title" { (title) }, + None => {} } div class="block-body" { - @for html in self.html.iter() { + @for html in self.html().iter() { (*html) } } @@ -88,12 +88,16 @@ impl Block { // Block GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } - pub fn title(&self) -> &str { - self.title.value() + pub fn title(&self) -> &Option { + self.title.option() + } + + pub fn html(&self) -> &Vec { + &self.html } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index b03ac0c8..532584fc 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -28,7 +28,7 @@ impl PageComponent for Chunck { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - @for html in self.html.iter() { + @for html in self.html().iter() { (*html) } } @@ -65,6 +65,10 @@ impl Chunck { // Chunck GETTERS. + pub fn html(&self) -> &Vec { + &self.html + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index e76b48b4..cba905d6 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -1,12 +1,12 @@ use crate::prelude::*; -enum ContainerType { Header, Footer, Main, Section, Wrapper } +pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable: fn() -> bool, weight : i8, - id : OptIden, container : ContainerType, + id : OptIden, components: PageContainer, template : String, } @@ -17,8 +17,8 @@ impl PageComponent for Container { Container { renderable: always, weight : 0, - id : OptIden::none(), container : ContainerType::Wrapper, + id : OptIden::none(), components: PageContainer::new(), template : "default".to_owned(), } @@ -33,38 +33,38 @@ impl PageComponent for Container { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - match self.container { + match self.container_type() { ContainerType::Header => html! { - header id=[&self.id.option()] class="header" { + header id=[self.id()] class="header" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Footer => html! { - footer id=[&self.id.option()] class="footer" { + footer id=[self.id()] class="footer" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Main => html! { - main id=[&self.id.option()] class="main" { + main id=[self.id()] class="main" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Section => html! { - section id=[&self.id.option()] class="section" { + section id=[self.id()] class="section" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, _ => html! { - div id=[&self.id.option()] class="container" { - (self.components.render(assets)) + div id=[self.id()] class="container" { + (self.render_components(assets)) } } } @@ -126,13 +126,23 @@ impl Container { // Container GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn container_type(&self) -> &ContainerType { + &self.container + } + + pub fn id(&self) -> &Option { + self.id.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Container EXTRAS. + + pub fn render_components(&self, assets: &mut PageAssets) -> Markup { + html! { (self.components.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index fa9794f2..fbe25738 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -enum ButtonType {Button, Reset, Submit} +pub enum ButtonType {Button, Reset, Submit} pub struct Button { renderable : fn() -> bool, @@ -37,26 +37,29 @@ impl PageComponent for Button { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (button_type, button_class) = match &self.button_type { + let (button_type, button_class) = match self.button_type() { ButtonType::Button => ("button", "btn btn-primary form-button"), ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), - ButtonType::Submit => ("submit", "btn btn-primary form-submit") + ButtonType::Submit => ("submit", "btn btn-primary form-submit"), }; - let id = match &self.name.option() { - Some(name) => Some(format!("edit-{}", name)), + let id = match self.name() { + Some(name) => Some(concat_string!("edit-", name)), _ => None }; html! { button type=(button_type) - id=[&id] + id=[id] class=(button_class) - name=[&self.name.option()] - value=[&self.value.option()] - autofocus=[&self.autofocus.option()] - disabled=[&self.disabled.option()] + name=[self.name()] + value=[self.value()] + autofocus=[self.autofocus()] + disabled=[self.disabled()] { - (self.value.value()) + @match self.value() { + Some(value) => { (value) }, + None => {}, + } } } } @@ -102,7 +105,7 @@ impl Button { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -110,7 +113,7 @@ impl Button { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -125,20 +128,24 @@ impl Button { // Button GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn button_type(&self) -> &ButtonType { + &self.button_type } - pub fn value(&self) -> &str { - self.value.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn value(&self) -> &Option { + self.value.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() + } + + pub fn disabled(&self) -> &Option { + self.disabled.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 5e42bc6b..906f5bbc 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -45,10 +45,10 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (class, id) = match self.name.option() { + let (class, id) = match self.name() { Some(name) => ( - format!("form-item form-item-{} form-type-date", name), - Some(format!("edit-{}", name)) + concat_string!("form-item form-item-", name, " form-type-date"), + Some(concat_string!("edit-", name)) ), None => ( "form-item form-type-date".to_owned(), @@ -57,35 +57,33 @@ impl PageComponent for Date { }; html! { div class=(class) { - @if self.label.has_value() { - label class="form-label" for=[&id] { - (self.label.value()) " " - @if self.required.has_value() { - span + @match self.label() { + Some(label) => label class="form-label" for=[&id] { + (label) " " + @match self.required() { + Some(_) => span class="form-required" - title="Este campo es obligatorio." - { - "*" - } " " + title="Este campo es obligatorio." { "*" } " ", + None => {} } - } + }, + None => {} } input type="date" - id=[&id] + id=[id] class="form-control" - name=[&self.name.option()] - value=[&self.value.option()] - placeholder=[&self.placeholder.option()] - autofocus=[&self.autofocus.option()] - autocomplete=[&self.autocomplete.option()] - readonly=[&self.readonly.option()] - required=[&self.required.option()] - disabled=[&self.disabled.option()]; - @if self.help_text.has_value() { - div class="form-text" { - (self.help_text.value()) - } + name=[self.name()] + value=[self.value()] + placeholder=[self.placeholder()] + autofocus=[self.autofocus()] + autocomplete=[self.autocomplete()] + readonly=[self.readonly()] + required=[self.required()] + disabled=[self.disabled()]; + @match self.help_text() { + Some(help_text) => div class="form-text" { (help_text) }, + None => {} } } } @@ -126,7 +124,7 @@ impl Date { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -134,7 +132,7 @@ impl Date { self } - pub fn autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -142,7 +140,7 @@ impl Date { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -150,7 +148,7 @@ impl Date { self } - pub fn readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -158,7 +156,7 @@ impl Date { self } - pub fn required(mut self, toggle: bool) -> Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -178,44 +176,44 @@ impl Date { // Date GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn value(&self) -> &str { - self.value.value() + pub fn value(&self) -> &Option { + self.value.option() } - pub fn label(&self) -> &str { - self.label.value() + pub fn label(&self) -> &Option { + self.label.option() } - pub fn placeholder(&self) -> &str { - self.placeholder.value() + pub fn placeholder(&self) -> &Option { + self.placeholder.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() } - pub fn has_autocomplete(&self) -> bool { - !self.autocomplete.has_value() + pub fn autocomplete(&self) -> &Option { + self.autocomplete.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn disabled(&self) -> &Option { + self.disabled.option() } - pub fn is_readonly(&self) -> bool { - self.readonly.has_value() + pub fn readonly(&self) -> &Option { + self.readonly.option() } - pub fn is_required(&self) -> bool { - self.required.has_value() + pub fn required(&self) -> &Option { + self.required.option() } - pub fn help_text(&self) -> &str { - self.help_text.value() + pub fn help_text(&self) -> &Option { + self.help_text.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 385dd369..5ecea5e0 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -7,8 +7,8 @@ pub struct Form { weight : i8, id : OptIden, action : OptAttr, - method : FormMethod, charset : OptAttr, + method : FormMethod, elements : PageContainer, template : String, } @@ -21,8 +21,8 @@ impl PageComponent for Form { weight : 0, id : OptIden::none(), action : OptAttr::none(), - method : FormMethod::Post, charset : OptAttr::some("UTF-8"), + method : FormMethod::Post, elements : PageContainer::new(), template : "default".to_owned(), } @@ -37,19 +37,19 @@ impl PageComponent for Form { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let method = match self.method { + let method = match self.method() { FormMethod::Get => None, FormMethod::Post => Some("post".to_owned()) }; html! { form - id=[&self.id.option()] - action=[&self.action.option()] + id=[self.id()] + action=[self.action()] method=[method] - accept-charset=[&self.charset.option()] + accept-charset=[self.charset()] { div { - (self.elements.render(assets)) + (self.render_elements(assets)) } } } @@ -80,13 +80,13 @@ impl Form { self } - pub fn with_method(mut self, method: FormMethod) -> Self { - self.method = method; + pub fn with_charset(mut self, charset: &str) -> Self { + self.charset.with_value(charset); self } - pub fn with_charset(mut self, charset: &str) -> Self { - self.charset.with_value(charset); + pub fn with_method(mut self, method: FormMethod) -> Self { + self.method = method; self } @@ -102,28 +102,31 @@ impl Form { // Form GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } - pub fn action(&self) -> &str { - self.action.value() + pub fn action(&self) -> &Option { + self.action.option() } - pub fn method(&self) -> &str { - match &self.method { - FormMethod::Get => "get", - FormMethod::Post => "post" - } + pub fn charset(&self) -> &Option { + self.charset.option() } - pub fn charset(&self) -> &str { - self.charset.value() + pub fn method(&self) -> &FormMethod { + &self.method } pub fn template(&self) -> &str { self.template.as_str() } + + // Form EXTRAS. + + pub fn render_elements(&self, assets: &mut PageAssets) -> Markup { + html! { (self.elements.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index b7eca015..636d034e 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -1,18 +1,18 @@ use crate::prelude::*; pub struct Hidden { - weight : i8, - name : OptIden, - value : OptAttr, + weight: i8, + name : OptIden, + value : OptAttr, } impl PageComponent for Hidden { fn new() -> Self { Hidden { - weight : 0, - name : OptIden::none(), - value : OptAttr::none(), + weight: 0, + name : OptIden::none(), + value : OptAttr::none(), } } @@ -21,16 +21,12 @@ impl PageComponent for Hidden { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let id = match self.name.option() { - Some(name) => Some(format!("value-{}", name)), + let id = match self.name() { + Some(name) => Some(concat_string!("value-", name)), _ => None }; html! { - input - type="hidden" - id=[&id] - name=[&self.name.option()] - value=[&self.value.option()]; + input type="hidden" id=[id] name=[self.name()] value=[self.value()]; } } } @@ -60,11 +56,11 @@ impl Hidden { // Hidden GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn value(&self) -> &str { - self.value.value() + pub fn value(&self) -> &Option { + self.value.option() } } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 7622fd08..7dded20f 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -enum InputType {Email, Password, Search, Telephone, Textfield, Url} +pub enum InputType {Email, Password, Search, Telephone, Textfield, Url} pub struct Input { renderable : fn() -> bool, @@ -55,7 +55,7 @@ impl PageComponent for Input { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (type_input, type_class) = match &self.input_type { + let (type_input, type_class) = match self.input_type() { InputType::Email => ("email", "form-type-email"), InputType::Password => ("password", "form-type-password"), InputType::Search => ("search", "form-type-search"), @@ -63,50 +63,48 @@ impl PageComponent for Input { InputType::Textfield => ("text", "form-type-textfield"), InputType::Url => ("url", "form-type-url") }; - let (class, id) = match &self.name.option() { + let (class, id) = match self.name() { Some(name) => ( - format!("form-item form-item-{} {}", name, type_class), - Some(format!("edit-{}", name)) + concat_string!("form-item form-item-", name, " ", type_class), + Some(concat_string!("edit-", name)) ), None => ( - format!("form-item {}", type_class), + concat_string!("form-item ", type_class), None ) }; html! { div class=(class) { - @if self.label.has_value() { - label class="form-label" for=[&id] { - (self.label.value()) " " - @if self.required.has_value() { - span + @match self.label() { + Some(label) => label class="form-label" for=[&id] { + (label) " " + @match self.required() { + Some(_) => span class="form-required" - title="Este campo es obligatorio." - { - "*" - } " " + title="Este campo es obligatorio." { "*" } " ", + None => {} } - } + }, + None => {} } input type=(type_input) - id=[&id] + id=[id] class="form-control" - name=[&self.name.option()] - value=[&self.value.option()] - size=[self.size] - minlength=[self.minlength] - maxlength=[self.maxlength] - placeholder=[&self.placeholder.option()] - autofocus=[&self.autofocus.option()] - autocomplete=[&self.autocomplete.option()] - readonly=[&self.readonly.option()] - required=[&self.required.option()] - disabled=[&self.disabled.option()]; - @if self.help_text.has_value() { - div class="form-text" { - (self.help_text.value()) - } + name=[self.name()] + value=[self.value()] + size=[self.size()] + minlength=[self.minlength()] + maxlength=[self.maxlength()] + placeholder=[self.placeholder()] + autofocus=[self.autofocus()] + autocomplete=[self.autocomplete()] + readonly=[self.readonly()] + required=[self.required()] + disabled=[self.disabled()]; + @match self.help_text() { + Some(help_text) => div class="form-text" { (help_text) }, + None => {} } } } @@ -196,7 +194,7 @@ impl Input { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -204,7 +202,7 @@ impl Input { self } - pub fn autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -212,7 +210,7 @@ impl Input { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -220,7 +218,7 @@ impl Input { self } - pub fn readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -228,7 +226,7 @@ impl Input { self } - pub fn required(mut self, toggle: bool) -> Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -248,16 +246,20 @@ impl Input { // Input GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn input_type(&self) -> &InputType { + &self.input_type } - pub fn value(&self) -> &str { - self.value.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn label(&self) -> &str { - self.label.value() + pub fn value(&self) -> &Option { + self.value.option() + } + + pub fn label(&self) -> &Option { + self.label.option() } pub fn size(&self) -> Option { @@ -272,32 +274,32 @@ impl Input { self.maxlength } - pub fn placeholder(&self) -> &str { - self.placeholder.value() + pub fn placeholder(&self) -> &Option { + self.placeholder.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() } - pub fn has_autocomplete(&self) -> bool { - !self.autocomplete.has_value() + pub fn autocomplete(&self) -> &Option { + self.autocomplete.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn disabled(&self) -> &Option { + self.disabled.option() } - pub fn is_readonly(&self) -> bool { - self.readonly.has_value() + pub fn readonly(&self) -> &Option { + self.readonly.option() } - pub fn is_required(&self) -> bool { - self.required.has_value() + pub fn required(&self) -> &Option { + self.required.option() } - pub fn help_text(&self) -> &str { - self.help_text.value() + pub fn help_text(&self) -> &Option { + self.help_text.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/base/component/form/mod.rs index 4e10d476..23b965e9 100644 --- a/pagetop/src/base/component/form/mod.rs +++ b/pagetop/src/base/component/form/mod.rs @@ -2,10 +2,10 @@ mod form; pub use form::{Form, FormMethod}; mod input; -pub use input::Input; +pub use input::{Input, InputType}; mod hidden; pub use hidden::Hidden; mod date; pub use date::Date; mod button; -pub use button::Button; +pub use button::{Button, ButtonType}; diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 19eb577b..6d3a7b19 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -32,8 +32,8 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class=[&self.classes.option()] { - (self.components.render(assets)) + div id=[self.id()] class=[self.classes()] { + (self.render_components(assets)) } } } @@ -75,13 +75,23 @@ impl Column { // Column GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Column EXTRAS. + + pub fn render_components(&self, assets: &mut PageAssets) -> Markup { + html! { (self.components.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 53719e3f..b1bb2c24 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -32,8 +32,8 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class=[&self.classes.option()] { - (self.columns.render(assets)) + div id=[self.id()] class=[self.classes()] { + (self.render_columns(assets)) } } } @@ -75,13 +75,23 @@ impl Row { // Row GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Row EXTRAS. + + pub fn render_columns(&self, assets: &mut PageAssets) -> Markup { + html! { (self.columns.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index b330b374..799aab63 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub struct Image { renderable: fn() -> bool, weight : i8, - source : Option, + source : OptAttr, template : String, } @@ -13,7 +13,7 @@ impl PageComponent for Image { Image { renderable: always, weight : 0, - source : None, + source : OptAttr::none(), template : "default".to_owned(), } } @@ -28,7 +28,7 @@ impl PageComponent for Image { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - img src=[&self.source] class="img-fluid" {} + img src=[self.source()] class="img-fluid"; } } } @@ -36,9 +36,7 @@ impl PageComponent for Image { impl Image { pub fn image(source: &str) -> Self { - let mut i = Image::new(); - i.source = Some(source.to_owned()); - i + Image::new().with_source(source) } // Image BUILDER. @@ -53,6 +51,11 @@ impl Image { self } + pub fn with_source(mut self, source: &str) -> Self { + self.source.with_value(source); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -60,6 +63,10 @@ impl Image { // Image GETTERS. + pub fn source(&self) -> &Option { + self.source.option() + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 0f529874..253cd3d8 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,12 +1,13 @@ use crate::prelude::*; -enum MenuItemType { +pub enum MenuItemType { Label(String), Link(String, String), LinkBlank(String, String), Html(Markup), Separator, Submenu(String, Menu), + Void, } // ----------------------------------------------------------------------------- @@ -16,7 +17,7 @@ enum MenuItemType { pub struct MenuItem { renderable: fn() -> bool, weight : i8, - item_type : Option, + item_type : MenuItemType, } impl PageComponent for MenuItem { @@ -25,7 +26,7 @@ impl PageComponent for MenuItem { MenuItem { renderable: always, weight : 0, - item_type : None, + item_type : MenuItemType::Void, } } @@ -38,22 +39,22 @@ impl PageComponent for MenuItem { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - match &self.item_type { - Some(MenuItemType::Label(label)) => html! { + match self.item_type() { + MenuItemType::Label(label) => html! { li class="label" { a href="#" { (label) } } }, - Some(MenuItemType::Link(label, path)) => html! { + MenuItemType::Link(label, path) => html! { li class="link" { a href=(path) { (label) } } }, - Some(MenuItemType::LinkBlank(label, path)) => html! { + MenuItemType::LinkBlank(label, path) => html! { li class="link_blank" { a href=(path) target="_blank" { (label) } } }, - Some(MenuItemType::Html(html)) => html! { + MenuItemType::Html(html) => html! { li class="html" { (*html) } }, - Some(MenuItemType::Submenu(label, menu)) => html! { + MenuItemType::Submenu(label, menu) => html! { li class="submenu" { a href="#" { (label) } ul { @@ -61,10 +62,10 @@ impl PageComponent for MenuItem { } } }, - Some(MenuItemType::Separator) => html! { + MenuItemType::Separator => html! { li class="separator" { } }, - None => html! {} + MenuItemType::Void => html! {}, } } } @@ -75,7 +76,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Label(label.to_owned())), + item_type : MenuItemType::Label(label.to_owned()), } } @@ -83,10 +84,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Link( + item_type : MenuItemType::Link( label.to_owned(), path.to_owned(), - )), + ), } } @@ -94,10 +95,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::LinkBlank( + item_type : MenuItemType::LinkBlank( label.to_owned(), path.to_owned(), - )), + ), } } @@ -105,7 +106,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Html(html)), + item_type : MenuItemType::Html(html), } } @@ -113,7 +114,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Separator), + item_type : MenuItemType::Separator, } } @@ -121,10 +122,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Submenu( + item_type : MenuItemType::Submenu( label.to_owned(), menu - )), + ), } } @@ -139,6 +140,12 @@ impl MenuItem { self.weight = weight; self } + + // MenuItem GETTERS. + + pub fn item_type(&self) -> &MenuItemType { + &self.item_type + } } // ----------------------------------------------------------------------------- @@ -186,7 +193,7 @@ impl PageComponent for Menu { )) .add_jquery(); - let id = assets.serial_id(self.name(), self.id.value()); + let id = assets.serial_id(self.name(), self.id()); html! { ul id=(id) class="sm sm-clean" { (self.render_items(assets)) @@ -232,8 +239,8 @@ impl Menu { // Menu GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index 4619c937..b4e646b9 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -1,5 +1,5 @@ mod container; -pub use container::Container; +pub use container::{Container, ContainerType}; pub mod grid; @@ -10,7 +10,7 @@ pub use block::Block; mod image; pub use image::Image; mod menu; -pub use menu::{Menu, MenuItem}; +pub use menu::{Menu, MenuItem, MenuItemType}; pub mod form; pub use form::{Form, FormMethod}; diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index c9fc9cc0..489b6d3b 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -140,7 +140,7 @@ fn just_visiting() -> Chunck { span { (l("visiting_title")) } - br {} + br; (l("visiting_subtitle")) } p { (l("visiting_text1")) } diff --git a/pagetop/src/html/optattr.rs b/pagetop/src/html/optattr.rs index 3eed9aab..a76f33b7 100644 --- a/pagetop/src/html/optattr.rs +++ b/pagetop/src/html/optattr.rs @@ -19,17 +19,6 @@ impl OptAttr { }; } - pub fn value(&self) -> &str { - match &self.0 { - Some(value) => value.as_str(), - None => "", - } - } - - pub fn has_value(&self) -> bool { - self.0 != None - } - pub fn option(&self) -> &Option { &self.0 } diff --git a/pagetop/src/html/optiden.rs b/pagetop/src/html/optiden.rs index 93caf18a..ec46acf1 100644 --- a/pagetop/src/html/optiden.rs +++ b/pagetop/src/html/optiden.rs @@ -19,17 +19,6 @@ impl OptIden { }; } - pub fn value(&self) -> &str { - match &self.0 { - Some(id) => id.as_str(), - None => "", - } - } - - pub fn has_value(&self) -> bool { - self.0 != None - } - pub fn option(&self) -> &Option { &self.0 } diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 731271d3..42ad192a 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,8 +1,11 @@ +// Exports. + +pub use concat_string::concat_string; +pub use doc_comment::doc_comment; +pub use once_cell::sync::Lazy; + // Local. -pub(crate) use concat_string::concat_string; -pub(crate) use doc_comment::doc_comment; -pub(crate) use once_cell::sync::Lazy; pub(crate) use futures::executor::block_on as run_now; // ----------------------------------------------------------------------------- diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 7c2e9ef3..429c9449 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -3,6 +3,7 @@ // Macros. pub use crate::{ args, + concat_string, theme_static_files, }; diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index ffc566ea..3d42a06f 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, base}; +use crate::{Lazy, base, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; use crate::theme::*; @@ -289,18 +289,19 @@ impl PageAssets { // Assets EXTRAS. - pub fn serial_id(&mut self, prefix: &str, id: &str) -> String { - if id.is_empty() { - let prefix = prefix.trim().replace(" ", "_").to_lowercase(); - let prefix = if prefix.is_empty() { - "prefix".to_owned() - } else { - prefix - }; - self.id_counter += 1; - [prefix, self.id_counter.to_string()].join("-") - } else { - id.to_owned() + pub fn serial_id(&mut self, prefix: &str, id: &Option) -> String { + match id { + Some(id) => id.to_string(), + None => { + let prefix = prefix.trim().replace(" ", "_").to_lowercase(); + let prefix = if prefix.is_empty() { + "prefix".to_owned() + } else { + prefix + }; + self.id_counter += 1; + concat_string!(prefix, "-", self.id_counter.to_string()) + } } } } diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index fedf05e4..50ff3040 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -122,20 +122,20 @@ impl<'a> Page<'a> { // Page GETTERS. - pub fn language(&self) -> &str { - self.language.value() + pub fn language(&self) -> &Option { + self.language.option() } - pub fn direction(&self) -> &str { - self.direction.value() + pub fn direction(&self) -> &Option { + self.direction.option() } - pub fn title(&self) -> &str { - self.title.value() + pub fn title(&self) -> &Option { + self.title.option() } - pub fn description(&self) -> &str { - self.description.value() + pub fn description(&self) -> &Option { + self.description.option() } pub fn body_classes(&mut self) -> &str { @@ -165,7 +165,7 @@ impl<'a> Page<'a> { // Finalmente, renderizar la página. return Ok(html! { (DOCTYPE) - html lang=[&self.language.option()] dir=[&self.direction.option()] { + html lang=[self.language()] dir=[self.direction()] { (head) (body) } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 15f6566e..51b1d4c8 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,4 +1,4 @@ -use crate::app; +use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::response::page::{Favicon, Page, PageAssets, PageComponent}; @@ -28,22 +28,21 @@ pub trait ThemeTrait: Send + Sync { } fn render_page_head(&self, page: &mut Page) -> Markup { - let title = page.title(); - let title = if title.is_empty() { - SETTINGS.app.name.to_owned() - } else { - [SETTINGS.app.name.to_string(), title.to_string()].join(" | ") - }; - let description = page.description(); let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no"; html! { head { meta charset="utf-8"; - title { (title) } + @match page.title() { + Some(t) => title { + (concat_string!(SETTINGS.app.name, " | ", t)) + }, + None => title { (SETTINGS.app.name) } + } - @if !description.is_empty() { - meta name="description" content=(description); + @match page.description() { + Some(d) => meta name="description" content=(d);, + None => {} } meta http-equiv="X-UA-Compatible" content="IE=edge";