Actualiza y simplifica la estructura del código

Revisión general del código fuente para asegurar los elementos que deben
ser públicos y estandarizar el uso de funciones globales.
This commit is contained in:
Manuel Cillero 2022-03-02 23:19:16 +01:00
parent 67952f6840
commit b6dd473578
34 changed files with 250 additions and 237 deletions

View file

@ -4,7 +4,7 @@ pub struct Block {
renderable: fn() -> bool, renderable: fn() -> bool,
weight : i8, weight : i8,
id : Option<String>, id : Option<String>,
title : String, title : Option<String>,
markup : Vec<Markup>, markup : Vec<Markup>,
template : String, template : String,
} }
@ -16,9 +16,9 @@ impl PageComponent for Block {
renderable: always, renderable: always,
weight : 0, weight : 0,
id : None, id : None,
title : "".to_string(), title : None,
markup : Vec::new(), 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()); let id = assets.serial_id(self.name(), self.id());
html! { html! {
div id=(id) class="block" { div id=(id) class="block" {
@if !self.title.is_empty() { @if self.title != None {
h2 class="block-title" { (self.title) } h2 class="block-title" { (self.title()) }
} }
div class="block-body" { div class="block-body" {
@for markup in self.markup.iter() { @for markup in self.markup.iter() {
@ -71,7 +71,7 @@ impl Block {
} }
pub fn with_title(mut self, title: &str) -> Self { pub fn with_title(mut self, title: &str) -> Self {
self.title = title.to_string(); self.title = util::optional_str(title);
self self
} }
@ -81,18 +81,18 @@ impl Block {
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Block GETTERS. // Block GETTERS.
pub fn id(&self) -> &str { pub fn id(&self) -> &str {
util::assigned_value(&self.id) util::assigned_str(&self.id)
} }
pub fn title(&self) -> &str { pub fn title(&self) -> &str {
self.title.as_str() util::assigned_str(&self.title)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -14,7 +14,7 @@ impl PageComponent for Chunck {
renderable: always, renderable: always,
weight : 0, weight : 0,
markup : Vec::new(), 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 { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }

View file

@ -20,7 +20,7 @@ impl PageComponent for Container {
id : None, id : None,
container : ContainerType::Wrapper, container : ContainerType::Wrapper,
components: PageContainer::new(), 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 { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Container GETTERS. // Container GETTERS.
pub fn id(&self) -> &str { pub fn id(&self) -> &str {
util::assigned_value(&self.id) util::assigned_str(&self.id)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -24,7 +24,7 @@ impl PageComponent for Button {
value : None, value : None,
autofocus : None, autofocus : None,
disabled : 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 { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_value(value); self.value = util::optional_str(value);
self self
} }
pub fn autofocus(mut self, toggle: bool) -> Self { pub fn autofocus(mut self, toggle: bool) -> Self {
self.autofocus = match toggle { self.autofocus = match toggle {
true => Some("autofocus".to_string()), true => Some("autofocus".to_owned()),
false => None false => None
}; };
self self
@ -115,25 +115,25 @@ impl Button {
pub fn disabled(mut self, toggle: bool) -> Self { pub fn disabled(mut self, toggle: bool) -> Self {
self.disabled = match toggle { self.disabled = match toggle {
true => Some("disabled".to_string()), true => Some("disabled".to_owned()),
false => None false => None
}; };
self self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Button GETTERS. // Button GETTERS.
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
util::assigned_value(&self.name) util::assigned_str(&self.name)
} }
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
util::assigned_value(&self.value) util::assigned_str(&self.value)
} }
pub fn has_autofocus(&self) -> bool { pub fn has_autofocus(&self) -> bool {

View file

@ -5,14 +5,14 @@ pub struct Date {
weight : i8, weight : i8,
name : Option<String>, name : Option<String>,
value : Option<String>, value : Option<String>,
label : String, label : Option<String>,
placeholder : Option<String>, placeholder : Option<String>,
autofocus : Option<String>, autofocus : Option<String>,
autocomplete: Option<String>, autocomplete: Option<String>,
disabled : Option<String>, disabled : Option<String>,
readonly : Option<String>, readonly : Option<String>,
required : Option<String>, required : Option<String>,
help_text : String, help_text : Option<String>,
template : String, template : String,
} }
@ -24,15 +24,15 @@ impl PageComponent for Date {
weight : 0, weight : 0,
name : None, name : None,
value : None, value : None,
label : "".to_string(), label : None,
placeholder : None, placeholder : None,
autofocus : None, autofocus : None,
autocomplete: None, autocomplete: None,
disabled : None, disabled : None,
readonly : None, readonly : None,
required : None, required : None,
help_text : "".to_string(), help_text : None,
template : "default".to_string(), template : "default".to_owned(),
} }
} }
@ -51,15 +51,15 @@ impl PageComponent for Date {
Some(format!("edit-{}", name)) Some(format!("edit-{}", name))
), ),
None => ( None => (
"form-item form-type-date".to_string(), "form-item form-type-date".to_owned(),
None None
) )
}; };
html! { html! {
div class=(class_item) { div class=(class_item) {
@if !self.label.is_empty() { @if self.label != None {
label class="form-label" for=[&id_item] { label class="form-label" for=[&id_item] {
(self.label) " " (self.label()) " "
@if self.required != None { @if self.required != None {
span span
class="form-required" class="form-required"
@ -82,9 +82,9 @@ impl PageComponent for Date {
readonly=[&self.readonly] readonly=[&self.readonly]
required=[&self.required] required=[&self.required]
disabled=[&self.disabled]; disabled=[&self.disabled];
@if !self.help_text.is_empty() { @if self.help_text != None {
div class="form-text" { 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 { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_value(value); self.value = util::optional_str(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label = label.to_string(); self.label = util::optional_str(label);
self self
} }
pub fn with_placeholder(mut self, placeholder: &str) -> Self { pub fn with_placeholder(mut self, placeholder: &str) -> Self {
self.placeholder = util::optional_value(placeholder); self.placeholder = util::optional_str(placeholder);
self self
} }
pub fn autofocus(mut self, toggle: bool) -> Self { pub fn autofocus(mut self, toggle: bool) -> Self {
self.autofocus = match toggle { self.autofocus = match toggle {
true => Some("autofocus".to_string()), true => Some("autofocus".to_owned()),
false => None false => None
}; };
self self
@ -137,14 +137,14 @@ impl Date {
pub fn autocomplete(mut self, toggle: bool) -> Self { pub fn autocomplete(mut self, toggle: bool) -> Self {
self.autocomplete = match toggle { self.autocomplete = match toggle {
true => None, true => None,
false => Some("off".to_string()) false => Some("off".to_owned())
}; };
self self
} }
pub fn disabled(mut self, toggle: bool) -> Self { pub fn disabled(mut self, toggle: bool) -> Self {
self.disabled = match toggle { self.disabled = match toggle {
true => Some("disabled".to_string()), true => Some("disabled".to_owned()),
false => None false => None
}; };
self self
@ -152,7 +152,7 @@ impl Date {
pub fn readonly(mut self, toggle: bool) -> Self { pub fn readonly(mut self, toggle: bool) -> Self {
self.readonly = match toggle { self.readonly = match toggle {
true => Some("readonly".to_string()), true => Some("readonly".to_owned()),
false => None false => None
}; };
self self
@ -160,38 +160,38 @@ impl Date {
pub fn required(mut self, toggle: bool) -> Self { pub fn required(mut self, toggle: bool) -> Self {
self.required = match toggle { self.required = match toggle {
true => Some("required".to_string()), true => Some("required".to_owned()),
false => None false => None
}; };
self self
} }
pub fn with_help_text(mut self, help_text: &str) -> 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 self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Date GETTERS. // Date GETTERS.
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
util::assigned_value(&self.name) util::assigned_str(&self.name)
} }
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
util::assigned_value(&self.value) util::assigned_str(&self.value)
} }
pub fn label(&self) -> &str { pub fn label(&self) -> &str {
self.label.as_str() util::assigned_str(&self.label)
} }
pub fn placeholder(&self) -> &str { pub fn placeholder(&self) -> &str {
util::assigned_value(&self.placeholder) util::assigned_str(&self.placeholder)
} }
pub fn has_autofocus(&self) -> bool { pub fn has_autofocus(&self) -> bool {
@ -230,7 +230,7 @@ impl Date {
} }
pub fn help_text(&self) -> &str { pub fn help_text(&self) -> &str {
self.help_text.as_str() util::assigned_str(&self.help_text)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -22,9 +22,9 @@ impl PageComponent for Form {
id : None, id : None,
action : None, action : None,
method : FormMethod::Post, method : FormMethod::Post,
charset : Some("UTF-8".to_string()), charset : Some("UTF-8".to_owned()),
elements : PageContainer::new(), 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 { fn default_render(&self, assets: &mut PageAssets) -> Markup {
let method = match self.method { let method = match self.method {
FormMethod::Get => None, FormMethod::Get => None,
FormMethod::Post => Some("post".to_string()) FormMethod::Post => Some("post".to_owned())
}; };
html! { html! {
form form
@ -76,7 +76,7 @@ impl Form {
} }
pub fn with_action(mut self, action: &str) -> Self { pub fn with_action(mut self, action: &str) -> Self {
self.action = util::optional_value(action); self.action = util::optional_str(action);
self self
} }
@ -86,7 +86,7 @@ impl Form {
} }
pub fn with_charset(mut self, charset: &str) -> Self { pub fn with_charset(mut self, charset: &str) -> Self {
self.charset = util::optional_value(charset); self.charset = util::optional_str(charset);
self self
} }
@ -96,18 +96,18 @@ impl Form {
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Form GETTERS. // Form GETTERS.
pub fn id(&self) -> &str { pub fn id(&self) -> &str {
util::assigned_value(&self.id) util::assigned_str(&self.id)
} }
pub fn action(&self) -> &str { pub fn action(&self) -> &str {
util::assigned_value(&self.action) util::assigned_str(&self.action)
} }
pub fn method(&self) -> &str { pub fn method(&self) -> &str {
@ -118,7 +118,7 @@ impl Form {
} }
pub fn charset(&self) -> &str { pub fn charset(&self) -> &str {
util::assigned_value(&self.charset) util::assigned_str(&self.charset)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -54,17 +54,17 @@ impl Hidden {
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_value(value); self.value = util::optional_str(value);
self self
} }
// Hidden GETTERS. // Hidden GETTERS.
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
util::assigned_value(&self.name) util::assigned_str(&self.name)
} }
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
util::assigned_value(&self.value) util::assigned_str(&self.value)
} }
} }

View file

@ -8,7 +8,7 @@ pub struct Input {
input_type : InputType, input_type : InputType,
name : Option<String>, name : Option<String>,
value : Option<String>, value : Option<String>,
label : String, label : Option<String>,
size : Option<u16>, size : Option<u16>,
minlength : Option<u16>, minlength : Option<u16>,
maxlength : Option<u16>, maxlength : Option<u16>,
@ -18,7 +18,7 @@ pub struct Input {
disabled : Option<String>, disabled : Option<String>,
readonly : Option<String>, readonly : Option<String>,
required : Option<String>, required : Option<String>,
help_text : String, help_text : Option<String>,
template : String, template : String,
} }
@ -31,7 +31,7 @@ impl PageComponent for Input {
input_type : InputType::Textfield, input_type : InputType::Textfield,
name : None, name : None,
value : None, value : None,
label : "".to_string(), label : None,
size : Some(60), size : Some(60),
minlength : None, minlength : None,
maxlength : Some(128), maxlength : Some(128),
@ -41,8 +41,8 @@ impl PageComponent for Input {
disabled : None, disabled : None,
readonly : None, readonly : None,
required : None, required : None,
help_text : "".to_string(), help_text : None,
template : "default".to_string(), template : "default".to_owned(),
} }
} }
@ -75,9 +75,9 @@ impl PageComponent for Input {
}; };
html! { html! {
div class=(class_item) { div class=(class_item) {
@if !self.label.is_empty() { @if self.label != None {
label class="form-label" for=[&id_item] { label class="form-label" for=[&id_item] {
(self.label) " " (self.label()) " "
@if self.required != None { @if self.required != None {
span span
class="form-required" class="form-required"
@ -103,9 +103,9 @@ impl PageComponent for Input {
readonly=[&self.readonly] readonly=[&self.readonly]
required=[&self.required] required=[&self.required]
disabled=[&self.disabled]; disabled=[&self.disabled];
@if !self.help_text.is_empty() { @if self.help_text != None {
div class="form-text" { 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 { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_value(value); self.value = util::optional_str(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label = label.to_string(); self.label = util::optional_str(label);
self self
} }
@ -192,13 +192,13 @@ impl Input {
} }
pub fn with_placeholder(mut self, placeholder: &str) -> Self { pub fn with_placeholder(mut self, placeholder: &str) -> Self {
self.placeholder = util::optional_value(placeholder); self.placeholder = util::optional_str(placeholder);
self self
} }
pub fn autofocus(mut self, toggle: bool) -> Self { pub fn autofocus(mut self, toggle: bool) -> Self {
self.autofocus = match toggle { self.autofocus = match toggle {
true => Some("autofocus".to_string()), true => Some("autofocus".to_owned()),
false => None false => None
}; };
self self
@ -207,14 +207,14 @@ impl Input {
pub fn autocomplete(mut self, toggle: bool) -> Self { pub fn autocomplete(mut self, toggle: bool) -> Self {
self.autocomplete = match toggle { self.autocomplete = match toggle {
true => None, true => None,
false => Some("off".to_string()) false => Some("off".to_owned())
}; };
self self
} }
pub fn disabled(mut self, toggle: bool) -> Self { pub fn disabled(mut self, toggle: bool) -> Self {
self.disabled = match toggle { self.disabled = match toggle {
true => Some("disabled".to_string()), true => Some("disabled".to_owned()),
false => None false => None
}; };
self self
@ -222,7 +222,7 @@ impl Input {
pub fn readonly(mut self, toggle: bool) -> Self { pub fn readonly(mut self, toggle: bool) -> Self {
self.readonly = match toggle { self.readonly = match toggle {
true => Some("readonly".to_string()), true => Some("readonly".to_owned()),
false => None false => None
}; };
self self
@ -230,34 +230,34 @@ impl Input {
pub fn required(mut self, toggle: bool) -> Self { pub fn required(mut self, toggle: bool) -> Self {
self.required = match toggle { self.required = match toggle {
true => Some("required".to_string()), true => Some("required".to_owned()),
false => None false => None
}; };
self self
} }
pub fn with_help_text(mut self, help_text: &str) -> 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 self
} }
pub fn using_template(mut self, template: &str) -> Self { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Input GETTERS. // Input GETTERS.
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
util::assigned_value(&self.name) util::assigned_str(&self.name)
} }
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
util::assigned_value(&self.value) util::assigned_str(&self.value)
} }
pub fn label(&self) -> &str { pub fn label(&self) -> &str {
self.label.as_str() util::assigned_str(&self.label)
} }
pub fn size(&self) -> Option<u16> { pub fn size(&self) -> Option<u16> {
@ -273,7 +273,7 @@ impl Input {
} }
pub fn placeholder(&self) -> &str { pub fn placeholder(&self) -> &str {
util::assigned_value(&self.placeholder) util::assigned_str(&self.placeholder)
} }
pub fn has_autofocus(&self) -> bool { pub fn has_autofocus(&self) -> bool {
@ -312,7 +312,7 @@ impl Input {
} }
pub fn help_text(&self) -> &str { pub fn help_text(&self) -> &str {
self.help_text.as_str() util::assigned_str(&self.help_text)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -75,7 +75,7 @@ impl MenuItem {
MenuItem { MenuItem {
renderable: always, renderable: always,
weight : 0, 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, renderable: always,
weight : 0, weight : 0,
item_type : Some(MenuItemType::Link( item_type : Some(MenuItemType::Link(
label.to_string(), label.to_owned(),
path.to_string(), path.to_owned(),
)), )),
} }
} }
@ -95,8 +95,8 @@ impl MenuItem {
renderable: always, renderable: always,
weight : 0, weight : 0,
item_type : Some(MenuItemType::LinkBlank( item_type : Some(MenuItemType::LinkBlank(
label.to_string(), label.to_owned(),
path.to_string(), path.to_owned(),
)), )),
} }
} }
@ -122,7 +122,7 @@ impl MenuItem {
renderable: always, renderable: always,
weight : 0, weight : 0,
item_type : Some(MenuItemType::Submenu( item_type : Some(MenuItemType::Submenu(
label.to_string(), label.to_owned(),
menu menu
)), )),
} }
@ -161,7 +161,7 @@ impl PageComponent for Menu {
weight : 0, weight : 0,
id : None, id : None,
items : PageContainer::new(), 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 { pub fn using_template(mut self, template: &str) -> Self {
self.template = template.to_string(); self.template = template.to_owned();
self self
} }
// Menu GETTERS. // Menu GETTERS.
pub fn id(&self) -> &str { pub fn id(&self) -> &str {
util::assigned_value(&self.id) util::assigned_str(&self.id)
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {

View file

@ -15,8 +15,8 @@ impl Module for AdminModule {
l("module_fullname") l("module_fullname")
} }
fn description(&self) -> String { fn description(&self) -> Option<String> {
l("module_description") Some(l("module_description"))
} }
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {

View file

@ -13,8 +13,8 @@ impl Module for HomepageModule {
l("module_fullname") l("module_fullname")
} }
fn description(&self) -> String { fn description(&self) -> Option<String> {
l("module_description") Some(l("module_description"))
} }
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {

View file

@ -13,8 +13,8 @@ impl Module for UserModule {
l("module_fullname") l("module_fullname")
} }
fn description(&self) -> String { fn description(&self) -> Option<String> {
l("module_description") Some(l("module_description"))
} }
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {
@ -29,7 +29,7 @@ fn form_login() -> impl PageComponent {
.with_name("name") .with_name("name")
.with_label(l("username").as_str()) .with_label(l("username").as_str())
.with_help_text(t("username_help", &args![ .with_help_text(t("username_help", &args![
"app" => SETTINGS.app.name.to_string() "app" => SETTINGS.app.name.to_owned()
]).as_str()) ]).as_str())
.autofocus(true) .autofocus(true)
) )

View file

@ -10,7 +10,7 @@ impl Theme for AlinerTheme {
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
"Aliner".to_string() "Aliner".to_owned()
} }
fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) {

View file

@ -12,7 +12,7 @@ impl Theme for BootsierTheme {
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
"Bootsier".to_string() "Bootsier".to_owned()
} }
fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) {

View file

@ -8,6 +8,6 @@ impl Theme for MinimalTheme {
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
"Minimal".to_string() "Minimal".to_owned()
} }
} }

View file

@ -1,11 +1,13 @@
use crate::Lazy; use crate::Lazy;
use crate::config::CONFIG_DIR;
use config_rs::{Config, File}; use config_rs::{Config, File};
use serde::Deserialize; use serde::Deserialize;
use std::env; 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 /// 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 /// 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 /// globales ([`SETTINGS`]); y se podrán asignar los ajustes específicos de la

View file

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

View file

@ -3,7 +3,6 @@ use crate::core::theme::Theme;
use crate::core::module::Module; use crate::core::module::Module;
use crate::core::response::page::PageContainer; use crate::core::response::page::PageContainer;
use crate::core::server; use crate::core::server;
use crate::base;
use std::sync::RwLock; use std::sync::RwLock;
use std::collections::HashMap; use std::collections::HashMap;
@ -15,11 +14,7 @@ include!(concat!(env!("OUT_DIR"), "/theme.rs"));
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| { pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| {
RwLock::new(vec![ RwLock::new(Vec::new())
&base::theme::aliner::AlinerTheme,
&base::theme::minimal::MinimalTheme,
&base::theme::bootsier::BootsierTheme,
])
}); });
pub fn themes(cfg: &mut server::web::ServiceConfig) { pub fn themes(cfg: &mut server::web::ServiceConfig) {
@ -38,10 +33,7 @@ pub fn themes(cfg: &mut server::web::ServiceConfig) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| { pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
RwLock::new(vec![ RwLock::new(Vec::new())
&base::module::admin::AdminModule,
&base::module::user::UserModule,
])
}); });
pub fn modules(cfg: &mut server::web::ServiceConfig) { pub fn modules(cfg: &mut server::web::ServiceConfig) {

View file

@ -1,6 +1,6 @@
pub use actix_web::dev::Server; pub use actix_web::dev::Server;
mod all; mod global;
pub mod theme; pub mod theme;
pub mod module; pub mod module;

View file

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

View file

@ -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<String> {
None
}
#[allow(unused_variables)]
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {
}
}

View file

@ -1,2 +1,16 @@
mod api; use crate::core::global;
pub use api::{Module, find_module, register_module};
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,
}
}

View file

@ -1,10 +1,10 @@
use crate::{Lazy, base}; use crate::{Lazy, base};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::core::all; use crate::core::global;
use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html}; use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html};
static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| { 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() { if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() {
return *t; return *t;
} }
@ -73,7 +73,7 @@ impl Favicon {
) -> Self { ) -> Self {
let mut link: String = format!("<link rel=\"{}\"", rel); let mut link: String = format!("<link rel=\"{}\"", rel);
if let Some(i) = source.rfind('.') { if let Some(i) = source.rfind('.') {
link = match source[i..].to_string().to_lowercase().as_str() { link = match source[i..].to_owned().to_lowercase().as_str() {
".gif" => format!("{} type=\"image/gif\"", link), ".gif" => format!("{} type=\"image/gif\"", link),
".ico" => format!("{} type=\"image/x-icon\"", link), ".ico" => format!("{} type=\"image/x-icon\"", link),
".jpg" => format!("{} type=\"image/jpg\"", link), ".jpg" => format!("{} type=\"image/jpg\"", link),
@ -295,14 +295,14 @@ impl PageAssets {
if id.is_empty() { if id.is_empty() {
let prefix = prefix.trim().replace(" ", "_").to_lowercase(); let prefix = prefix.trim().replace(" ", "_").to_lowercase();
let prefix = if prefix.is_empty() { let prefix = if prefix.is_empty() {
"prefix".to_string() "prefix".to_owned()
} else { } else {
prefix prefix
}; };
self.id_counter += 1; self.id_counter += 1;
[prefix, self.id_counter.to_string()].join("-") [prefix, self.id_counter.to_string()].join("-")
} else { } else {
id.to_string() id.to_owned()
} }
} }
} }

View file

@ -18,11 +18,11 @@ pub trait PageComponent: Downcast + Send + Sync {
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
type_name::<Self>().to_string() type_name::<Self>().to_owned()
} }
fn description(&self) -> String { fn description(&self) -> Option<String> {
"".to_string() None
} }
fn is_renderable(&self) -> bool { fn is_renderable(&self) -> bool {

View file

@ -1,6 +1,6 @@
use crate::{Lazy, trace, util}; use crate::{Lazy, trace, util};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::core::{all, server}; use crate::core::{global, server};
use crate::core::theme::{DOCTYPE, Markup, html}; use crate::core::theme::{DOCTYPE, Markup, html};
use crate::core::response::page::{PageAssets, PageComponent, PageContainer}; use crate::core::response::page::{PageAssets, PageComponent, PageContainer};
@ -19,9 +19,9 @@ static DEFAULT_LANGUAGE: Lazy<Option<String>> = Lazy::new(|| {
static DEFAULT_DIRECTION: Lazy<Option<String>> = Lazy::new(|| { static DEFAULT_DIRECTION: Lazy<Option<String>> = Lazy::new(|| {
let direction = SETTINGS.app.direction.to_lowercase(); let direction = SETTINGS.app.direction.to_lowercase();
match direction.as_str() { match direction.as_str() {
"auto" => Some("auto".to_string()), "auto" => Some("auto".to_owned()),
"ltr" => Some("ltr".to_string()), "ltr" => Some("ltr".to_owned()),
"rtl" => Some("rtl".to_string()), "rtl" => Some("rtl".to_owned()),
"" => None, "" => None,
_ => { _ => {
trace::warn!( trace::warn!(
@ -44,7 +44,7 @@ pub struct Page<'a> {
assets : PageAssets, assets : PageAssets,
body_classes: Cow<'a, str>, body_classes: Cow<'a, str>,
regions : HashMap<&'a str, PageContainer>, regions : HashMap<&'a str, PageContainer>,
template : Option<String>, template : String,
} }
impl<'a> Page<'a> { impl<'a> Page<'a> {
@ -52,45 +52,45 @@ impl<'a> Page<'a> {
pub fn prepare() -> Self { pub fn prepare() -> Self {
Page { Page {
language : match &*DEFAULT_LANGUAGE { language : match &*DEFAULT_LANGUAGE {
Some(language) => Some(language.to_string()), Some(language) => Some(language.to_owned()),
_ => None, _ => None,
}, },
direction : match &*DEFAULT_DIRECTION { direction : match &*DEFAULT_DIRECTION {
Some(direction) => Some(direction.to_string()), Some(direction) => Some(direction.to_owned()),
_ => None, _ => None,
}, },
title : None, title : None,
description : None, description : None,
body_classes: "body".into(), body_classes: "body".into(),
assets : PageAssets::new(), assets : PageAssets::new(),
regions : all::COMPONENTS.read().unwrap().clone(), regions : global::COMPONENTS.read().unwrap().clone(),
template : Some("default".to_string()), template : "default".to_owned(),
} }
} }
// Page BUILDER. // Page BUILDER.
pub fn with_language(&mut self, language: &str) -> &mut Self { pub fn with_language(&mut self, language: &str) -> &mut Self {
self.language = util::optional_value(language); self.language = util::optional_str(language);
self self
} }
pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self { pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self {
self.direction = match dir { self.direction = match dir {
TextDirection::Auto => Some("auto".to_string()), TextDirection::Auto => Some("auto".to_owned()),
TextDirection::LeftToRight => Some("ltr".to_string()), TextDirection::LeftToRight => Some("ltr".to_owned()),
TextDirection::RightToLeft => Some("rtl".to_string()), TextDirection::RightToLeft => Some("rtl".to_owned()),
}; };
self self
} }
pub fn with_title(&mut self, title: &str) -> &mut Self { pub fn with_title(&mut self, title: &str) -> &mut Self {
self.title = util::optional_value(title); self.title = util::optional_str(title);
self self
} }
pub fn with_description(&mut self, description: &str) -> &mut Self { pub fn with_description(&mut self, description: &str) -> &mut Self {
self.description = util::optional_value(description); self.description = util::optional_str(description);
self self
} }
@ -120,26 +120,26 @@ impl<'a> Page<'a> {
} }
pub fn using_template(&mut self, template: &str) -> &mut Self { pub fn using_template(&mut self, template: &str) -> &mut Self {
self.template = util::optional_value(template); self.template = template.to_owned();
self self
} }
// Page GETTERS. // Page GETTERS.
pub fn language(&self) -> &str { pub fn language(&self) -> &str {
util::assigned_value(&self.language) util::assigned_str(&self.language)
} }
pub fn direction(&self) -> &str { pub fn direction(&self) -> &str {
util::assigned_value(&self.direction) util::assigned_str(&self.direction)
} }
pub fn title(&self) -> &str { pub fn title(&self) -> &str {
util::assigned_value(&self.title) util::assigned_str(&self.title)
} }
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
util::assigned_value(&self.description) util::assigned_str(&self.description)
} }
pub fn body_classes(&self) -> &str { pub fn body_classes(&self) -> &str {
@ -154,7 +154,7 @@ impl<'a> Page<'a> {
} }
pub fn template(&self) -> &str { pub fn template(&self) -> &str {
util::assigned_value(&self.template) self.template.as_str()
} }
// Page RENDER. // Page RENDER.
@ -208,7 +208,7 @@ pub fn render_component(
} }
pub fn add_component_to(region: &'static str, component: impl PageComponent) { pub fn add_component_to(region: &'static str, component: impl PageComponent) {
let mut hmap = all::COMPONENTS.write().unwrap(); let mut hmap = global::COMPONENTS.write().unwrap();
if let Some(regions) = hmap.get_mut(region) { if let Some(regions) = hmap.get_mut(region) {
regions.add(component); regions.add(component);
} else { } else {

View file

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

View file

@ -1,6 +1,7 @@
use crate::{Lazy, base, trace}; use crate::{Lazy, base, locale, trace};
use crate::config::SETTINGS; 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 crate::core::module::register_module;
use actix_web::middleware::normalize; use actix_web::middleware::normalize;
@ -32,11 +33,20 @@ pub fn run(bootstrap: Option<fn()>) -> Result<Server, std::io::Error> {
); );
} }
// Inicia la traza de la aplicación. // Inicia registro de trazas y eventos.
Lazy::force(&server::tracing::TRACING); Lazy::force(&server::tracing::TRACING);
// Asigna identificador de idioma. // 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. // Ejecuta la función de inicio de la aplicación.
if bootstrap != None { if bootstrap != None {
@ -54,8 +64,8 @@ pub fn run(bootstrap: Option<fn()>) -> Result<Server, std::io::Error> {
server::App::new() server::App::new()
.wrap(tracing_actix_web::TracingLogger) .wrap(tracing_actix_web::TracingLogger)
.wrap(normalize::NormalizePath::new(normalize::TrailingSlash::Trim)) .wrap(normalize::NormalizePath::new(normalize::TrailingSlash::Trim))
.configure(&all::themes) .configure(&global::themes)
.configure(&all::modules) .configure(&global::modules)
}) })
.bind(format!("{}:{}", .bind(format!("{}:{}",
&SETTINGS.webserver.bind_address, &SETTINGS.webserver.bind_address,

View file

@ -4,8 +4,5 @@ pub use actix_web::{
mod tracing; mod tracing;
mod langid;
pub use langid::LANGID;
mod main; mod main;
pub use main::run; pub use main::run;

View file

@ -4,6 +4,19 @@ use crate::config::SETTINGS;
use tracing_appender::non_blocking::WorkerGuard; use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::EnvFilter; 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<WorkerGuard>` se garantiza que todos los registros almacenados se
/// enviarán antes de terminar la ejecución.
pub static TRACING: Lazy<WorkerGuard> = Lazy::new(|| { pub static TRACING: Lazy<WorkerGuard> = Lazy::new(|| {
let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing) let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing)
.unwrap_or(EnvFilter::new("Info")); .unwrap_or(EnvFilter::new("Info"));

View file

@ -1,5 +1,5 @@
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::core::{all, server}; use crate::core::server;
use crate::core::theme::{Markup, html}; use crate::core::theme::{Markup, html};
use crate::core::response::page::{Page, PageAssets, PageComponent}; use crate::core::response::page::{Page, PageAssets, PageComponent};
use crate::base::component::Chunck; use crate::base::component::Chunck;
@ -10,8 +10,8 @@ pub trait Theme: Send + Sync {
fn fullname(&self) -> String; fn fullname(&self) -> String;
fn description(&self) -> String { fn description(&self) -> Option<String> {
"".to_string() None
} }
#[allow(unused_variables)] #[allow(unused_variables)]
@ -25,7 +25,7 @@ pub trait Theme: Send + Sync {
fn render_page_head(&self, page: &mut Page) -> Markup { fn render_page_head(&self, page: &mut Page) -> Markup {
let title = page.title(); let title = page.title();
let title = if title.is_empty() { let title = if title.is_empty() {
SETTINGS.app.name.to_string() SETTINGS.app.name.to_owned()
} else { } else {
[SETTINGS.app.name.to_string(), title.to_string()].join(" | ") [SETTINGS.app.name.to_string(), title.to_string()].join(" | ")
}; };
@ -104,15 +104,3 @@ pub trait Theme: Send + Sync {
.render() .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,
}
}

View file

@ -1,4 +1,18 @@
use crate::core::global;
pub use maud::{DOCTYPE, Markup, PreEscaped, html}; pub use maud::{DOCTYPE, Markup, PreEscaped, html};
mod api; mod definition;
pub use api::{Theme, find_theme, register_theme}; 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,
}
}

View file

@ -8,7 +8,7 @@ pub use once_cell::sync::Lazy;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub mod config; // Gestión de la configuración. 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 locale; // Localización.
pub mod core; // Servidor web y sistemas para Temas, Módulos y Respuestas. pub mod core; // Servidor web y sistemas para Temas, Módulos y Respuestas.
pub mod base; // Temas, Módulos y Componentes base. pub mod base; // Temas, Módulos y Componentes base.

View file

@ -2,12 +2,35 @@ pub use fluent_templates::{static_loader as static_locale, Loader as Locale};
pub use fluent_templates; pub use fluent_templates;
pub use fluent_templates::fluent_bundle::FluentValue; 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<LanguageIdentifier> = 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] #[macro_export]
/// Permite integrar fácilmente localización en temas, módulos y componentes. /// Permite integrar fácilmente localización en temas, módulos y componentes.
macro_rules! localize { macro_rules! localize {
( $DEF_LANGID:literal, $locales:literal $(, $core_locales:literal)? ) => { ( $DEF_LANGID:literal, $locales:literal $(, $core_locales:literal)? ) => {
use $crate::locale::*; use $crate::locale::*;
use $crate::core::server::LANGID;
static_locale! { static_locale! {
static LOCALES = { static LOCALES = {

View file

@ -26,17 +26,17 @@ pub fn valid_id(id: &str) -> Option<String> {
} }
} }
pub fn optional_value(value: &str) -> Option<String> { pub fn optional_str(s: &str) -> Option<String> {
let value = value.to_string(); let s = s.to_owned();
match value.is_empty() { match s.is_empty() {
true => None, true => None,
false => Some(value), false => Some(s),
} }
} }
pub fn assigned_value(value: &Option<String>) -> &str { pub fn assigned_str(optional: &Option<String>) -> &str {
match value { match optional {
Some(value) => value.as_str(), Some(o) => o.as_str(),
_ => "", _ => "",
} }
} }