diff --git a/CREDITS.md b/CREDITS.md index 5b9979f4..4254ed59 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,9 +1,9 @@ # FIGfonts PageTop utiliza el paquete [figlet-rs](https://crates.io/crates/figlet-rs) de -*yuanbohan*, que muestra al inicio de la ejecución un rótulo con el nombre de +*yuanbohan*. Muestra en el terminal un rótulo de presentación con el nombre de la aplicación usando caracteres [FIGlet](http://www.figlet.org/). Las fuentes -incluidas en `resources` son: +incluidas en `src/app/banner` son: * [slant.flf](http://www.figlet.org/fontdb_example.cgi?font=slant.flf) por *Glenn Chappell*. @@ -13,3 +13,10 @@ incluidas en `resources` son: por *Claude Martins*. * [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf) por *Ryan Youck*. + +# Icono + +El monstruo sonriente de Frankenstein es una divertida creación de +[Webalys](https://www.iconfinder.com/webalys). Puede encontrarse en su colección +[Nasty Icons](https://www.iconfinder.com/iconsets/nasty) disponible en +[ICONFINDER](https://www.iconfinder.com/). \ No newline at end of file diff --git a/config/default.toml b/config/default.toml index 5b6982fe..13012a93 100644 --- a/config/default.toml +++ b/config/default.toml @@ -15,7 +15,7 @@ db_user = "drust" db_pass = "DrU__#3T" [log] -tracing = "Info,sqlx::query=Warn" +tracing = "Info,pagetop=Debug,sqlx::query=Warn" [dev] #static_files = "pagetop/static" diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index e3ad0337..a00e7fae 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -7,6 +7,10 @@ mod summary; pub struct AdminModule; impl ModuleTrait for AdminModule { + fn name(&self) -> &'static str { + "Admin" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index af6d8b3f..afcd729f 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -8,6 +8,10 @@ mod migration; pub struct NodeModule; impl ModuleTrait for NodeModule { + fn name(&self) -> &'static str { + "Node" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index c76233e1..343daa7a 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -8,6 +8,10 @@ mod migration; pub struct UserModule; impl ModuleTrait for UserModule { + fn name(&self) -> &'static str { + "User" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 4d92b378..a260d17f 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.3" +version = "0.0.4" edition = "2021" authors = [ diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 4ed2c1da..070390c8 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -27,13 +27,18 @@ impl Application { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] Lazy::force(&app::db::DBCONN); + // Registra los temas predeterminados. + theme::register_theme(&base::theme::aliner::AlinerTheme); + theme::register_theme(&base::theme::minimal::MinimalTheme); + theme::register_theme(&base::theme::bootsier::BootsierTheme); + // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); let _ = &bootstrap(); - // Registra el módulo para una página de presentación de PageTop. + // Registra el módulo de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. - module::register_module(&base::module::homepage::HomepageModule); + module::register_module(&base::module::demopage::DemopageModule); // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 4f658c9e..96fce677 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -71,7 +71,7 @@ impl Block { } pub fn with_title(mut self, title: &str) -> Self { - self.title = util::optional_str(title); + self.title = util::valid_str(title); self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index c76c49dd..57810fea 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -101,7 +101,7 @@ impl Button { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index ccc6ab31..6614670a 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -112,17 +112,17 @@ impl Date { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::optional_str(label); + self.label = util::valid_str(label); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_str(placeholder); + self.placeholder = util::valid_str(placeholder); self } @@ -167,7 +167,7 @@ impl Date { } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::optional_str(help_text); + self.help_text = util::valid_str(help_text); self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 63eace0c..2fac4403 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -76,7 +76,7 @@ impl Form { } pub fn with_action(mut self, action: &str) -> Self { - self.action = util::optional_str(action); + self.action = util::valid_str(action); self } @@ -86,7 +86,7 @@ impl Form { } pub fn with_charset(mut self, charset: &str) -> Self { - self.charset = util::optional_str(charset); + self.charset = util::valid_str(charset); self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 9ac0a4f9..bd158b85 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -54,7 +54,7 @@ impl Hidden { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 884d2232..f0e73a63 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -167,12 +167,12 @@ impl Input { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::optional_str(label); + self.label = util::valid_str(label); self } @@ -192,7 +192,7 @@ impl Input { } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_str(placeholder); + self.placeholder = util::valid_str(placeholder); self } @@ -237,7 +237,7 @@ impl Input { } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::optional_str(help_text); + self.help_text = util::valid_str(help_text); self } diff --git a/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl similarity index 95% rename from pagetop/src/base/module/homepage/locales/en-US/homepage.ftl rename to pagetop/src/base/module/demopage/locales/en-US/demopage.ftl index 39a5e426..14c93f2f 100644 --- a/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl +++ b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl @@ -1,5 +1,5 @@ module_fullname = Default homepage -module_description = Displays a default homepage when none is configured. +module_description = Displays a demo homepage when none is configured. page_title = Hello world! diff --git a/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl similarity index 93% rename from pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl rename to pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl index f1d85b2e..39720fcd 100644 --- a/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl +++ b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl @@ -1,5 +1,5 @@ module_fullname = Página de inicio predeterminada -module_description = Muestra una página de inicio predeterminada cuando no hay ninguna configurada. +module_description = Muestra una página de demostración predeterminada cuando no hay ninguna configurada. page_title = ¡Hola mundo! diff --git a/pagetop/src/base/module/homepage/mod.rs b/pagetop/src/base/module/demopage/mod.rs similarity index 91% rename from pagetop/src/base/module/homepage/mod.rs rename to pagetop/src/base/module/demopage/mod.rs index bd364534..bb6e3b94 100644 --- a/pagetop/src/base/module/homepage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -1,10 +1,14 @@ use crate::prelude::*; -localize!("src/base/module/homepage/locales"); +localize!("src/base/module/demopage/locales"); -pub struct HomepageModule; +pub struct DemopageModule; + +impl ModuleTrait for DemopageModule { + fn name(&self) -> &'static str { + "Demopage" + } -impl ModuleTrait for HomepageModule { fn fullname(&self) -> String { l("module_fullname") } @@ -20,9 +24,13 @@ impl ModuleTrait for HomepageModule { async fn home() -> app::Result { Page::prepare() + .using_theme("Bootsier") .with_title( l("page_title").as_str() ) + + + .add_to("content", Container::prepare() .with_id("welcome") .add(Chunck::markup(html! { diff --git a/pagetop/src/base/module/mod.rs b/pagetop/src/base/module/mod.rs index 070e5b82..7107d180 100644 --- a/pagetop/src/base/module/mod.rs +++ b/pagetop/src/base/module/mod.rs @@ -1 +1 @@ -pub mod homepage; +pub mod demopage; diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index 07b1470f..d4f4f252 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -6,7 +6,7 @@ pub struct AlinerTheme; impl ThemeTrait for AlinerTheme { fn name(&self) -> &'static str { - "aliner" + "Aliner" } fn fullname(&self) -> String { @@ -19,6 +19,10 @@ impl ThemeTrait for AlinerTheme { fn before_render_page(&self, page: &mut Page) { page.assets() + .with_favicon( + Favicon::new() + .with_icon("/theme/favicon.png") + ) .add_stylesheet( StyleSheet::source( "/aliner/css/styles.css" diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index dbd31727..ada65b0e 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -8,7 +8,7 @@ pub struct BootsierTheme; impl ThemeTrait for BootsierTheme { fn name(&self) -> &'static str { - "bootsier" + "Bootsier" } fn fullname(&self) -> String { @@ -23,7 +23,7 @@ impl ThemeTrait for BootsierTheme { page.assets() .with_favicon( Favicon::new() - .with_icon("/bootsier/favicon.png") + .with_icon("/theme/favicon.png") ) .add_stylesheet( StyleSheet::source( diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs index b3a50906..471b3738 100644 --- a/pagetop/src/base/theme/minimal/mod.rs +++ b/pagetop/src/base/theme/minimal/mod.rs @@ -4,7 +4,7 @@ pub struct MinimalTheme; impl ThemeTrait for MinimalTheme { fn name(&self) -> &'static str { - "minimal" + "Minimal" } fn fullname(&self) -> String { diff --git a/pagetop/src/module/all.rs b/pagetop/src/module/all.rs index 120c59b6..c95583e9 100644 --- a/pagetop/src/module/all.rs +++ b/pagetop/src/module/all.rs @@ -10,13 +10,24 @@ static MODULES: Lazy>> = Lazy::new(|| { }); pub fn register_module(module: &'static dyn ModuleTrait) { - let mut modules = MODULES.write().unwrap(); - match modules.iter().find(|m| m.name() == module.name()) { - None => { - trace::info!("{}", module.name()); - modules.push(module); - }, - Some(_) => {}, + let mut list: Vec<&dyn ModuleTrait> = Vec::new(); + add_to(&mut list, module); + list.reverse(); + MODULES.write().unwrap().append(&mut list); +} + +fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { + if !MODULES.read().unwrap().iter().any(|m| m.name() == module.name()) { + if !list.iter().any(|m| m.name() == module.name()) { + trace::debug!("Registering \"{}\" module", module.name()); + list.push(module); + + let mut dependencies = module.dependencies(); + dependencies.reverse(); + for d in dependencies.iter() { + add_to(list, *d); + } + } } } diff --git a/pagetop/src/module/definition.rs b/pagetop/src/module/definition.rs index 9424fbd8..b01f9801 100644 --- a/pagetop/src/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -3,17 +3,9 @@ use crate::app; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; -use std::any::type_name; - /// Los módulos deben implementar este *trait*. pub trait ModuleTrait: Send + Sync { - fn name(&self) -> &'static str { - let name = type_name::(); - match name.rfind("::") { - Some(position) => &name[(position + 2)..], - None => name - } - } + fn name(&self) -> &'static str; fn fullname(&self) -> String; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 58541d22..eff38daa 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -75,7 +75,7 @@ impl<'a> Page<'a> { // Page BUILDER. pub fn with_language(&mut self, language: &str) -> &mut Self { - self.language = util::optional_str(language); + self.language = util::valid_str(language); self } @@ -89,12 +89,12 @@ impl<'a> Page<'a> { } pub fn with_title(&mut self, title: &str) -> &mut Self { - self.title = util::optional_str(title); + self.title = util::valid_str(title); self } pub fn with_description(&mut self, description: &str) -> &mut Self { - self.description = util::optional_str(description); + self.description = util::valid_str(description); self } diff --git a/pagetop/src/theme/all.rs b/pagetop/src/theme/all.rs index cc25d9d8..ee0bfedb 100644 --- a/pagetop/src/theme/all.rs +++ b/pagetop/src/theme/all.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, app, base, theme_static_files, trace}; +use crate::{Lazy, app, theme_static_files, trace}; use super::ThemeTrait; use std::sync::RwLock; @@ -7,21 +7,14 @@ include!(concat!(env!("OUT_DIR"), "/theme.rs")); // Temas registrados. 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 register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); - match themes.iter().find(|t| t.name() == theme.name()) { - None => { - trace::info!("{}", theme.name()); - themes.push(theme); - }, - Some(_) => {}, + if !themes.iter().any(|t| t.name() == theme.name()) { + trace::debug!("Registering \"{}\" theme", theme.name()); + themes.push(theme); } } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 727df347..733736e2 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,7 +1,7 @@ use crate::app; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::response::page::{Page, PageAssets, PageComponent}; +use crate::response::page::{Favicon, Page, PageAssets, PageComponent}; use crate::base::component::Chunck; /// Los temas deben implementar este "trait". @@ -20,6 +20,11 @@ pub trait ThemeTrait: Send + Sync { #[allow(unused_variables)] fn before_render_page(&self, page: &mut Page) { + page.assets() + .with_favicon( + Favicon::new() + .with_icon("/theme/favicon.png") + ); } fn render_page_head(&self, page: &mut Page) -> Markup { diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index c5254618..4ba4f76e 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -37,24 +37,24 @@ macro_rules! theme_static_files { } pub fn valid_id(id: &str) -> Option { - let id = id.trim().replace(" ", "_").to_lowercase(); + let id = id.trim(); match id.is_empty() { true => None, - false => Some(id), + false => Some(id.replace(" ", "_").to_lowercase()), } } -pub fn optional_str(s: &str) -> Option { - let s = s.to_owned(); +pub fn valid_str(s: &str) -> Option { + let s = s.trim(); match s.is_empty() { true => None, - false => Some(s), + false => Some(s.to_owned()), } } pub fn assigned_str(optional: &Option) -> &str { match optional { Some(o) => o.as_str(), - _ => "", + None => "", } } diff --git a/pagetop/static/theme/favicon.png b/pagetop/static/theme/favicon.png new file mode 100644 index 00000000..7d38ea4a Binary files /dev/null and b/pagetop/static/theme/favicon.png differ