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:
parent
67952f6840
commit
b6dd473578
34 changed files with 250 additions and 237 deletions
|
|
@ -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<RwLock<Vec<&dyn Theme>>> = 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<RwLock<Vec<&dyn Module>>> = 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) {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
pub use actix_web::dev::Server;
|
||||
|
||||
mod all;
|
||||
mod global;
|
||||
|
||||
pub mod theme;
|
||||
pub mod module;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
16
src/core/module/definition.rs
Normal file
16
src/core/module/definition.rs
Normal 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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!("<link rel=\"{}\"", rel);
|
||||
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),
|
||||
".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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ pub trait PageComponent: Downcast + Send + Sync {
|
|||
}
|
||||
|
||||
fn fullname(&self) -> String {
|
||||
type_name::<Self>().to_string()
|
||||
type_name::<Self>().to_owned()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
fn description(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_renderable(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -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<Option<String>> = Lazy::new(|| {
|
|||
static DEFAULT_DIRECTION: Lazy<Option<String>> = 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<String>,
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -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<fn()>) -> Result<Server, std::io::Error> {
|
|||
);
|
||||
}
|
||||
|
||||
// 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<fn()>) -> Result<Server, std::io::Error> {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,5 @@ pub use actix_web::{
|
|||
|
||||
mod tracing;
|
||||
|
||||
mod langid;
|
||||
pub use langid::LANGID;
|
||||
|
||||
mod main;
|
||||
pub use main::run;
|
||||
|
|
|
|||
|
|
@ -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<WorkerGuard>` se garantiza que todos los registros almacenados se
|
||||
/// enviarán antes de terminar la ejecución.
|
||||
|
||||
pub static TRACING: Lazy<WorkerGuard> = Lazy::new(|| {
|
||||
let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing)
|
||||
.unwrap_or(EnvFilter::new("Info"));
|
||||
|
|
|
|||
|
|
@ -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<String> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue