Libera la versión de desarrollo 0.0.4

This commit is contained in:
Manuel Cillero 2022-03-25 20:24:19 +01:00
parent d72e1ccad5
commit 5b1064fda2
27 changed files with 104 additions and 67 deletions

View file

@ -1,9 +1,9 @@
# FIGfonts # FIGfonts
PageTop utiliza el paquete [figlet-rs](https://crates.io/crates/figlet-rs) de 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 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) * [slant.flf](http://www.figlet.org/fontdb_example.cgi?font=slant.flf)
por *Glenn Chappell*. por *Glenn Chappell*.
@ -13,3 +13,10 @@ incluidas en `resources` son:
por *Claude Martins*. por *Claude Martins*.
* [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf) * [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf)
por *Ryan Youck*. 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/).

View file

@ -15,7 +15,7 @@ db_user = "drust"
db_pass = "DrU__#3T" db_pass = "DrU__#3T"
[log] [log]
tracing = "Info,sqlx::query=Warn" tracing = "Info,pagetop=Debug,sqlx::query=Warn"
[dev] [dev]
#static_files = "pagetop/static" #static_files = "pagetop/static"

View file

@ -7,6 +7,10 @@ mod summary;
pub struct AdminModule; pub struct AdminModule;
impl ModuleTrait for AdminModule { impl ModuleTrait for AdminModule {
fn name(&self) -> &'static str {
"Admin"
}
fn fullname(&self) -> String { fn fullname(&self) -> String {
l("module_fullname") l("module_fullname")
} }

View file

@ -8,6 +8,10 @@ mod migration;
pub struct NodeModule; pub struct NodeModule;
impl ModuleTrait for NodeModule { impl ModuleTrait for NodeModule {
fn name(&self) -> &'static str {
"Node"
}
fn fullname(&self) -> String { fn fullname(&self) -> String {
l("module_fullname") l("module_fullname")
} }

View file

@ -8,6 +8,10 @@ mod migration;
pub struct UserModule; pub struct UserModule;
impl ModuleTrait for UserModule { impl ModuleTrait for UserModule {
fn name(&self) -> &'static str {
"User"
}
fn fullname(&self) -> String { fn fullname(&self) -> String {
l("module_fullname") l("module_fullname")
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "pagetop" name = "pagetop"
version = "0.0.3" version = "0.0.4"
edition = "2021" edition = "2021"
authors = [ authors = [

View file

@ -27,13 +27,18 @@ impl Application {
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
Lazy::force(&app::db::DBCONN); 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. // Ejecuta la función de inicio de la aplicación.
trace::info!("Calling application bootstrap"); trace::info!("Calling application bootstrap");
let _ = &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. // 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). // Actualizaciones pendientes de la base de datos (opcional).
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]

View file

@ -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 = util::optional_str(title); self.title = util::valid_str(title);
self self
} }

View file

@ -101,7 +101,7 @@ impl Button {
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_str(value); self.value = util::valid_str(value);
self self
} }

View file

@ -112,17 +112,17 @@ impl Date {
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_str(value); self.value = util::valid_str(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label = util::optional_str(label); self.label = util::valid_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_str(placeholder); self.placeholder = util::valid_str(placeholder);
self self
} }
@ -167,7 +167,7 @@ impl Date {
} }
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 = util::optional_str(help_text); self.help_text = util::valid_str(help_text);
self self
} }

View file

@ -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_str(action); self.action = util::valid_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_str(charset); self.charset = util::valid_str(charset);
self self
} }

View file

@ -54,7 +54,7 @@ impl Hidden {
} }
pub fn with_value(mut self, value: &str) -> Self { pub fn with_value(mut self, value: &str) -> Self {
self.value = util::optional_str(value); self.value = util::valid_str(value);
self self
} }

View file

@ -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_str(value); self.value = util::valid_str(value);
self self
} }
pub fn with_label(mut self, label: &str) -> Self { pub fn with_label(mut self, label: &str) -> Self {
self.label = util::optional_str(label); self.label = util::valid_str(label);
self self
} }
@ -192,7 +192,7 @@ impl Input {
} }
pub fn with_placeholder(mut self, placeholder: &str) -> Self { pub fn with_placeholder(mut self, placeholder: &str) -> Self {
self.placeholder = util::optional_str(placeholder); self.placeholder = util::valid_str(placeholder);
self self
} }
@ -237,7 +237,7 @@ impl Input {
} }
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 = util::optional_str(help_text); self.help_text = util::valid_str(help_text);
self self
} }

View file

@ -1,5 +1,5 @@
module_fullname = Default homepage 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! page_title = Hello world!

View file

@ -1,5 +1,5 @@
module_fullname = Página de inicio predeterminada 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! page_title = ¡Hola mundo!

View file

