diff --git a/src/base/component/block.rs b/src/base/component/block.rs index 9ffe986d..4f658c9e 100644 --- a/src/base/component/block.rs +++ b/src/base/component/block.rs @@ -4,7 +4,7 @@ pub struct Block { renderable: fn() -> bool, weight : i8, id : Option, - title : String, + title : Option, markup : Vec, template : String, } @@ -16,9 +16,9 @@ impl PageComponent for Block { renderable: always, weight : 0, id : None, - title : "".to_string(), + title : None, markup : Vec::new(), - template : "default".to_string(), + template : "default".to_owned(), } } @@ -34,8 +34,8 @@ impl PageComponent for Block { let id = assets.serial_id(self.name(), self.id()); html! { div id=(id) class="block" { - @if !self.title.is_empty() { - h2 class="block-title" { (self.title) } + @if self.title != None { + h2 class="block-title" { (self.title()) } } div class="block-body" { @for markup in self.markup.iter() { @@ -71,7 +71,7 @@ impl Block { } pub fn with_title(mut self, title: &str) -> Self { - self.title = title.to_string(); + self.title = util::optional_str(title); self } @@ -81,18 +81,18 @@ impl Block { } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Block GETTERS. pub fn id(&self) -> &str { - util::assigned_value(&self.id) + util::assigned_str(&self.id) } pub fn title(&self) -> &str { - self.title.as_str() + util::assigned_str(&self.title) } pub fn template(&self) -> &str { diff --git a/src/base/component/chunck.rs b/src/base/component/chunck.rs index 8d4e956f..63cc20f7 100644 --- a/src/base/component/chunck.rs +++ b/src/base/component/chunck.rs @@ -14,7 +14,7 @@ impl PageComponent for Chunck { renderable: always, weight : 0, markup : Vec::new(), - template : "default".to_string(), + template : "default".to_owned(), } } @@ -59,7 +59,7 @@ impl Chunck { } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } diff --git a/src/base/component/container.rs b/src/base/component/container.rs index 61c08336..161bea78 100644 --- a/src/base/component/container.rs +++ b/src/base/component/container.rs @@ -20,7 +20,7 @@ impl PageComponent for Container { id : None, container : ContainerType::Wrapper, components: PageContainer::new(), - template : "default".to_string(), + template : "default".to_owned(), } } @@ -83,14 +83,14 @@ impl Container { } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Container GETTERS. pub fn id(&self) -> &str { - util::assigned_value(&self.id) + util::assigned_str(&self.id) } pub fn template(&self) -> &str { diff --git a/src/base/component/form/button.rs b/src/base/component/form/button.rs index c95eb3ec..c76c49dd 100644 --- a/src/base/component/form/button.rs +++ b/src/base/component/form/button.rs @@ -24,7 +24,7 @@ impl PageComponent for Button { value : None, autofocus : None, disabled : None, - template : "default".to_string(), + template : "default".to_owned(), } } @@ -101,13 +101,13 @@ impl Button { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_value(value); + self.value = util::optional_str(value); self } pub fn autofocus(mut self, toggle: bool) -> Self { self.autofocus = match toggle { - true => Some("autofocus".to_string()), + true => Some("autofocus".to_owned()), false => None }; self @@ -115,25 +115,25 @@ impl Button { pub fn disabled(mut self, toggle: bool) -> Self { self.disabled = match toggle { - true => Some("disabled".to_string()), + true => Some("disabled".to_owned()), false => None }; self } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Button GETTERS. pub fn name(&self) -> &str { - util::assigned_value(&self.name) + util::assigned_str(&self.name) } pub fn value(&self) -> &str { - util::assigned_value(&self.value) + util::assigned_str(&self.value) } pub fn has_autofocus(&self) -> bool { diff --git a/src/base/component/form/date.rs b/src/base/component/form/date.rs index b2839e8e..ccc6ab31 100644 --- a/src/base/component/form/date.rs +++ b/src/base/component/form/date.rs @@ -5,14 +5,14 @@ pub struct Date { weight : i8, name : Option, value : Option, - label : String, + label : Option, placeholder : Option, autofocus : Option, autocomplete: Option, disabled : Option, readonly : Option, required : Option, - help_text : String, + help_text : Option, template : String, } @@ -24,15 +24,15 @@ impl PageComponent for Date { weight : 0, name : None, value : None, - label : "".to_string(), + label : None, placeholder : None, autofocus : None, autocomplete: None, disabled : None, readonly : None, required : None, - help_text : "".to_string(), - template : "default".to_string(), + help_text : None, + template : "default".to_owned(), } } @@ -51,15 +51,15 @@ impl PageComponent for Date { Some(format!("edit-{}", name)) ), None => ( - "form-item form-type-date".to_string(), + "form-item form-type-date".to_owned(), None ) }; html! { div class=(class_item) { - @if !self.label.is_empty() { + @if self.label != None { label class="form-label" for=[&id_item] { - (self.label) " " + (self.label()) " " @if self.required != None { span class="form-required" @@ -82,9 +82,9 @@ impl PageComponent for Date { readonly=[&self.readonly] required=[&self.required] disabled=[&self.disabled]; - @if !self.help_text.is_empty() { + @if self.help_text != None { div class="form-text" { - (self.help_text) + (self.help_text()) } } } @@ -112,23 +112,23 @@ impl Date { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_value(value); + self.value = util::optional_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = label.to_string(); + self.label = util::optional_str(label); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_value(placeholder); + self.placeholder = util::optional_str(placeholder); self } pub fn autofocus(mut self, toggle: bool) -> Self { self.autofocus = match toggle { - true => Some("autofocus".to_string()), + true => Some("autofocus".to_owned()), false => None }; self @@ -137,14 +137,14 @@ impl Date { pub fn autocomplete(mut self, toggle: bool) -> Self { self.autocomplete = match toggle { true => None, - false => Some("off".to_string()) + false => Some("off".to_owned()) }; self } pub fn disabled(mut self, toggle: bool) -> Self { self.disabled = match toggle { - true => Some("disabled".to_string()), + true => Some("disabled".to_owned()), false => None }; self @@ -152,7 +152,7 @@ impl Date { pub fn readonly(mut self, toggle: bool) -> Self { self.readonly = match toggle { - true => Some("readonly".to_string()), + true => Some("readonly".to_owned()), false => None }; self @@ -160,38 +160,38 @@ impl Date { pub fn required(mut self, toggle: bool) -> Self { self.required = match toggle { - true => Some("required".to_string()), + true => Some("required".to_owned()), false => None }; self } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = help_text.to_string(); + self.help_text = util::optional_str(help_text); self } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Date GETTERS. pub fn name(&self) -> &str { - util::assigned_value(&self.name) + util::assigned_str(&self.name) } pub fn value(&self) -> &str { - util::assigned_value(&self.value) + util::assigned_str(&self.value) } pub fn label(&self) -> &str { - self.label.as_str() + util::assigned_str(&self.label) } pub fn placeholder(&self) -> &str { - util::assigned_value(&self.placeholder) + util::assigned_str(&self.placeholder) } pub fn has_autofocus(&self) -> bool { @@ -230,7 +230,7 @@ impl Date { } pub fn help_text(&self) -> &str { - self.help_text.as_str() + util::assigned_str(&self.help_text) } pub fn template(&self) -> &str { diff --git a/src/base/component/form/form.rs b/src/base/component/form/form.rs index 6f73469d..63eace0c 100644 --- a/src/base/component/form/form.rs +++ b/src/base/component/form/form.rs @@ -22,9 +22,9 @@ impl PageComponent for Form { id : None, action : None, method : FormMethod::Post, - charset : Some("UTF-8".to_string()), + charset : Some("UTF-8".to_owned()), elements : PageContainer::new(), - template : "default".to_string(), + template : "default".to_owned(), } } @@ -39,7 +39,7 @@ impl PageComponent for Form { fn default_render(&self, assets: &mut PageAssets) -> Markup { let method = match self.method { FormMethod::Get => None, - FormMethod::Post => Some("post".to_string()) + FormMethod::Post => Some("post".to_owned()) }; html! { form @@ -76,7 +76,7 @@ impl Form { } pub fn with_action(mut self, action: &str) -> Self { - self.action = util::optional_value(action); + self.action = util::optional_str(action); self } @@ -86,7 +86,7 @@ impl Form { } pub fn with_charset(mut self, charset: &str) -> Self { - self.charset = util::optional_value(charset); + self.charset = util::optional_str(charset); self } @@ -96,18 +96,18 @@ impl Form { } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Form GETTERS. pub fn id(&self) -> &str { - util::assigned_value(&self.id) + util::assigned_str(&self.id) } pub fn action(&self) -> &str { - util::assigned_value(&self.action) + util::assigned_str(&self.action) } pub fn method(&self) -> &str { @@ -118,7 +118,7 @@ impl Form { } pub fn charset(&self) -> &str { - util::assigned_value(&self.charset) + util::assigned_str(&self.charset) } pub fn template(&self) -> &str { diff --git a/src/base/component/form/hidden.rs b/src/base/component/form/hidden.rs index 57b4b34f..9ac0a4f9 100644 --- a/src/base/component/form/hidden.rs +++ b/src/base/component/form/hidden.rs @@ -54,17 +54,17 @@ impl Hidden { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_value(value); + self.value = util::optional_str(value); self } // Hidden GETTERS. pub fn name(&self) -> &str { - util::assigned_value(&self.name) + util::assigned_str(&self.name) } pub fn value(&self) -> &str { - util::assigned_value(&self.value) + util::assigned_str(&self.value) } } diff --git a/src/base/component/form/input.rs b/src/base/component/form/input.rs index 82c0bda3..884d2232 100644 --- a/src/base/component/form/input.rs +++ b/src/base/component/form/input.rs @@ -8,7 +8,7 @@ pub struct Input { input_type : InputType, name : Option, value : Option, - label : String, + label : Option, size : Option, minlength : Option, maxlength : Option, @@ -18,7 +18,7 @@ pub struct Input { disabled : Option, readonly : Option, required : Option, - help_text : String, + help_text : Option, template : String, } @@ -31,7 +31,7 @@ impl PageComponent for Input { input_type : InputType::Textfield, name : None, value : None, - label : "".to_string(), + label : None, size : Some(60), minlength : None, maxlength : Some(128), @@ -41,8 +41,8 @@ impl PageComponent for Input { disabled : None, readonly : None, required : None, - help_text : "".to_string(), - template : "default".to_string(), + help_text : None, + template : "default".to_owned(), } } @@ -75,9 +75,9 @@ impl PageComponent for Input { }; html! { div class=(class_item) { - @if !self.label.is_empty() { + @if self.label != None { label class="form-label" for=[&id_item] { - (self.label) " " + (self.label()) " " @if self.required != None { span class="form-required" @@ -103,9 +103,9 @@ impl PageComponent for Input { readonly=[&self.readonly] required=[&self.required] disabled=[&self.disabled]; - @if !self.help_text.is_empty() { + @if self.help_text != None { div class="form-text" { - (self.help_text) + (self.help_text()) } } } @@ -167,12 +167,12 @@ impl Input { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_value(value); + self.value = util::optional_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = label.to_string(); + self.label = util::optional_str(label); self } @@ -192,13 +192,13 @@ impl Input { } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_value(placeholder); + self.placeholder = util::optional_str(placeholder); self } pub fn autofocus(mut self, toggle: bool) -> Self { self.autofocus = match toggle { - true => Some("autofocus".to_string()), + true => Some("autofocus".to_owned()), false => None }; self @@ -207,14 +207,14 @@ impl Input { pub fn autocomplete(mut self, toggle: bool) -> Self { self.autocomplete = match toggle { true => None, - false => Some("off".to_string()) + false => Some("off".to_owned()) }; self } pub fn disabled(mut self, toggle: bool) -> Self { self.disabled = match toggle { - true => Some("disabled".to_string()), + true => Some("disabled".to_owned()), false => None }; self @@ -222,7 +222,7 @@ impl Input { pub fn readonly(mut self, toggle: bool) -> Self { self.readonly = match toggle { - true => Some("readonly".to_string()), + true => Some("readonly".to_owned()), false => None }; self @@ -230,34 +230,34 @@ impl Input { pub fn required(mut self, toggle: bool) -> Self { self.required = match toggle { - true => Some("required".to_string()), + true => Some("required".to_owned()), false => None }; self } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = help_text.to_string(); + self.help_text = util::optional_str(help_text); self } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Input GETTERS. pub fn name(&self) -> &str { - util::assigned_value(&self.name) + util::assigned_str(&self.name) } pub fn value(&self) -> &str { - util::assigned_value(&self.value) + util::assigned_str(&self.value) } pub fn label(&self) -> &str { - self.label.as_str() + util::assigned_str(&self.label) } pub fn size(&self) -> Option { @@ -273,7 +273,7 @@ impl Input { } pub fn placeholder(&self) -> &str { - util::assigned_value(&self.placeholder) + util::assigned_str(&self.placeholder) } pub fn has_autofocus(&self) -> bool { @@ -312,7 +312,7 @@ impl Input { } pub fn help_text(&self) -> &str { - self.help_text.as_str() + util::assigned_str(&self.help_text) } pub fn template(&self) -> &str { diff --git a/src/base/component/menu.rs b/src/base/component/menu.rs index 0f44fad5..d3cdb6b8 100644 --- a/src/base/component/menu.rs +++ b/src/base/component/menu.rs @@ -75,7 +75,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Label(label.to_string())), + item_type : Some(MenuItemType::Label(label.to_owned())), } } @@ -84,8 +84,8 @@ impl MenuItem { renderable: always, weight : 0, item_type : Some(MenuItemType::Link( - label.to_string(), - path.to_string(), + label.to_owned(), + path.to_owned(), )), } } @@ -95,8 +95,8 @@ impl MenuItem { renderable: always, weight : 0, item_type : Some(MenuItemType::LinkBlank( - label.to_string(), - path.to_string(), + label.to_owned(), + path.to_owned(), )), } } @@ -122,7 +122,7 @@ impl MenuItem { renderable: always, weight : 0, item_type : Some(MenuItemType::Submenu( - label.to_string(), + label.to_owned(), menu )), } @@ -161,7 +161,7 @@ impl PageComponent for Menu { weight : 0, id : None, items : PageContainer::new(), - template : "default".to_string(), + template : "default".to_owned(), } } @@ -226,14 +226,14 @@ impl Menu { } pub fn using_template(mut self, template: &str) -> Self { - self.template = template.to_string(); + self.template = template.to_owned(); self } // Menu GETTERS. pub fn id(&self) -> &str { - util::assigned_value(&self.id) + util::assigned_str(&self.id) } pub fn template(&self) -> &str { diff --git a/src/base/module/admin/mod.rs b/src/base/module/admin/mod.rs index 5991d4f0..0bb1202d 100644 --- a/src/base/module/admin/mod.rs +++ b/src/base/module/admin/mod.rs @@ -15,8 +15,8 @@ impl Module for AdminModule { l("module_fullname") } - fn description(&self) -> String { - l("module_description") + fn description(&self) -> Option { + Some(l("module_description")) } fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { diff --git a/src/base/module/homepage/mod.rs b/src/base/module/homepage/mod.rs index 386b6716..de4b98ce 100644 --- a/src/base/module/homepage/mod.rs +++ b/src/base/module/homepage/mod.rs @@ -13,8 +13,8 @@ impl Module for HomepageModule { l("module_fullname") } - fn description(&self) -> String { - l("module_description") + fn description(&self) -> Option { + Some(l("module_description")) } fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { diff --git a/src/base/module/user/mod.rs b/src/base/module/user/mod.rs index bbb3ee93..73ab7d16 100644 --- a/src/base/module/user/mod.rs +++ b/src/base/module/user/mod.rs @@ -13,8 +13,8 @@ impl Module for UserModule { l("module_fullname") } - fn description(&self) -> String { - l("module_description") + fn description(&self) -> Option { + Some(l("module_description")) } fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { @@ -29,7 +29,7 @@ fn form_login() -> impl PageComponent { .with_name("name") .with_label(l("username").as_str()) .with_help_text(t("username_help", &args![ - "app" => SETTINGS.app.name.to_string() + "app" => SETTINGS.app.name.to_owned() ]).as_str()) .autofocus(true) ) diff --git a/src/base/theme/aliner/mod.rs b/src/base/theme/aliner/mod.rs index d27e2f91..b678d4b7 100644 --- a/src/base/theme/aliner/mod.rs +++ b/src/base/theme/aliner/mod.rs @@ -10,7 +10,7 @@ impl Theme for AlinerTheme { } fn fullname(&self) -> String { - "Aliner".to_string() + "Aliner".to_owned() } fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { diff --git a/src/base/theme/bootsier/mod.rs b/src/base/theme/bootsier/mod.rs index 97b7fa46..3a340a84 100644 --- a/src/base/theme/bootsier/mod.rs +++ b/src/base/theme/bootsier/mod.rs @@ -12,7 +12,7 @@ impl Theme for BootsierTheme { } fn fullname(&self) -> String { - "Bootsier".to_string() + "Bootsier".to_owned() } fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { diff --git a/src/base/theme/minimal/mod.rs b/src/base/theme/minimal/mod.rs index 17611468..c6780005 100644 --- a/src/base/theme/minimal/mod.rs +++ b/src/base/theme/minimal/mod.rs @@ -8,6 +8,6 @@ impl Theme for MinimalTheme { } fn fullname(&self) -> String { - "Minimal".to_string() + "Minimal".to_owned() } } diff --git a/src/config/settings.rs b/src/config.rs similarity index 97% rename from src/config/settings.rs rename to src/config.rs index 66ddbe42..bd80bd76 100644 --- a/src/config/settings.rs +++ b/src/config.rs @@ -1,11 +1,13 @@ use crate::Lazy; -use crate::config::CONFIG_DIR; use config_rs::{Config, File}; use serde::Deserialize; use std::env; +/// Nombre del directorio donde se encuentra la configuración. +const CONFIG_DIR: &'static str = "config"; + /// Al arrancar la aplicación, carga los valores originales "clave = valor" de /// los archivos de configuración. Con [`config_map`] se asignarán los ajustes /// globales ([`SETTINGS`]); y se podrán asignar los ajustes específicos de la diff --git a/src/config/mod.rs b/src/config/mod.rs deleted file mode 100644 index aba410ee..00000000 --- a/src/config/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// Nombre del directorio donde se encuentra la configuración. -pub const CONFIG_DIR: &'static str = "config"; - -mod settings; -pub use settings::{CONFIG, SETTINGS}; diff --git a/src/core/all.rs b/src/core/global.rs similarity index 83% rename from src/core/all.rs rename to src/core/global.rs index eb7bed10..1d64d44f 100644 --- a/src/core/all.rs +++ b/src/core/global.rs @@ -3,7 +3,6 @@ use crate::core::theme::Theme; use crate::core::module::Module; use crate::core::response::page::PageContainer; use crate::core::server; -use crate::base; use std::sync::RwLock; use std::collections::HashMap; @@ -15,11 +14,7 @@ include!(concat!(env!("OUT_DIR"), "/theme.rs")); // ----------------------------------------------------------------------------- pub static THEMES: Lazy>> = Lazy::new(|| { - RwLock::new(vec![ - &base::theme::aliner::AlinerTheme, - &base::theme::minimal::MinimalTheme, - &base::theme::bootsier::BootsierTheme, - ]) + RwLock::new(Vec::new()) }); pub fn themes(cfg: &mut server::web::ServiceConfig) { @@ -38,10 +33,7 @@ pub fn themes(cfg: &mut server::web::ServiceConfig) { // ----------------------------------------------------------------------------- pub static MODULES: Lazy>> = Lazy::new(|| { - RwLock::new(vec![ - &base::module::admin::AdminModule, - &base::module::user::UserModule, - ]) + RwLock::new(Vec::new()) }); pub fn modules(cfg: &mut server::web::ServiceConfig) { diff --git a/src/core/mod.rs b/src/core/mod.rs index 40530f15..26618959 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,6 +1,6 @@ pub use actix_web::dev::Server; -mod all; +mod global; pub mod theme; pub mod module; diff --git a/src/core/module/api.rs b/src/core/module/api.rs deleted file mode 100644 index 83be71c3..00000000 --- a/src/core/module/api.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::core::{all, server}; - -/// Los módulos deben implementar este *trait*. -pub trait Module: Send + Sync { - fn name(&self) -> &'static str; - - fn fullname(&self) -> String; - - fn description(&self) -> String { - "".to_string() - } - - #[allow(unused_variables)] - fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { - } -} - -pub fn register_module(m: &'static (dyn Module + 'static)) { - all::MODULES.write().unwrap().push(m); -} - -pub fn find_module(name: &str) -> Option<&'static (dyn Module + 'static)> { - let modules = all::MODULES.write().unwrap(); - match modules.iter().find(|t| t.name() == name) { - Some(module) => Some(*module), - _ => None, - } -} diff --git a/src/core/module/definition.rs b/src/core/module/definition.rs new file mode 100644 index 00000000..40e9cee8 --- /dev/null +++ b/src/core/module/definition.rs @@ -0,0 +1,16 @@ +use crate::core::server; + +/// Los módulos deben implementar este *trait*. +pub trait Module: Send + Sync { + fn name(&self) -> &'static str; + + fn fullname(&self) -> String; + + fn description(&self) -> Option { + None + } + + #[allow(unused_variables)] + fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { + } +} diff --git a/src/core/module/mod.rs b/src/core/module/mod.rs index 08686bcd..439cff79 100644 --- a/src/core/module/mod.rs +++ b/src/core/module/mod.rs @@ -1,2 +1,16 @@ -mod api; -pub use api::{Module, find_module, register_module}; +use crate::core::global; + +mod definition; +pub use definition::Module; + +pub fn register_module(m: &'static (dyn Module + 'static)) { + global::MODULES.write().unwrap().push(m); +} + +pub fn find_module(name: &str) -> Option<&'static (dyn Module + 'static)> { + let modules = global::MODULES.write().unwrap(); + match modules.iter().find(|t| t.name() == name) { + Some(module) => Some(*module), + _ => None, + } +} diff --git a/src/core/response/page/assets.rs b/src/core/response/page/assets.rs index 77174e58..11cdd35c 100644 --- a/src/core/response/page/assets.rs +++ b/src/core/response/page/assets.rs @@ -1,10 +1,10 @@ use crate::{Lazy, base}; use crate::config::SETTINGS; -use crate::core::all; +use crate::core::global; use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html}; static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| { - for t in all::THEMES.read().unwrap().iter() { + for t in global::THEMES.read().unwrap().iter() { if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() { return *t; } @@ -73,7 +73,7 @@ impl Favicon { ) -> Self { let mut link: String = format!(" format!("{} type=\"image/gif\"", link), ".ico" => format!("{} type=\"image/x-icon\"", link), ".jpg" => format!("{} type=\"image/jpg\"", link), @@ -295,14 +295,14 @@ impl PageAssets { if id.is_empty() { let prefix = prefix.trim().replace(" ", "_").to_lowercase(); let prefix = if prefix.is_empty() { - "prefix".to_string() + "prefix".to_owned() } else { prefix }; self.id_counter += 1; [prefix, self.id_counter.to_string()].join("-") } else { - id.to_string() + id.to_owned() } } } diff --git a/src/core/response/page/component.rs b/src/core/response/page/component.rs index ccc0facb..1472ffe2 100644 --- a/src/core/response/page/component.rs +++ b/src/core/response/page/component.rs @@ -18,11 +18,11 @@ pub trait PageComponent: Downcast + Send + Sync { } fn fullname(&self) -> String { - type_name::().to_string() + type_name::().to_owned() } - fn description(&self) -> String { - "".to_string() + fn description(&self) -> Option { + None } fn is_renderable(&self) -> bool { diff --git a/src/core/response/page/page.rs b/src/core/response/page/page.rs index 18e8c917..8052683d 100644 --- a/src/core/response/page/page.rs +++ b/src/core/response/page/page.rs @@ -1,6 +1,6 @@ use crate::{Lazy, trace, util}; use crate::config::SETTINGS; -use crate::core::{all, server}; +use crate::core::{global, server}; use crate::core::theme::{DOCTYPE, Markup, html}; use crate::core::response::page::{PageAssets, PageComponent, PageContainer}; @@ -19,9 +19,9 @@ static DEFAULT_LANGUAGE: Lazy> = Lazy::new(|| { static DEFAULT_DIRECTION: Lazy> = Lazy::new(|| { let direction = SETTINGS.app.direction.to_lowercase(); match direction.as_str() { - "auto" => Some("auto".to_string()), - "ltr" => Some("ltr".to_string()), - "rtl" => Some("rtl".to_string()), + "auto" => Some("auto".to_owned()), + "ltr" => Some("ltr".to_owned()), + "rtl" => Some("rtl".to_owned()), "" => None, _ => { trace::warn!( @@ -44,7 +44,7 @@ pub struct Page<'a> { assets : PageAssets, body_classes: Cow<'a, str>, regions : HashMap<&'a str, PageContainer>, - template : Option, + template : String, } impl<'a> Page<'a> { @@ -52,45 +52,45 @@ impl<'a> Page<'a> { pub fn prepare() -> Self { Page { language : match &*DEFAULT_LANGUAGE { - Some(language) => Some(language.to_string()), + Some(language) => Some(language.to_owned()), _ => None, }, direction : match &*DEFAULT_DIRECTION { - Some(direction) => Some(direction.to_string()), + Some(direction) => Some(direction.to_owned()), _ => None, }, title : None, description : None, body_classes: "body".into(), assets : PageAssets::new(), - regions : all::COMPONENTS.read().unwrap().clone(), - template : Some("default".to_string()), + regions : global::COMPONENTS.read().unwrap().clone(), + template : "default".to_owned(), } } // Page BUILDER. pub fn with_language(&mut self, language: &str) -> &mut Self { - self.language = util::optional_value(language); + self.language = util::optional_str(language); self } pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self { self.direction = match dir { - TextDirection::Auto => Some("auto".to_string()), - TextDirection::LeftToRight => Some("ltr".to_string()), - TextDirection::RightToLeft => Some("rtl".to_string()), + TextDirection::Auto => Some("auto".to_owned()), + TextDirection::LeftToRight => Some("ltr".to_owned()), + TextDirection::RightToLeft => Some("rtl".to_owned()), }; self } pub fn with_title(&mut self, title: &str) -> &mut Self { - self.title = util::optional_value(title); + self.title = util::optional_str(title); self } pub fn with_description(&mut self, description: &str) -> &mut Self { - self.description = util::optional_value(description); + self.description = util::optional_str(description); self } @@ -120,26 +120,26 @@ impl<'a> Page<'a> { } pub fn using_template(&mut self, template: &str) -> &mut Self { - self.template = util::optional_value(template); + self.template = template.to_owned(); self } // Page GETTERS. pub fn language(&self) -> &str { - util::assigned_value(&self.language) + util::assigned_str(&self.language) } pub fn direction(&self) -> &str { - util::assigned_value(&self.direction) + util::assigned_str(&self.direction) } pub fn title(&self) -> &str { - util::assigned_value(&self.title) + util::assigned_str(&self.title) } pub fn description(&self) -> &str { - util::assigned_value(&self.description) + util::assigned_str(&self.description) } pub fn body_classes(&self) -> &str { @@ -154,7 +154,7 @@ impl<'a> Page<'a> { } pub fn template(&self) -> &str { - util::assigned_value(&self.template) + self.template.as_str() } // Page RENDER. @@ -208,7 +208,7 @@ pub fn render_component( } pub fn add_component_to(region: &'static str, component: impl PageComponent) { - let mut hmap = all::COMPONENTS.write().unwrap(); + let mut hmap = global::COMPONENTS.write().unwrap(); if let Some(regions) = hmap.get_mut(region) { regions.add(component); } else { diff --git a/src/core/server/langid.rs b/src/core/server/langid.rs deleted file mode 100644 index 3638a6a4..00000000 --- a/src/core/server/langid.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::{Lazy, trace}; -use crate::config::SETTINGS; - -use unic_langid::LanguageIdentifier; - -/// Almacena el Identificador de Idioma Unicode ([Unicode Language Identifier] -/// (https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)) de -/// la aplicación, obtenido de `SETTINGS.app.language`. -pub static LANGID: Lazy = Lazy::new(|| { - match SETTINGS.app.language.parse() { - Ok(language) => language, - Err(_) => { - trace::warn!( - "Failed to parse language \"{}\". {}. {}. {}.", - SETTINGS.app.language, - "Unicode Language Identifier not recognized", - "Using \"en-US\"", - "Check the settings file", - ); - "en-US".parse().unwrap() - } - } -}); diff --git a/src/core/server/main.rs b/src/core/server/main.rs index c39c9f83..b6800142 100644 --- a/src/core/server/main.rs +++ b/src/core/server/main.rs @@ -1,6 +1,7 @@ -use crate::{Lazy, base, trace}; +use crate::{Lazy, base, locale, trace}; use crate::config::SETTINGS; -use crate::core::{Server, all, server}; +use crate::core::{Server, global, server}; +use crate::core::theme::register_theme; use crate::core::module::register_module; use actix_web::middleware::normalize; @@ -32,11 +33,20 @@ pub fn run(bootstrap: Option) -> Result { ); } - // Inicia la traza de la aplicación. + // Inicia registro de trazas y eventos. Lazy::force(&server::tracing::TRACING); // Asigna identificador de idioma. - Lazy::force(&server::langid::LANGID); + Lazy::force(&locale::LANGID); + + // Registra los temas predefinidos. + register_theme(&base::theme::aliner::AlinerTheme); + register_theme(&base::theme::minimal::MinimalTheme); + register_theme(&base::theme::bootsier::BootsierTheme); + + // Registra los módulos predeterminados. + register_module(&base::module::admin::AdminModule); + register_module(&base::module::user::UserModule); // Ejecuta la función de inicio de la aplicación. if bootstrap != None { @@ -54,8 +64,8 @@ pub fn run(bootstrap: Option) -> Result { server::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(normalize::NormalizePath::new(normalize::TrailingSlash::Trim)) - .configure(&all::themes) - .configure(&all::modules) + .configure(&global::themes) + .configure(&global::modules) }) .bind(format!("{}:{}", &SETTINGS.webserver.bind_address, diff --git a/src/core/server/mod.rs b/src/core/server/mod.rs index 6bb25129..7db53759 100644 --- a/src/core/server/mod.rs +++ b/src/core/server/mod.rs @@ -4,8 +4,5 @@ pub use actix_web::{ mod tracing; -mod langid; -pub use langid::LANGID; - mod main; pub use main::run; diff --git a/src/core/server/tracing.rs b/src/core/server/tracing.rs index fd907461..a9804213 100644 --- a/src/core/server/tracing.rs +++ b/src/core/server/tracing.rs @@ -4,6 +4,19 @@ use crate::config::SETTINGS; use tracing_appender::non_blocking::WorkerGuard; use tracing_subscriber::EnvFilter; +/// Registro de trazas y eventos de la aplicación. +/// +/// Para aumentar el rendimiento, un subproceso dedicado utiliza un sistema de +/// escritura sin bloqueo (*non-blocking writer*) que actúa periódicamente en +/// vez de enviar cada traza o evento al instante. Si el programa termina +/// abruptamente (por ejemplo, por un `panic!` o un `std::process::exit`), es +/// posible que algunas trazas o eventos no se envíen. +/// +/// Puesto que las trazas o eventos registrados poco antes de la caída de una +/// aplicación suelen ser importantes para diagnosticar la causa del fallo, con +/// `Lazy` se garantiza que todos los registros almacenados se +/// enviarán antes de terminar la ejecución. + pub static TRACING: Lazy = Lazy::new(|| { let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing) .unwrap_or(EnvFilter::new("Info")); diff --git a/src/core/theme/api.rs b/src/core/theme/definition.rs similarity index 85% rename from src/core/theme/api.rs rename to src/core/theme/definition.rs index efbc9cef..12d9e05f 100644 --- a/src/core/theme/api.rs +++ b/src/core/theme/definition.rs @@ -1,5 +1,5 @@ use crate::config::SETTINGS; -use crate::core::{all, server}; +use crate::core::server; use crate::core::theme::{Markup, html}; use crate::core::response::page::{Page, PageAssets, PageComponent}; use crate::base::component::Chunck; @@ -10,8 +10,8 @@ pub trait Theme: Send + Sync { fn fullname(&self) -> String; - fn description(&self) -> String { - "".to_string() + fn description(&self) -> Option { + None } #[allow(unused_variables)] @@ -25,7 +25,7 @@ pub trait Theme: 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_string() + SETTINGS.app.name.to_owned() } else { [SETTINGS.app.name.to_string(), title.to_string()].join(" | ") }; @@ -104,15 +104,3 @@ pub trait Theme: Send + Sync { .render() } } - -pub fn register_theme(t: &'static (dyn Theme + 'static)) { - all::THEMES.write().unwrap().push(t); -} - -pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> { - let themes = all::THEMES.write().unwrap(); - match themes.iter().find(|t| t.name() == name) { - Some(theme) => Some(*theme), - _ => None, - } -} diff --git a/src/core/theme/mod.rs b/src/core/theme/mod.rs index 9f708803..8292ade6 100644 --- a/src/core/theme/mod.rs +++ b/src/core/theme/mod.rs @@ -1,4 +1,18 @@ +use crate::core::global; + pub use maud::{DOCTYPE, Markup, PreEscaped, html}; -mod api; -pub use api::{Theme, find_theme, register_theme}; +mod definition; +pub use definition::Theme; + +pub fn register_theme(t: &'static (dyn Theme + 'static)) { + global::THEMES.write().unwrap().push(t); +} + +pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> { + let themes = global::THEMES.write().unwrap(); + match themes.iter().find(|t| t.name() == name) { + Some(theme) => Some(*theme), + _ => None, + } +} diff --git a/src/lib.rs b/src/lib.rs index 42f51a3a..7d17db44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub use once_cell::sync::Lazy; // ----------------------------------------------------------------------------- pub mod config; // Gestión de la configuración. -pub mod trace; // Traza de ejecución. +pub mod trace; // Registro de trazas y eventos de la aplicación. pub mod locale; // Localización. pub mod core; // Servidor web y sistemas para Temas, Módulos y Respuestas. pub mod base; // Temas, Módulos y Componentes base. diff --git a/src/locale.rs b/src/locale.rs index b43d9fd6..e3639858 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -2,12 +2,35 @@ pub use fluent_templates::{static_loader as static_locale, Loader as Locale}; pub use fluent_templates; pub use fluent_templates::fluent_bundle::FluentValue; +use crate::{Lazy, trace}; +use crate::config::SETTINGS; + +use unic_langid::LanguageIdentifier; + +/// Almacena el Identificador de Idioma Unicode ([Unicode Language Identifier] +/// (https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)) de +/// la aplicación, obtenido de `SETTINGS.app.language`. +pub static LANGID: Lazy = Lazy::new(|| { + match SETTINGS.app.language.parse() { + Ok(language) => language, + Err(_) => { + trace::warn!( + "Failed to parse language \"{}\". {}. {}. {}.", + SETTINGS.app.language, + "Unicode Language Identifier not recognized", + "Using \"en-US\"", + "Check the settings file", + ); + "en-US".parse().unwrap() + } + } +}); + #[macro_export] /// Permite integrar fácilmente localización en temas, módulos y componentes. macro_rules! localize { ( $DEF_LANGID:literal, $locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; - use $crate::core::server::LANGID; static_locale! { static LOCALES = { diff --git a/src/util.rs b/src/util.rs index 638e948f..3fff0a23 100644 --- a/src/util.rs +++ b/src/util.rs @@ -26,17 +26,17 @@ pub fn valid_id(id: &str) -> Option { } } -pub fn optional_value(value: &str) -> Option { - let value = value.to_string(); - match value.is_empty() { +pub fn optional_str(s: &str) -> Option { + let s = s.to_owned(); + match s.is_empty() { true => None, - false => Some(value), + false => Some(s), } } -pub fn assigned_value(value: &Option) -> &str { - match value { - Some(value) => value.as_str(), +pub fn assigned_str(optional: &Option) -> &str { + match optional { + Some(o) => o.as_str(), _ => "", } }