Modifica el renderizado de componentes

La función default_render() se implementa usando llamadas a funciones,
nunca usando campos internos de la estructura. Esto es así para dar las
mismas opciones a los temas que alteren el render de un componente dado.
This commit is contained in:
Manuel Cillero 2022-03-29 22:53:17 +02:00
parent 5aee113f54
commit 68d79f6090
23 changed files with 335 additions and 295 deletions

View file

@ -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")

View file

@ -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<String> {
self.id.option()
}
pub fn title(&self) -> &str {
self.title.value()
pub fn title(&self) -> &Option<String> {
self.title.option()
}
pub fn html(&self) -> &Vec<Markup> {
&self.html
}
pub fn template(&self) -> &str {

View file

@ -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<Markup> {
&self.html
}
pub fn template(&self) -> &str {
self.template.as_str()
}

View file

@ -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<String> {
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 {

View file

@ -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<String> {
self.name.option()
}
pub fn has_autofocus(&self) -> bool {
self.autofocus.has_value()
pub fn value(&self) -> &Option<String> {
self.value.option()
}
pub fn is_disabled(&self) -> bool {
self.disabled.has_value()
pub fn autofocus(&self) -> &Option<String> {
self.autofocus.option()
}
pub fn disabled(&self) -> &Option<String> {
self.disabled.option()
}
pub fn template(&self) -> &str {

View file

@ -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<String> {
self.name.option()
}
pub fn value(&self) -> &str {
self.value.value()
pub fn value(&self) -> &Option<String> {
self.value.option()
}
pub fn label(&self) -> &str {
self.label.value()
pub fn label(&self) -> &Option<String> {
self.label.option()
}
pub fn placeholder(&self) -> &str {
self.placeholder.value()
pub fn placeholder(&self) -> &Option<String> {
self.placeholder.option()
}
pub fn has_autofocus(&self) -> bool {
self.autofocus.has_value()
pub fn autofocus(&self) -> &Option<String> {
self.autofocus.option()
}
pub fn has_autocomplete(&self) -> bool {
!self.autocomplete.has_value()
pub fn autocomplete(&self) -> &Option<String> {
self.autocomplete.option()
}
pub fn is_disabled(&self) -> bool {
self.disabled.has_value()
pub fn disabled(&self) -> &Option<String> {
self.disabled.option()
}
pub fn is_readonly(&self) -> bool {
self.readonly.has_value()
pub fn readonly(&self) -> &Option<String> {
self.readonly.option()
}
pub fn is_required(&self) -> bool {
self.required.has_value()
pub fn required(&self) -> &Option<String> {
self.required.option()
}
pub fn help_text(&self) -> &str {
self.help_text.value()
pub fn help_text(&self) -> &Option<String> {
self.help_text.option()
}
pub fn template(&self) -> &str {

View file

@ -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<String> {
self.id.option()
}
pub fn action(&self) -> &str {
self.action.value()
pub fn action(&self) -> &Option<String> {
self.action.option()
}
pub fn method(&self) -> &str {
match &self.method {
FormMethod::Get => "get",
FormMethod::Post => "post"
}
pub fn charset(&self) -> &Option<String> {
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 {

View file

@ -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<String> {
self.name.option()
}
pub fn value(&self) -> &str {
self.value.value()
pub fn value(&self) -> &Option<String> {
self.value.option()
}
}

View file

@ -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<String> {
self.name.option()
}
pub fn label(&self) -> &str {
self.label.value()
pub fn value(&self) -> &Option<String> {
self.value.option()
}
pub fn label(&self) -> &Option<String> {
self.label.option()
}
pub fn size(&self) -> Option<u16> {
@ -272,32 +274,32 @@ impl Input {
self.maxlength
}
pub fn placeholder(&self) -> &str {
self.placeholder.value()
pub fn placeholder(&self) -> &Option<String> {
self.placeholder.option()
}
pub fn has_autofocus(&self) -> bool {
self.autofocus.has_value()
pub fn autofocus(&self) -> &Option<String> {
self.autofocus.option()
}
pub fn has_autocomplete(&self) -> bool {
!self.autocomplete.has_value()
pub fn autocomplete(&self) -> &Option<String> {
self.autocomplete.option()
}
pub fn is_disabled(&self) -> bool {
self.disabled.has_value()
pub fn disabled(&self) -> &Option<String> {
self.disabled.option()
}
pub fn is_readonly(&self) -> bool {
self.readonly.has_value()
pub fn readonly(&self) -> &Option<String> {
self.readonly.option()
}
pub fn is_required(&self) -> bool {
self.required.has_value()
pub fn required(&self) -> &Option<String> {
self.required.option()
}
pub fn help_text(&self) -> &str {
self.help_text.value()
pub fn help_text(&self) -> &Option<String> {
self.help_text.option()
}
pub fn template(&self) -> &str {

View file

@ -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};

View file

@ -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<String> {
self.id.option()
}
pub fn classes(&self) -> &Option<String> {
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 {

View file

@ -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<String> {
self.id.option()
}
pub fn classes(&self) -> &Option<String> {
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 {

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
pub struct Image {
renderable: fn() -> bool,
weight : i8,
source : Option<String>,
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<String> {
self.source.option()
}
pub fn template(&self) -> &str {
self.template.as_str()
}

View file

@ -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<MenuItemType>,
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<String> {
self.id.option()
}
pub fn template(&self) -> &str {

View file

@ -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};

View file

@ -140,7 +140,7 @@ fn just_visiting() -> Chunck {
span {
(l("visiting_title"))
}
br {}
br;
(l("visiting_subtitle"))
}
p { (l("visiting_text1")) }

View file

@ -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<String> {
&self.0
}

View file

@ -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<String> {
&self.0
}

View file

@ -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;
// -----------------------------------------------------------------------------

View file

@ -3,6 +3,7 @@
// Macros.
pub use crate::{
args,
concat_string,
theme_static_files,
};

View file

@ -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>) -> 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())
}
}
}
}

View file

@ -122,20 +122,20 @@ impl<'a> Page<'a> {
// Page GETTERS.
pub fn language(&self) -> &str {
self.language.value()
pub fn language(&self) -> &Option<String> {
self.language.option()
}
pub fn direction(&self) -> &str {
self.direction.value()
pub fn direction(&self) -> &Option<String> {
self.direction.option()
}
pub fn title(&self) -> &str {
self.title.value()
pub fn title(&self) -> &Option<String> {
self.title.option()
}
pub fn description(&self) -> &str {
self.description.value()
pub fn description(&self) -> &Option<String> {
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)
}

View file

@ -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";