@ -1,10 +1,14 @@
use crate::prelude::*; 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 { fn fullname(&self) -> String {
l("module_fullname") l("module_fullname")
} }
@ -20,9 +24,13 @@ impl ModuleTrait for HomepageModule {
async fn home() -> app::Result<Markup> { async fn home() -> app::Result<Markup> {
Page::prepare() Page::prepare()
.using_theme("Bootsier")
.with_title( .with_title(
l("page_title").as_str() l("page_title").as_str()
) )
.add_to("content", Container::prepare() .add_to("content", Container::prepare()
.with_id("welcome") .with_id("welcome")
.add(Chunck::markup(html! { .add(Chunck::markup(html! {

View file

@ -1 +1 @@
pub mod homepage; pub mod demopage;

View file

@ -6,7 +6,7 @@ pub struct AlinerTheme;
impl ThemeTrait for AlinerTheme { impl ThemeTrait for AlinerTheme {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"aliner" "Aliner"
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
@ -19,6 +19,10 @@ impl ThemeTrait for AlinerTheme {
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.assets() page.assets()
.with_favicon(
Favicon::new()
.with_icon("/theme/favicon.png")
)
.add_stylesheet( .add_stylesheet(
StyleSheet::source( StyleSheet::source(
"/aliner/css/styles.css" "/aliner/css/styles.css"

View file

@ -8,7 +8,7 @@ pub struct BootsierTheme;
impl ThemeTrait for BootsierTheme { impl ThemeTrait for BootsierTheme {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"bootsier" "Bootsier"
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {
@ -23,7 +23,7 @@ impl ThemeTrait for BootsierTheme {
page.assets() page.assets()
.with_favicon( .with_favicon(
Favicon::new() Favicon::new()
.with_icon("/bootsier/favicon.png") .with_icon("/theme/favicon.png")
) )
.add_stylesheet( .add_stylesheet(
StyleSheet::source( StyleSheet::source(

View file

@ -4,7 +4,7 @@ pub struct MinimalTheme;
impl ThemeTrait for MinimalTheme { impl ThemeTrait for MinimalTheme {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"minimal" "Minimal"
} }
fn fullname(&self) -> String { fn fullname(&self) -> String {

View file

@ -10,13 +10,24 @@ static MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
}); });
pub fn register_module(module: &'static dyn ModuleTrait) { pub fn register_module(module: &'static dyn ModuleTrait) {
let mut modules = MODULES.write().unwrap(); let mut list: Vec<&dyn ModuleTrait> = Vec::new();
match modules.iter().find(|m| m.name() == module.name()) { add_to(&mut list, module);
None => { list.reverse();
trace::info!("{}", module.name()); MODULES.write().unwrap().append(&mut list);
modules.push(module); }
},
Some(_) => {}, 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);
}
}
} }
} }

View file

@ -3,17 +3,9 @@ use crate::app;
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
use crate::db; use crate::db;
use std::any::type_name;
/// Los módulos deben implementar este *trait*. /// Los módulos deben implementar este *trait*.
pub trait ModuleTrait: Send + Sync { pub trait ModuleTrait: Send + Sync {
fn name(&self) -> &'static str { fn name(&self) -> &'static str;
let name = type_name::<Self>();
match name.rfind("::") {
Some(position) => &name[(position + 2)..],
None => name
}
}
fn fullname(&self) -> String; fn fullname(&self) -> String;

View file

@ -75,7 +75,7 @@ impl<'a> Page<'a> {
// 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_str(language); self.language = util::valid_str(language);
self self
} }
@ -89,12 +89,12 @@ impl<'a> Page<'a> {
} }
pub fn with_title(&mut self, title: &str) -> &mut Self { pub fn with_title(&mut self, title: &str) -> &mut Self {
self.title = util::optional_str(title); self.title = util::valid_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_str(description); self.description = util::valid_str(description);
self self
} }

View file

@ -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 super::ThemeTrait;
use std::sync::RwLock; use std::sync::RwLock;
@ -7,21 +7,14 @@ include!(concat!(env!("OUT_DIR"), "/theme.rs"));
// Temas registrados. // Temas registrados.
static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(|| { static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(|| {
RwLock::new(vec![ RwLock::new(Vec::new())
&base::theme::aliner::AlinerTheme,
&base::theme::minimal::MinimalTheme,
&base::theme::bootsier::BootsierTheme,
])
}); });
pub fn register_theme(theme: &'static dyn ThemeTrait) { pub fn register_theme(theme: &'static dyn ThemeTrait) {
let mut themes = THEMES.write().unwrap(); let mut themes = THEMES.write().unwrap();
match themes.iter().find(|t| t.name() == theme.name()) { if !themes.iter().any(|t| t.name() == theme.name()) {
None => { trace::debug!("Registering \"{}\" theme", theme.name());
trace::info!("{}", theme.name()); themes.push(theme);
themes.push(theme);
},
Some(_) => {},
} }
} }

View file

@ -1,7 +1,7 @@
use crate::app; use crate::app;
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Markup, html}; 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; use crate::base::component::Chunck;
/// Los temas deben implementar este "trait". /// Los temas deben implementar este "trait".
@ -20,6 +20,11 @@ pub trait ThemeTrait: Send + Sync {
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) { 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 { fn render_page_head(&self, page: &mut Page) -> Markup {

View file

@ -37,24 +37,24 @@ macro_rules! theme_static_files {
} }
pub fn valid_id(id: &str) -> Option<String> { pub fn valid_id(id: &str) -> Option<String> {
let id = id.trim().replace(" ", "_").to_lowercase(); let id = id.trim();
match id.is_empty() { match id.is_empty() {
true => None, true => None,
false => Some(id), false => Some(id.replace(" ", "_").to_lowercase()),
} }
} }
pub fn optional_str(s: &str) -> Option<String> { pub fn valid_str(s: &str) -> Option<String> {
let s = s.to_owned(); let s = s.trim();
match s.is_empty() { match s.is_empty() {
true => None, true => None,
false => Some(s), false => Some(s.to_owned()),
} }
} }
pub fn assigned_str(optional: &Option<String>) -> &str { pub fn assigned_str(optional: &Option<String>) -> &str {
match optional { match optional {
Some(o) => o.as_str(), Some(o) => o.as_str(),
_ => "", None => "",
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB