Actualiza formato del código aplicando cargo fmt

This commit is contained in:
Manuel Cillero 2022-07-20 00:01:01 +02:00
parent 4b5caf06a7
commit e6ea59785e
75 changed files with 1069 additions and 1160 deletions

View file

@ -22,16 +22,11 @@ impl ModuleTrait for Admin {
}
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
cfg.service(
app::web::scope("/admin")
.route("", app::web::get().to(summary::summary))
);
cfg.service(app::web::scope("/admin").route("", app::web::get().to(summary::summary)));
}
fn actions(&self) -> Vec<HookAction> {
vec![
hook_action!(BeforeRenderPageHook => before_render_page)
]
vec![hook_action!(BeforeRenderPageHook => before_render_page)]
}
}

View file

@ -1,19 +1,23 @@
use pagetop::prelude::*;
use super::l;
use pagetop::prelude::*;
pub async fn summary() -> app::Result<Markup> {
let top_menu = Menu::new()
.with_item(MenuItem::label(l("module_name").as_str()))
.with_item(MenuItem::link("Opción 2", "https://www.google.es"))
.with_item(MenuItem::link_blank("Opción 3", "https://www.google.es"))
.with_item(MenuItem::submenu("Submenú 1", Menu::new()
.with_item(MenuItem::submenu(
"Submenú 1",
Menu::new()
.with_item(MenuItem::label("Opción 1"))
.with_item(MenuItem::label("Opción 2"))
.with_item(MenuItem::label("Opción 2")),
))
.with_item(MenuItem::separator())
.with_item(MenuItem::submenu("Submenú 2", Menu::new()
.with_item(MenuItem::submenu(
"Submenú 2",
Menu::new()
.with_item(MenuItem::label("Opción 1"))
.with_item(MenuItem::label("Opción 2"))
.with_item(MenuItem::label("Opción 2")),
))
.with_item(MenuItem::label("Opción 4"));
@ -21,38 +25,33 @@ pub async fn summary() -> app::Result<Markup> {
.with_item(MenuItem::label("Opción 1"))
.with_item(MenuItem::link("Opción 2", "https://www.google.es"))
.with_item(MenuItem::link_blank("Opción 3", "https://www.google.es"))
.with_item(MenuItem::submenu("Submenú 1", Menu::new()
.with_item(MenuItem::submenu(
"Submenú 1",
Menu::new()
.with_item(MenuItem::label("Opción 1"))
.with_item(MenuItem::label("Opción 2"))
.with_item(MenuItem::label("Opción 2")),
))
.with_item(MenuItem::separator())
.with_item(MenuItem::submenu("Submenú 2", Menu::new()
.with_item(MenuItem::submenu(
"Submenú 2",
Menu::new()
.with_item(MenuItem::label("Opción 1"))
.with_item(MenuItem::label("Opción 2"))
.with_item(MenuItem::label("Opción 2")),
))
.with_item(MenuItem::label("Opción 4"));
Page::new()
.with_context(InContextOp::SetTheme("Bootsier"))
.with_title("Admin")
.add_to("top-menu", top_menu)
.add_to("content", grid::Row::new()
.with_column(grid::Column::new()
.with_component(side_menu)
)
.with_column(grid::Column::new()
.with_component(Chunck::with(html! {
.add_to(
"content",
grid::Row::new()
.with_column(grid::Column::new().with_component(side_menu))
.with_column(grid::Column::new().with_component(Chunck::with(html! {
p { "Columna 2"}
}))
}))),
)
)
.using_template("admin")
.render()
}

View file

@ -27,9 +27,7 @@ impl ModuleTrait for Node {
}
fn actions(&self) -> Vec<HookAction> {
vec![
hook_action!(BeforeRenderPageHook => before_render_page, -1)
]
vec![hook_action!(BeforeRenderPageHook => before_render_page, -1)]
}
fn migrations(&self) -> Vec<MigrationItem> {
@ -43,11 +41,7 @@ impl ModuleTrait for Node {
}
async fn node() -> app::Result<Markup> {
Page::new()
.with_title(
"Nodo"
)
.render()
Page::new().with_title("Nodo").render()
}
fn before_render_page(page: &mut Page) {

View file

@ -24,61 +24,35 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(NodeType::Table)
.if_not_exists()
.col(ColumnDef::new(NodeType::Type)
.col(
ColumnDef::new(NodeType::Type)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeType::Name)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::Description)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::Help)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::HasTitle)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::TitleLabel)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::Custom)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::Locked)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::Disabled)
.string()
.not_null()
)
.col(ColumnDef::new(NodeType::OrigType)
.string()
.not_null()
)
.to_owned()
.col(ColumnDef::new(NodeType::Name).string().not_null())
.col(ColumnDef::new(NodeType::Description).string().not_null())
.col(ColumnDef::new(NodeType::Help).string().not_null())
.col(ColumnDef::new(NodeType::HasTitle).string().not_null())
.col(ColumnDef::new(NodeType::TitleLabel).string().not_null())
.col(ColumnDef::new(NodeType::Custom).string().not_null())
.col(ColumnDef::new(NodeType::Locked).string().not_null())
.col(ColumnDef::new(NodeType::Disabled).string().not_null())
.col(ColumnDef::new(NodeType::OrigType).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(NodeType::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(NodeType::Table).to_owned())
.await
}
}

View file

@ -31,77 +31,39 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(Node::Table)
.if_not_exists()
.col(ColumnDef::new(Node::Nid)
.col(
ColumnDef::new(Node::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(Node::Vid)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Type)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Language)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Title)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Uid)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Status)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Created)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Changed)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Comment)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Promote)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Sticky)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Tnid)
.string()
.not_null()
)
.col(ColumnDef::new(Node::Translate)
.string()
.not_null()
)
.to_owned()
.col(ColumnDef::new(Node::Vid).string().not_null())
.col(ColumnDef::new(Node::Type).string().not_null())
.col(ColumnDef::new(Node::Language).string().not_null())
.col(ColumnDef::new(Node::Title).string().not_null())
.col(ColumnDef::new(Node::Uid).string().not_null())
.col(ColumnDef::new(Node::Status).string().not_null())
.col(ColumnDef::new(Node::Created).string().not_null())
.col(ColumnDef::new(Node::Changed).string().not_null())
.col(ColumnDef::new(Node::Comment).string().not_null())
.col(ColumnDef::new(Node::Promote).string().not_null())
.col(ColumnDef::new(Node::Sticky).string().not_null())
.col(ColumnDef::new(Node::Tnid).string().not_null())
.col(ColumnDef::new(Node::Translate).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(Node::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(Node::Table).to_owned())
.await
}
}

View file

@ -23,45 +23,31 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(NodeAccess::Table)
.if_not_exists()
.col(ColumnDef::new(NodeAccess::Nid)
.col(
ColumnDef::new(NodeAccess::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeAccess::Gid)
.string()
.not_null()
)
.col(ColumnDef::new(NodeAccess::Realm)
.string()
.not_null()
)
.col(ColumnDef::new(NodeAccess::GrantView)
.string()
.not_null()
)
.col(ColumnDef::new(NodeAccess::GrantUpdate)
.string()
.not_null()
)
.col(ColumnDef::new(NodeAccess::GrantDelete)
.string()
.not_null()
)
.to_owned()
.col(ColumnDef::new(NodeAccess::Gid).string().not_null())
.col(ColumnDef::new(NodeAccess::Realm).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantView).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantUpdate).string().not_null())
.col(ColumnDef::new(NodeAccess::GrantDelete).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(NodeAccess::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(NodeAccess::Table).to_owned())
.await
}
}

View file

@ -25,61 +25,35 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(NodeRevision::Table)
.if_not_exists()
.col(ColumnDef::new(NodeRevision::Nid)
.col(
ColumnDef::new(NodeRevision::Nid)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(NodeRevision::Vid)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Uid)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Title)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Log)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Timestamp)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Status)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Comment)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Promote)
.string()
.not_null()
)
.col(ColumnDef::new(NodeRevision::Sticky)
.string()
.not_null()
)
.to_owned()
.col(ColumnDef::new(NodeRevision::Vid).string().not_null())
.col(ColumnDef::new(NodeRevision::Uid).string().not_null())
.col(ColumnDef::new(NodeRevision::Title).string().not_null())
.col(ColumnDef::new(NodeRevision::Log).string().not_null())
.col(ColumnDef::new(NodeRevision::Timestamp).string().not_null())
.col(ColumnDef::new(NodeRevision::Status).string().not_null())
.col(ColumnDef::new(NodeRevision::Comment).string().not_null())
.col(ColumnDef::new(NodeRevision::Promote).string().not_null())
.col(ColumnDef::new(NodeRevision::Sticky).string().not_null())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(NodeRevision::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(NodeRevision::Table).to_owned())
.await
}
}

View file

@ -37,12 +37,12 @@ impl ModuleTrait for User {
async fn login() -> app::Result<Markup> {
Page::new()
.with_title(
"Identificación del usuario"
)
.add_to("content", Container::new()
.with_title("Identificación del usuario")
.add_to(
"content",
Container::new()
.with_id("welcome")
.with_component(form_login())
.with_component(form_login()),
)
.render()
}
@ -50,18 +50,26 @@ async fn login() -> app::Result<Markup> {
fn form_login() -> Form {
Form::new()
.with_id("user-login")
.with_element(form::Input::textfield()
.with_element(
form::Input::textfield()
.with_name("name")
.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_owned()
]).as_str())
.with_autofocus(true)
],
)
.with_element(form::Input::password()
.as_str(),
)
.with_autofocus(true),
)
.with_element(
form::Input::password()
.with_name("pass")
.with_label(l("password").as_str())
.with_help_text(l("password_help").as_str())
.with_help_text(l("password_help").as_str()),
)
.with_element(form::Button::submit(l("login").as_str()))
}

View file

@ -14,51 +14,57 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(Role::Table)
.if_not_exists()
.col(ColumnDef::new(Role::Rid)
.col(
ColumnDef::new(Role::Rid)
.unsigned()
.not_null()
.auto_increment()
.primary_key()
.primary_key(),
)
.col(ColumnDef::new(Role::Name)
.col(
ColumnDef::new(Role::Name)
.string_len(64)
.not_null()
.unique_key()
.unique_key(),
)
.col(ColumnDef::new(Role::Weight)
.col(
ColumnDef::new(Role::Weight)
.integer()
.not_null()
.default(10)
.default(10),
)
// INDEXES.
.index(Index::create()
.index(
Index::create()
.name("weight-name")
.col(Role::Weight)
.col(Role::Name)
.col(Role::Name),
)
.to_owned()
.to_owned(),
)
.await?;
// Built-in roles.
app::db::exec::<InsertStatement>(Query::insert()
app::db::exec::<InsertStatement>(
Query::insert()
.into_table(Role::Table)
.columns(vec![Role::Name, Role::Weight])
.values_panic(vec!["anonymous".into(), "1".into()])
.values_panic(vec!["authenticated".into(), "2".into()])
.values_panic(vec!["administrator".into(), "3".into()])
.values_panic(vec!["administrator".into(), "3".into()]),
)
.await.map(|_| ())
.await
.map(|_| ())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(Role::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(Role::Table).to_owned())
.await
}
}

View file

@ -9,50 +9,55 @@ enum RolePermission {
}
#[derive(Iden)]
enum Role { Table, Rid, /* ... */ }
enum Role {
Table,
Rid,
/* ... */
}
pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(RolePermission::Table)
.if_not_exists()
.col(ColumnDef::new(RolePermission::Rid)
.unsigned()
.not_null()
)
.col(ColumnDef::new(RolePermission::Permission)
.col(ColumnDef::new(RolePermission::Rid).unsigned().not_null())
.col(
ColumnDef::new(RolePermission::Permission)
.string_len(128)
.not_null()
.not_null(),
)
// INDEXES.
.primary_key(Index::create()
.primary_key(
Index::create()
.col(RolePermission::Rid)
.col(RolePermission::Permission)
.col(RolePermission::Permission),
)
.index(Index::create()
.index(
Index::create()
.name("permission")
.col(RolePermission::Permission)
.col(RolePermission::Permission),
)
.foreign_key(ForeignKey::create()
.foreign_key(
ForeignKey::create()
.name("fk_role_permission-rid")
.from(RolePermission::Table, RolePermission::Rid)
.to(Role::Table, Role::Rid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.to_owned()
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(RolePermission::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(RolePermission::Table).to_owned())
.await
}
}

View file

@ -21,59 +21,39 @@ pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(User::Table)
.if_not_exists()
.col(ColumnDef::new(User::Uid)
.col(
ColumnDef::new(User::Uid)
.unsigned()
.not_null()
.primary_key()
.primary_key(),
)
.col(ColumnDef::new(User::Name)
.col(
ColumnDef::new(User::Name)
.string_len(60)
.not_null()
.unique_key()
.unique_key(),
)
.col(ColumnDef::new(User::Pass)
.string_len(128)
.not_null()
)
.col(ColumnDef::new(User::Mail)
.string_len(255)
)
.col(ColumnDef::new(User::Created)
.timestamp()
.not_null()
)
.col(ColumnDef::new(User::Changed)
.timestamp()
.not_null()
)
.col(ColumnDef::new(User::Access)
.timestamp()
.not_null()
)
.col(ColumnDef::new(User::Login)
.timestamp()
.not_null()
)
.col(ColumnDef::new(User::Status)
.boolean()
.not_null()
)
.col(ColumnDef::new(User::Timezone)
.string_len(32)
)
.to_owned()
.col(ColumnDef::new(User::Pass).string_len(128).not_null())
.col(ColumnDef::new(User::Mail).string_len(255))
.col(ColumnDef::new(User::Created).timestamp().not_null())
.col(ColumnDef::new(User::Changed).timestamp().not_null())
.col(ColumnDef::new(User::Access).timestamp().not_null())
.col(ColumnDef::new(User::Login).timestamp().not_null())
.col(ColumnDef::new(User::Status).boolean().not_null())
.col(ColumnDef::new(User::Timezone).string_len(32))
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(User::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(User::Table).to_owned())
.await
}
}

View file

@ -9,56 +9,57 @@ enum UserRole {
}
#[derive(Iden)]
enum User { Table, Uid, /* ... */ }
enum User {
Table,
Uid,
/* ... */
}
#[derive(Iden)]
enum Role { Table, Rid, /* ... */ }
enum Role {
Table,
Rid,
/* ... */
}
pub_migration!(Migration);
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.create_table(Table::create()
manager
.create_table(
Table::create()
.table(UserRole::Table)
.if_not_exists()
.col(ColumnDef::new(UserRole::Uid)
.unsigned()
.not_null()
)
.col(ColumnDef::new(UserRole::Rid)
.unsigned()
.not_null()
)
.col(ColumnDef::new(UserRole::Uid).unsigned().not_null())
.col(ColumnDef::new(UserRole::Rid).unsigned().not_null())
// INDEXES.
.primary_key(Index::create()
.col(UserRole::Uid)
.col(UserRole::Rid)
)
.foreign_key(ForeignKey::create()
.primary_key(Index::create().col(UserRole::Uid).col(UserRole::Rid))
.foreign_key(
ForeignKey::create()
.name("fk_user_role-uid")
.from(UserRole::Table, UserRole::Uid)
.to(User::Table, User::Uid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.foreign_key(ForeignKey::create()
.foreign_key(
ForeignKey::create()
.name("fk_user_role-rid")
.from(UserRole::Table, UserRole::Rid)
.to(Role::Table, Role::Rid)
.on_delete(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict)
.on_update(ForeignKeyAction::Restrict),
)
.to_owned()
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager.drop_table(Table::drop()
.table(UserRole::Table)
.to_owned()
)
manager
.drop_table(Table::drop().table(UserRole::Table).to_owned())
.await
}
}

View file

@ -13,7 +13,7 @@ fn main() -> std::io::Result<()> {
fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> {
let mut resource = resource_dir(dir);
resource.with_generated_filename(
Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name))
Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)),
);
resource.with_module_name(format!("resources_{}", name));
resource.build()

View file

@ -1,6 +1,4 @@
pub use actix_web::{
App, HttpRequest, HttpResponse, HttpServer, Responder, Result, http, web
};
pub use actix_web::{http, web, App, HttpRequest, HttpResponse, HttpServer, Responder, Result};
mod banner;

View file

@ -1,10 +1,10 @@
use crate::{Lazy, base, trace};
use super::AppTrait;
use crate::config::SETTINGS;
use crate::core::{module, theme};
use super::AppTrait;
use crate::{base, trace, Lazy};
use std::io::Error;
use actix_web::dev::Server;
use std::io::Error;
pub struct Application {
server: Server,
@ -26,9 +26,7 @@ impl Application {
Lazy::force(&super::db::DBCONN);
// Habilita los módulos predeterminados.
module::all::enable_modules(vec![
&base::module::homepage::DefaultHomePage,
]);
module::all::enable_modules(vec![&base::module::homepage::DefaultHomePage]);
// Habilita los módulos de la aplicación.
module::all::enable_modules(app.enable_modules());
@ -60,9 +58,9 @@ impl Application {
.configure(&module::all::modules)
.configure(&theme::all::themes)
})
.bind(format!("{}:{}",
&SETTINGS.webserver.bind_address,
&SETTINGS.webserver.bind_port
.bind(format!(
"{}:{}",
&SETTINGS.webserver.bind_address, &SETTINGS.webserver.bind_port
))?
.run();

View file

@ -14,7 +14,8 @@ pub fn print_on_startup() {
if SETTINGS.app.name.len() > maxlen {
app = format!("{}...", app);
}
println!("\n{} {}\n\n Powered by PageTop {}\n",
println!(
"\n{} {}\n\n Powered by PageTop {}\n",
FIGFONT.convert(&app).unwrap(),
&SETTINGS.app.description,
env!("CARGO_PKG_VERSION")
@ -22,7 +23,8 @@ pub fn print_on_startup() {
return;
}
}
println!("\n{}\n{}\n\nPowered by PageTop {}\n",
println!(
"\n{}\n{}\n\nPowered by PageTop {}\n",
&SETTINGS.app.name,
&SETTINGS.app.description,
env!("CARGO_PKG_VERSION")

View file

@ -1,5 +1,5 @@
use crate::Lazy;
use crate::config::SETTINGS;
use crate::Lazy;
use figlet_rs::FIGfont;
@ -9,8 +9,7 @@ pub static FIGFONT: Lazy<FIGfont> = Lazy::new(|| {
let speed = include_str!("speed.flf");
let starwars = include_str!("starwars.flf");
FIGfont::from_content(
match SETTINGS.app.startup_banner.to_lowercase().as_str() {
FIGfont::from_content(match SETTINGS.app.startup_banner.to_lowercase().as_str() {
"off" => slant,
"slant" => slant,
"small" => small,
@ -19,12 +18,10 @@ pub static FIGFONT: Lazy<FIGfont> = Lazy::new(|| {
_ => {
println!(
"\n FIGfont \"{}\" not found for banner. {}. {}.",
SETTINGS.app.startup_banner,
"Using \"Slant\"",
"Check the settings file",
SETTINGS.app.startup_banner, "Using \"Slant\"", "Check the settings file",
);
slant
}
}
).unwrap()
})
.unwrap()
});

View file

@ -1,8 +1,8 @@
use crate::{Lazy, run_now, trace};
use crate::config::SETTINGS;
use crate::db::*;
use crate::{run_now, trace, Lazy};
use sea_orm::{ConnectionTrait, ConnectOptions, Database, DatabaseBackend, Statement};
use sea_orm::{ConnectOptions, ConnectionTrait, Database, DatabaseBackend, Statement};
use tracing_unwrap::ResultExt;
pub static DBCONN: Lazy<DbConn> = Lazy::new(|| {
@ -14,31 +14,36 @@ pub static DBCONN: Lazy<DbConn> = Lazy::new(|| {
let db_uri = match SETTINGS.database.db_type.as_str() {
"mysql" | "postgres" => {
let mut tmp_uri = DbUri::parse(format!(
let mut tmp_uri = DbUri::parse(
format!(
"{}://{}/{}",
&SETTINGS.database.db_type,
&SETTINGS.database.db_host,
&SETTINGS.database.db_name
).as_str()).unwrap();
tmp_uri.set_username(
&SETTINGS.database.db_user.as_str()
).unwrap();
)
.as_str(),
)
.unwrap();
tmp_uri
.set_username(&SETTINGS.database.db_user.as_str())
.unwrap();
// https://github.com/launchbadge/sqlx/issues/1624
tmp_uri.set_password(
Some(&SETTINGS.database.db_pass.as_str())
).unwrap();
tmp_uri
.set_password(Some(&SETTINGS.database.db_pass.as_str()))
.unwrap();
if SETTINGS.database.db_port != 0 {
tmp_uri.set_port(
Some(SETTINGS.database.db_port)
).unwrap();
tmp_uri.set_port(Some(SETTINGS.database.db_port)).unwrap();
}
tmp_uri
},
}
"sqlite" => DbUri::parse(
format!("{}://{}",
&SETTINGS.database.db_type,
&SETTINGS.database.db_name
).as_str()).unwrap(),
format!(
"{}://{}",
&SETTINGS.database.db_type, &SETTINGS.database.db_name
)
.as_str(),
)
.unwrap(),
_ => {
trace::error!(
"Unrecognized database type \"{}\"",
@ -48,42 +53,44 @@ pub static DBCONN: Lazy<DbConn> = Lazy::new(|| {
}
};
run_now(
Database::connect::<ConnectOptions>({
run_now(Database::connect::<ConnectOptions>({
let mut db_opt = ConnectOptions::new(db_uri.to_string());
db_opt.max_connections(SETTINGS.database.max_pool_size);
db_opt.into()
})
).expect_or_log("Failed to connect to database")
});
static DBBACKEND: Lazy<DatabaseBackend> = Lazy::new(|| {
DBCONN.get_database_backend()
}))
.expect_or_log("Failed to connect to database")
});
static DBBACKEND: Lazy<DatabaseBackend> = Lazy::new(|| DBCONN.get_database_backend());
pub async fn query<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Vec<QueryResult>, DbErr> {
DBCONN.query_all(Statement::from_string(
DBCONN
.query_all(Statement::from_string(
*DBBACKEND,
match *DBBACKEND {
DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder),
DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder),
DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder),
}
)).await
},
))
.await
}
pub async fn exec<Q: QueryStatementWriter>(stmt: &mut Q) -> Result<Option<QueryResult>, DbErr> {
DBCONN.query_one(Statement::from_string(
DBCONN
.query_one(Statement::from_string(
*DBBACKEND,
match *DBBACKEND {
DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder),
DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder),
DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder),
}
)).await
},
))
.await
}
pub async fn exec_raw(stmt: String) -> Result<ExecResult, DbErr> {
DBCONN.execute(Statement::from_string(*DBBACKEND, stmt)).await
DBCONN
.execute(Statement::from_string(*DBBACKEND, stmt))
.await
}

View file

@ -2,8 +2,7 @@ use crate::core::module::ModuleTrait;
use crate::core::theme::ThemeTrait;
pub trait AppTrait: Send + Sync {
fn bootstrap(&self) {
}
fn bootstrap(&self) {}
fn enable_modules(&self) -> Vec<&'static dyn ModuleTrait> {
vec![]

View file

@ -1,13 +1,12 @@
use crate::{Lazy, trace};
use crate::config::SETTINGS;
use crate::{trace, Lazy};
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() {
pub static LANGID: Lazy<LanguageIdentifier> = Lazy::new(|| match SETTINGS.app.language.parse() {
Ok(language) => language,
Err(_) => {
trace::warn!(
@ -20,5 +19,4 @@ pub static LANGID: Lazy<LanguageIdentifier> = Lazy::new(|| {
);
"en-US".parse().unwrap()
}
}
});

View file

@ -1,5 +1,5 @@
use crate::Lazy;
use crate::config::SETTINGS;
use crate::Lazy;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::EnvFilter;
@ -18,14 +18,11 @@ use tracing_subscriber::EnvFilter;
/// 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"));
let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing).unwrap_or(EnvFilter::new("Info"));
let rolling = SETTINGS.log.rolling.to_lowercase();
let (non_blocking, guard) = match rolling.as_str() {
"stdout" => tracing_appender::non_blocking(
std::io::stdout()
),
"stdout" => tracing_appender::non_blocking(std::io::stdout()),
_ => tracing_appender::non_blocking({
let path = &SETTINGS.log.path;
let prefix = &SETTINGS.log.prefix;
@ -37,14 +34,12 @@ pub static TRACING: Lazy<WorkerGuard> = Lazy::new(|| {
_ => {
println!(
"Rolling value \"{}\" not valid. {}. {}.",
SETTINGS.log.rolling,
"Using \"daily\"",
"Check the settings file",
SETTINGS.log.rolling, "Using \"daily\"", "Check the settings file",
);
tracing_appender::rolling::daily(path, prefix)
}
}
})
}),
};
let subscriber = tracing_subscriber::fmt()
.with_env_filter(env_filter)
@ -58,9 +53,7 @@ pub static TRACING: Lazy<WorkerGuard> = Lazy::new(|| {
_ => {
println!(
"Tracing format \"{}\" not valid. {}. {}.",
SETTINGS.log.format,
"Using \"Full\"",
"Check the settings file",
SETTINGS.log.format, "Using \"Full\"", "Check the settings file",
);
subscriber.init();
}

View file

@ -1,44 +1,24 @@
mod container;
pub use container::{
COMPONENT_CONTAINER, Container, ContainerType
};
pub use container::{Container, ContainerType, COMPONENT_CONTAINER};
pub mod grid;
mod chunck;
pub use chunck::{
COMPONENT_CHUNCK, Chunck
};
pub use chunck::{Chunck, COMPONENT_CHUNCK};
mod icon;
pub use icon::{
COMPONENT_ICON, Icon
};
pub use icon::{Icon, COMPONENT_ICON};
mod heading;
pub use heading::{
COMPONENT_HEADING, Heading, HeadingDisplay, HeadingType
};
pub use heading::{Heading, HeadingDisplay, HeadingType, COMPONENT_HEADING};
mod paragraph;
pub use paragraph::{
COMPONENT_PARAGRAPH, Paragraph, ParagraphDisplay
};
pub use paragraph::{Paragraph, ParagraphDisplay, COMPONENT_PARAGRAPH};
mod anchor;
pub use anchor::{
COMPONENT_ANCHOR, Anchor, AnchorIcon, AnchorTarget, AnchorType
};
pub use anchor::{Anchor, AnchorIcon, AnchorTarget, AnchorType, COMPONENT_ANCHOR};
mod block;
pub use block::{
COMPONENT_BLOCK, Block
};
pub use block::{Block, COMPONENT_BLOCK};
mod image;
pub use image::{
COMPONENT_IMAGE, Image
};
pub use image::{Image, COMPONENT_IMAGE};
mod menu;
pub use menu::{
COMPONENT_MENU, COMPONENT_MENUITEM, Menu, MenuItem, MenuItemType
};
pub use menu::{Menu, MenuItem, MenuItemType, COMPONENT_MENU, COMPONENT_MENUITEM};
pub mod form;
pub use form::{
COMPONENT_FORM, Form, FormMethod
};
pub use form::{Form, FormMethod, COMPONENT_FORM};

View file

@ -98,7 +98,10 @@ impl Anchor {
}
pub fn button(href: &str, html: Markup) -> Self {
Anchor::new().with_type(AnchorType::Button).with_href(href).with_html(html)
Anchor::new()
.with_type(AnchorType::Button)
.with_href(href)
.with_html(html)
}
pub fn location(id: &str) -> Self {
@ -186,10 +189,13 @@ impl Anchor {
pub fn alter_type(&mut self, anchor_type: AnchorType) -> &mut Self {
self.anchor_type = anchor_type;
self.classes.alter(ClassesOp::SetDefault, match self.anchor_type {
self.classes.alter(
ClassesOp::SetDefault,
match self.anchor_type {
AnchorType::Button => "btn btn-primary",
_ => "",
});
},
);
self
}

View file

@ -71,7 +71,6 @@ impl ComponentTrait for Block {
}
impl Block {
// Block BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -7,7 +7,13 @@ hook_before_render_component!(
Container
);
pub enum ContainerType { Header, Footer, Main, Section, Wrapper }
pub enum ContainerType {
Header,
Footer,
Main,
Section,
Wrapper,
}
pub struct Container {
weight : isize,
@ -84,7 +90,7 @@ impl ComponentTrait for Container {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(context))
}
}
},
}
}

View file

@ -1,21 +1,11 @@
mod form;
pub use form::{
COMPONENT_FORM, Form, FormMethod
};
pub use form::{Form, FormMethod, COMPONENT_FORM};
mod input;
pub use input::{
COMPONENT_INPUT, Input, InputType
};
pub use input::{Input, InputType, COMPONENT_INPUT};
mod hidden;
pub use hidden::{
COMPONENT_HIDDEN, Hidden
};
pub use hidden::{Hidden, COMPONENT_HIDDEN};
mod date;
pub use date::{
COMPONENT_DATE, Date
};
pub use date::{Date, COMPONENT_DATE};
mod button;
pub use button::{
COMPONENT_BUTTON, Button, ButtonType
};
pub use button::{Button, ButtonType, COMPONENT_BUTTON};

View file

@ -2,7 +2,11 @@ use crate::prelude::*;
pub const COMPONENT_BUTTON: &str = "pagetop::component::form::button";
pub enum ButtonType {Button, Reset, Submit}
pub enum ButtonType {
Button,
Reset,
Submit,
}
pub struct Button {
weight : isize,
@ -52,7 +56,7 @@ impl ComponentTrait for Button {
};
let id = match self.name().get() {
Some(name) => Some(concat_string!("edit-", name)),
_ => None
_ => None,
};
html! {
button

View file

@ -101,7 +101,6 @@ impl ComponentTrait for Date {
}
impl Date {
// Date BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -7,7 +7,10 @@ hook_before_render_component!(
Form
);
pub enum FormMethod {Get, Post}
pub enum FormMethod {
Get,
Post,
}
pub struct Form {
weight : isize,
@ -55,7 +58,7 @@ impl ComponentTrait for Form {
fn default_render(&self, context: &mut InContext) -> Markup {
let method = match self.method() {
FormMethod::Get => None,
FormMethod::Post => Some("post".to_owned())
FormMethod::Post => Some("post".to_owned()),
};
html! {
form
@ -80,7 +83,6 @@ impl ComponentTrait for Form {
}
impl Form {
// Form BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -28,7 +28,7 @@ impl ComponentTrait for Hidden {
fn default_render(&self, _: &mut InContext) -> Markup {
let id = match self.name().get() {
Some(name) => Some(concat_string!("value-", name)),
_ => None
_ => None,
};
html! {
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()];

View file

@ -2,7 +2,14 @@ use crate::prelude::*;
pub const COMPONENT_INPUT: &str = "pagetop::component::form::input";
pub enum InputType {Email, Password, Search, Telephone, Textfield, Url}
pub enum InputType {
Email,
Password,
Search,
Telephone,
Textfield,
Url,
}
pub struct Input {
weight : isize,
@ -127,36 +134,46 @@ impl Input {
}
pub fn password() -> Self {
let mut input = Input::new()
.with_classes(ClassesOp::Replace("form-type-textfield"), "form-type-password");
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-password",
);
input.input_type = InputType::Password;
input
}
pub fn search() -> Self {
let mut input = Input::new()
.with_classes(ClassesOp::Replace("form-type-textfield"), "form-type-search");
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-search",
);
input.input_type = InputType::Search;
input
}
pub fn email() -> Self {
let mut input = Input::new()
.with_classes(ClassesOp::Replace("form-type-textfield"), "form-type-email");
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-email"
);
input.input_type = InputType::Email;
input
}
pub fn telephone() -> Self {
let mut input = Input::new()
.with_classes(ClassesOp::Replace("form-type-textfield"), "form-type-telephone");
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-telephone",
);
input.input_type = InputType::Telephone;
input
}
pub fn url() -> Self {
let mut input = Input::new()
.with_classes(ClassesOp::Replace("form-type-textfield"), "form-type-url");
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-url"
);
input.input_type = InputType::Url;
input
}
@ -267,8 +284,9 @@ impl Input {
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.with_value(name);
self.alter_classes(ClassesOp::SetDefault,
concat_string!("form-item form-item-", name).as_str()
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("form-item form-item-", name).as_str(),
);
self
}

View file

@ -1,8 +1,4 @@
mod row;
pub use row::{
COMPONENT_ROW, Row
};
pub use row::{Row, COMPONENT_ROW};
mod column;
pub use column::{
COMPONENT_COLUMN, Column, ColumnSize
};
pub use column::{Column, ColumnSize, COMPONENT_COLUMN};

View file

@ -93,7 +93,6 @@ impl ComponentTrait for Column {
}
impl Column {
// Column BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -62,7 +62,6 @@ impl ComponentTrait for Row {
}
impl Row {
// Row BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -2,7 +2,14 @@ use crate::prelude::*;
pub const COMPONENT_HEADING: &str = "pagetop::component::heading";
pub enum HeadingType { H1, H2, H3, H4, H5, H6 }
pub enum HeadingType {
H1,
H2,
H3,
H4,
H5,
H6,
}
pub enum HeadingDisplay {
XxLarge,
@ -75,27 +82,39 @@ impl ComponentTrait for Heading {
impl Heading {
pub fn h1(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H1).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H1)
.with_html(html)
}
pub fn h2(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H2).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H2)
.with_html(html)
}
pub fn h3(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H3).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H3)
.with_html(html)
}
pub fn h4(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H4).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H4)
.with_html(html)
}
pub fn h5(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H5).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H5)
.with_html(html)
}
pub fn h6(html: Markup) -> Self {
Heading::new().with_heading_type(HeadingType::H6).with_html(html)
Heading::new()
.with_heading_type(HeadingType::H6)
.with_html(html)
}
// Heading BUILDER.
@ -174,7 +193,9 @@ impl Heading {
pub fn alter_display(&mut self, display: HeadingDisplay) -> &mut Self {
self.display = display;
self.classes.alter(ClassesOp::SetDefault, match &self.display() {
self.classes.alter(
ClassesOp::SetDefault,
match &self.display() {
HeadingDisplay::XxLarge => "display-2",
HeadingDisplay::Large => "display-3",
HeadingDisplay::Medium => "display-4",
@ -182,7 +203,8 @@ impl Heading {
HeadingDisplay::XxSmall => "display-6",
HeadingDisplay::Normal => "",
HeadingDisplay::Subtitle => "",
});
},
);
self
}

View file

@ -32,10 +32,8 @@ impl ComponentTrait for Icon {
}
fn before_render(&mut self, context: &mut InContext) {
context
.alter(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/theme/icons/bootstrap-icons.css")
.with_version("1.8.2")
context.alter(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"),
)));
}
@ -93,7 +91,10 @@ impl Icon {
pub fn alter_icon_name(&mut self, name: &str) -> &mut Self {
self.icon_name = name.to_owned();
self.alter_classes(ClassesOp::SetDefault, concat_string!("bi-", self.icon_name).as_str());
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("bi-", self.icon_name).as_str(),
);
self
}

View file

@ -94,10 +94,7 @@ impl MenuItem {
MenuItem {
weight : 0,
renderable: render_always,
item_type : MenuItemType::Link(
label.to_owned(),
path.to_owned(),
),
item_type : MenuItemType::Link(label.to_owned(), path.to_owned()),
}
}
@ -105,10 +102,7 @@ impl MenuItem {
MenuItem {
weight : 0,
renderable: render_always,
item_type : MenuItemType::LinkBlank(
label.to_owned(),
path.to_owned(),
),
item_type : MenuItemType::LinkBlank(label.to_owned(), path.to_owned()),
}
}
@ -132,10 +126,7 @@ impl MenuItem {
MenuItem {
weight : 0,
renderable: render_always,
item_type : MenuItemType::Submenu(
label.to_owned(),
menu
),
item_type : MenuItemType::Submenu(label.to_owned(), menu),
}
}
@ -219,16 +210,13 @@ impl ComponentTrait for Menu {
fn default_render(&self, context: &mut InContext) -> Markup {
context
.alter(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/theme/menu/css/menu.css")
.with_version("1.1.1")
StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"),
)))
.alter(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/theme/menu/css/menu-clean.css")
.with_version("1.1.1")
StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"),
)))
.alter(InContextOp::JavaScript(AssetsOp::Add(
JavaScript::located("/theme/menu/js/menu.min.js")
.with_version("1.1.1")
JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"),
)))
.alter(InContextOp::AddJQuery);
@ -257,7 +245,6 @@ impl ComponentTrait for Menu {
}
impl Menu {
// Menu BUILDER.
pub fn with_weight(mut self, weight: isize) -> Self {

View file

@ -132,14 +132,17 @@ impl Paragraph {
pub fn alter_display(&mut self, display: ParagraphDisplay) -> &mut Self {
self.display = display;
self.classes.alter(ClassesOp::SetDefault, match &self.display() {
self.classes.alter(
ClassesOp::SetDefault,
match &self.display() {
ParagraphDisplay::XxLarge => "fs-2",
ParagraphDisplay::Large => "fs-3",
ParagraphDisplay::Medium => "fs-4",
ParagraphDisplay::Small => "fs-5",
ParagraphDisplay::XxSmall => "fs-6",
ParagraphDisplay::Normal => "",
});
},
);
self
}

View file

@ -27,9 +27,9 @@ impl ModuleTrait for DefaultHomePage {
async fn demo() -> app::Result<Markup> {
Page::new()
.with_title(l("page_title").as_str())
.with_context(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/theme/module/homepage/styles.css")
)))
.with_context(InContextOp::StyleSheet(AssetsOp::Add(StyleSheet::located(
"/theme/module/homepage/styles.css",
))))
.add_to("content", hello_world())
.add_to("content", welcome())
.add_to("content", about_pagetop())
@ -39,46 +39,56 @@ async fn demo() -> app::Result<Markup> {
}
fn hello_world() -> Container {
Container::header()
.with_id("hello-world")
.with_component(grid::Row::new()
.with_column(grid::Column::new()
Container::header().with_id("hello-world").with_component(
grid::Row::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "hello-col-text")
.with_size(grid::ColumnSize::Is4of12)
.with_component(Heading::h1(html! {
.with_component(
Heading::h1(html! {
(l("page_title"))
})
.with_display(HeadingDisplay::Medium)
.with_display(HeadingDisplay::Medium),
)
.with_component(Paragraph::with(html! {
.with_component(
Paragraph::with(html! {
(e("hello_intro", &args![
"app" => format!("<strong>{}</strong>", &SETTINGS.app.name)
]))
})
.with_display(ParagraphDisplay::Small)
.with_display(ParagraphDisplay::Small),
)
.with_component(Paragraph::with(html! {
(e("hello_pagetop", &args![
"pagetop" => "<a href=\"https://pagetop-rs\">PageTop</a>"
]))
})
)
.with_component(Anchor::button("#", html! {
}))
.with_component(
Anchor::button(
"#",
html! {
("Offered services")
})
},
)
.with_left_icon(Icon::with("card-checklist"))
.with_classes(ClassesOp::Add, "services-link")
.with_classes(ClassesOp::Add, "services-link"),
)
.with_component(Anchor::button("#", html! {
.with_component(
Anchor::button(
"#",
html! {
("Get quote")
})
.with_left_icon(Icon::with("envelope-open-heart-fill"))
},
)
.with_left_icon(Icon::with("envelope-open-heart-fill")),
),
)
.with_column(grid::Column::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "hello-col-image")
.with_component(Image::image("/theme/images/demo-header.svg"))
)
.with_component(Image::image("/theme/images/demo-header.svg")),
),
)
}
@ -89,100 +99,103 @@ fn welcome() -> Container {
.with_component(Heading::h2(html! {
(t("welcome_to", &args!["app" => SETTINGS.app.name.as_str()]))
}))
.with_component(Heading::h3(html! {
.with_component(
Heading::h3(html! {
(l("welcome_subtitle"))
})
.with_display(HeadingDisplay::Subtitle)
.with_display(HeadingDisplay::Subtitle),
)
.with_component(Paragraph::with(html! {
.with_component(
Paragraph::with(html! {
(l("welcome_text1"))
})
.with_display(ParagraphDisplay::Small)
.with_display(ParagraphDisplay::Small),
)
.with_component(Paragraph::with(html! { (l("welcome_text2")) }))
}
fn about_pagetop() -> Container {
Container::new()
.with_id("pagetop")
.with_component(grid::Row::new()
.with_column(grid::Column::new()
Container::new().with_id("pagetop").with_component(
grid::Row::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "pagetop-col-image")
.with_size(grid::ColumnSize::Is5of12)
.with_component(Image::image("/theme/images/demo-about.svg"))
.with_component(Image::image("/theme/images/demo-about.svg")),
)
.with_column(grid::Column::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "pagetop-col-text")
.with_component(Heading::h2(html! {
(l("pagetop_title"))
}))
.with_component(Paragraph::with(html! {
.with_component(
Paragraph::with(html! {
(l("pagetop_text1"))
})
.with_display(ParagraphDisplay::Small)
.with_display(ParagraphDisplay::Small),
)
.with_component(Paragraph::with(html! {
(l("pagetop_text2"))
})
)
}))
.with_component(Paragraph::with(html! {
(l("pagetop_text3"))
})
)
)
})),
),
)
}
fn promo_pagetop() -> Container {
Container::new()
.with_id("promo")
.with_component(grid::Row::new()
.with_column(grid::Column::new()
Container::new().with_id("promo").with_component(
grid::Row::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "promo-col-image")
.with_size(grid::ColumnSize::Is5of12)
.with_component(Image::image("/theme/images/demo-pagetop.svg"))
.with_component(Image::image("/theme/images/demo-pagetop.svg")),
)
.with_column(grid::Column::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "promo-col-text")
.with_component(Heading::h2(html! {
(l("pagetop_promo_title"))
})
)
.with_component(Paragraph::with(html! {
}))
.with_component(
Paragraph::with(html! {
(e("pagetop_promo_text1", &args![
"pagetop" => "<a href=\"https://pagetop-rs\">PageTop</a>"
]))
})
.with_display(ParagraphDisplay::Small)
)
)
.with_display(ParagraphDisplay::Small),
),
),
)
}
fn reporting_problems() -> Container {
Container::new()
.with_id("reporting")
.with_component(grid::Row::new()
.with_column(grid::Column::new()
Container::new().with_id("reporting").with_component(
grid::Row::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "reporting-col-text")
.with_size(grid::ColumnSize::Is7of12)
.with_component(Heading::h2(html! {
(l("report_problems_title"))
})
)
.with_component(Paragraph::with(html! {
}))
.with_component(
Paragraph::with(html! {
(l("report_problems_text1"))
})
.with_display(ParagraphDisplay::Small)
.with_display(ParagraphDisplay::Small),
)
.with_component(Paragraph::with(html! {
(l("report_problems_text2"))
})
})),
)
)
.with_column(grid::Column::new()
.with_column(
grid::Column::new()
.with_classes(ClassesOp::Add, "reporting-col-image")
.with_component(Image::image("/theme/images/demo-pagetop.svg"))
)
.with_component(Image::image("/theme/images/demo-pagetop.svg")),
),
)
}

View file

@ -1,4 +1,7 @@
pub mod aliner;
pub mod minimal;
pub mod bootsier;
pub mod bulmix;

View file

@ -16,15 +16,11 @@ impl ThemeTrait for Aliner {
}
fn before_render_page(&self, page: &mut Page) {
page
.alter_context(InContextOp::Favicon(Some(Favicon::new()
.with_icon("/theme/favicon.png")
page.alter_context(InContextOp::Favicon(Some(
Favicon::new().with_icon("/theme/favicon.png"),
)))
.alter_context(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located(
"/aliner/css/styles.css"
)
.with_weight(-99)
StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
)));
}
}

View file

@ -18,19 +18,18 @@ impl ThemeTrait for Bootsier {
}
fn before_render_page(&self, page: &mut Page) {
page
.alter_context(InContextOp::Favicon(Some(Favicon::new()
.with_icon("/theme/favicon.png")
page.alter_context(InContextOp::Favicon(Some(
Favicon::new().with_icon("/theme/favicon.png"),
)))
.alter_context(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3")
.with_weight(-99)
.with_weight(-99),
)))
.alter_context(InContextOp::JavaScript(AssetsOp::Add(
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3")
.with_weight(-99)
.with_weight(-99),
)))
.alter_context(InContextOp::AddJQuery);
}
@ -42,14 +41,16 @@ impl ThemeTrait for Bootsier {
app::http::StatusCode::NOT_FOUND => {
description = "e404-description";
message = "e404-message";
},
}
_ => {
s = app::http::StatusCode::INTERNAL_SERVER_ERROR;
}
}
Page::new()
.with_title(format!("Error {}", s.as_str()).as_str())
.add_to("content", Chunck::with(html! {
.add_to(
"content",
Chunck::with(html! {
div class="jumbotron" {
div class="media" {
img
@ -72,7 +73,8 @@ impl ThemeTrait for Bootsier {
}
}
}
}))
}),
)
.render()
}
}

View file

@ -16,14 +16,13 @@ impl ThemeTrait for Bulmix {
}
fn before_render_page(&self, page: &mut Page) {
page
.alter_context(InContextOp::Favicon(Some(Favicon::new()
.with_icon("/theme/favicon.png")
page.alter_context(InContextOp::Favicon(Some(
Favicon::new().with_icon("/theme/favicon.png"),
)))
.alter_context(InContextOp::StyleSheet(AssetsOp::Add(
StyleSheet::located("/bulmix/css/bulma.min.css")
.with_version("0.9.4")
.with_weight(-99)
.with_weight(-99),
)))
.alter_context(InContextOp::AddJQuery);
}
@ -31,19 +30,24 @@ impl ThemeTrait for Bulmix {
fn before_render_component(
&self,
component: &mut dyn ComponentTrait,
_context: &mut InContext
_context: &mut InContext,
) {
match component.handler() {
COMPONENT_ANCHOR => {
let a = component_mut::<Anchor>(component);
a.alter_classes(ClassesOp::SetDefault, match a.anchor_type() {
a.alter_classes(
ClassesOp::SetDefault,
match a.anchor_type() {
AnchorType::Button => "button is-primary",
_ => "",
});
},
);
}
COMPONENT_HEADING => {
let h = component_mut::<Heading>(component);
h.alter_classes(ClassesOp::SetDefault, match h.display() {
h.alter_classes(
ClassesOp::SetDefault,
match h.display() {
HeadingDisplay::XxLarge => "title is-1",
HeadingDisplay::Large => "title is-2",
HeadingDisplay::Medium => "title is-3",
@ -51,22 +55,30 @@ impl ThemeTrait for Bulmix {
HeadingDisplay::XxSmall => "title is-5",
HeadingDisplay::Normal => "title",
HeadingDisplay::Subtitle => "subtitle",
});
},
);
}
COMPONENT_PARAGRAPH => {
let p = component_mut::<Paragraph>(component);
p.alter_classes(ClassesOp::SetDefault, match p.display() {
p.alter_classes(
ClassesOp::SetDefault,
match p.display() {
ParagraphDisplay::XxLarge => "is-size-2",
ParagraphDisplay::Large => "is-size-3",
ParagraphDisplay::Medium => "is-size-4",
ParagraphDisplay::Small => "is-size-5",
ParagraphDisplay::XxSmall => "is-size-6",
ParagraphDisplay::Normal => "",
});
},
);
}
grid::COMPONENT_COLUMN => {
let col = component_mut::<grid::Column>(component);
col.alter_classes(ClassesOp::SetDefault, concat_string!("column", match col.size() {
col.alter_classes(
ClassesOp::SetDefault,
concat_string!(
"column",
match col.size() {
grid::ColumnSize::Default => "",
grid::ColumnSize::Is1of12 => " is-1",
grid::ColumnSize::Is2of12 => " is-2",
@ -80,20 +92,24 @@ impl ThemeTrait for Bulmix {
grid::ColumnSize::Is10of12 => " is-10",
grid::ColumnSize::Is11of12 => " is-11",
grid::ColumnSize::IsFull => " is-12",
}, " content").as_str());
},
" content"
)
.as_str(),
);
}
grid::COMPONENT_ROW => {
let row = component_mut::<grid::Row>(component);
row.alter_classes(ClassesOp::SetDefault, "columns");
},
_ => {},
}
_ => {}
}
}
fn render_component(
&self,
component: &dyn ComponentTrait,
_context: &mut InContext
_context: &mut InContext,
) -> Option<Markup> {
match component.handler() {
COMPONENT_ICON => {
@ -103,7 +119,7 @@ impl ThemeTrait for Bulmix {
i class=[icon.classes().get()] {};
}
})
},
}
_ => None,
}
}

View file

@ -22,19 +22,14 @@ pub static CONFIG: Lazy<Config> = Lazy::new(|| {
// Combina los archivos de configuración y asigna el modo de ejecución.
settings
.merge(
File::with_name(
&format!("{}/{}.toml", CONFIG_DIR, "common")
).required(false)).unwrap()
.merge(
File::with_name(
&format!("{}/{}.toml", CONFIG_DIR, run_mode)
).required(false)).unwrap()
.merge(
File::with_name(
&format!("{}/{}.toml", CONFIG_DIR, "local")
).required(false)).unwrap()
.set("app.run_mode", run_mode).unwrap();
.merge(File::with_name(&format!("{}/{}.toml", CONFIG_DIR, "common")).required(false))
.unwrap()
.merge(File::with_name(&format!("{}/{}.toml", CONFIG_DIR, run_mode)).required(false))
.unwrap()
.merge(File::with_name(&format!("{}/{}.toml", CONFIG_DIR, "local")).required(false))
.unwrap()
.set("app.run_mode", run_mode)
.unwrap();
settings
});

View file

@ -1,4 +1,11 @@
pub mod component; // API to build new components.
pub mod hook; // API to define functions that alter the behavior of PageTop core.
pub mod module; // API to add new features with modules.
pub mod theme; // API to create themes.
// API to build new components.
pub mod component;
// API to define functions that alter the behavior of PageTop core.
pub mod hook;
// API to add new features with modules.
pub mod module;
// API to create themes.
pub mod theme;

View file

@ -2,13 +2,8 @@ mod context;
pub use context::{InContext, InContextOp};
mod definition;
pub use definition::{
AnyComponent,
ComponentTrait,
component_ref,
component_mut,
};
use definition::render_component;
pub use definition::{component_mut, component_ref, AnyComponent, ComponentTrait};
mod bundle;
pub use bundle::ComponentsBundle;
@ -19,6 +14,10 @@ pub(crate) use all::common_components;
pub type Renderable = fn(_: &InContext) -> bool;
pub fn render_always(_: &InContext) -> bool { true }
pub fn render_always(_: &InContext) -> bool {
true
}
pub fn render_never(_: &InContext) -> bool { false }
pub fn render_never(_: &InContext) -> bool {
false
}

View file

@ -1,12 +1,11 @@
use super::{ComponentTrait, ComponentsBundle};
use crate::Lazy;
use super::{ComponentsBundle, ComponentTrait};
use std::sync::RwLock;
use std::collections::HashMap;
use std::sync::RwLock;
static COMPONENTS: Lazy<RwLock<HashMap<&str, ComponentsBundle>>> = Lazy::new(|| {
RwLock::new(HashMap::new())
});
static COMPONENTS: Lazy<RwLock<HashMap<&str, ComponentsBundle>>> =
Lazy::new(|| RwLock::new(HashMap::new()));
pub fn add_component_to(region: &'static str, component: impl ComponentTrait) {
let mut hmap = COMPONENTS.write().unwrap();

View file

@ -1,5 +1,5 @@
use crate::html::{Markup, html};
use super::{InContext, ComponentTrait};
use super::{ComponentTrait, InContext};
use crate::html::{html, Markup};
use std::sync::{Arc, RwLock};

View file

@ -1,14 +1,13 @@
use crate::{Lazy, base, concat_string, util};
use crate::config::SETTINGS;
use crate::html::*;
use crate::core::theme::ThemeTrait;
use crate::core::theme::all::theme_by_single_name;
use crate::core::theme::ThemeTrait;
use crate::html::*;
use crate::{base, concat_string, util, Lazy};
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
match theme_by_single_name(&SETTINGS.app.theme) {
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> =
Lazy::new(|| match theme_by_single_name(&SETTINGS.app.theme) {
Some(theme) => theme,
None => &base::theme::bootsier::Bootsier,
}
});
pub enum InContextOp {
@ -47,28 +46,30 @@ impl InContext {
match op {
InContextOp::SetTheme(theme_name) => {
self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
},
}
InContextOp::AddMetadata(name, content) => {
self.metadata.push((name.to_owned(), content.to_owned()));
},
}
InContextOp::Favicon(favicon) => {
self.favicon = favicon;
},
}
InContextOp::StyleSheet(css) => {
self.stylesheets.alter(css);
},
}
InContextOp::JavaScript(js) => {
self.javascripts.alter(js);
},
InContextOp::AddJQuery => if !self.with_jquery {
}
InContextOp::AddJQuery => {
if !self.with_jquery {
self.javascripts.alter(AssetsOp::Add(
JavaScript::located("/theme/js/jquery.min.js")
.with_version("3.6.0")
.with_weight(isize::MIN)
.with_mode(JSMode::Normal)
.with_mode(JSMode::Normal),
));
self.with_jquery = true;
},
}
}
}
self
}

View file

@ -1,11 +1,13 @@
use crate::util;
use crate::html::{Markup, html};
use super::InContext;
use crate::html::{html, Markup};
use crate::util;
pub use std::any::Any as AnyComponent;
pub trait ComponentTrait: AnyComponent + Send + Sync {
fn new() -> Self where Self: Sized;
fn new() -> Self
where
Self: Sized;
fn handler(&self) -> &'static str;
@ -27,8 +29,7 @@ pub trait ComponentTrait: AnyComponent + Send + Sync {
}
#[allow(unused_variables)]
fn before_render(&mut self, context: &mut InContext) {
}
fn before_render(&mut self, context: &mut InContext) {}
#[allow(unused_variables)]
fn default_render(&self, context: &mut InContext) -> Markup {
@ -58,9 +59,9 @@ pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InCont
match component.is_renderable(context) {
true => match context.theme().render_component(component, context) {
Some(html) => html,
None => component.default_render(context)
None => component.default_render(context),
},
false => html! {}
false => html! {},
}
}

View file

@ -1,14 +1,10 @@
mod definition;
pub use definition::{
AnyHook,
HookTrait,
action_ref,
};
pub use definition::{action_ref, AnyHook, HookTrait};
mod holder;
pub use holder::HookAction;
use holder::HooksHolder;
mod all;
pub use all::run_actions;
pub(crate) use all::add_hook;
pub use all::run_actions;

View file

@ -1,13 +1,12 @@
use crate::Lazy;
use super::{HookAction, HooksHolder};
use crate::Lazy;
use std::sync::RwLock;
use std::collections::HashMap;
use std::sync::RwLock;
// Registered actions.
static ACTIONS: Lazy<RwLock<HashMap<&str, HooksHolder>>> = Lazy::new(|| {
RwLock::new(HashMap::new())
});
static ACTIONS: Lazy<RwLock<HashMap<&str, HooksHolder>>> =
Lazy::new(|| RwLock::new(HashMap::new()));
pub fn add_hook(hook: HookAction) {
let mut hmap = ACTIONS.write().unwrap();
@ -19,7 +18,10 @@ pub fn add_hook(hook: HookAction) {
}
}
pub fn run_actions<B, F>(action_handler: &str, f: F) where F: FnMut(&HookAction) -> B {
pub fn run_actions<B, F>(action_handler: &str, f: F)
where
F: FnMut(&HookAction) -> B,
{
if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) {
actions.iter_map(f)
}

View file

@ -1,7 +1,9 @@
pub use std::any::Any as AnyHook;
pub trait HookTrait: AnyHook + Send + Sync {
fn new() -> Self where Self: Sized;
fn new() -> Self
where
Self: Sized;
fn handler(&self) -> &'static str;

View file

@ -30,7 +30,11 @@ impl HooksHolder {
actions.sort_by_key(|a| a.weight());
}
pub fn iter_map<B, F>(&self, f: F) where Self: Sized, F: FnMut(&HookAction) -> B {
pub fn iter_map<B, F>(&self, f: F)
where
Self: Sized,
F: FnMut(&HookAction) -> B,
{
let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect();
}
}

View file

@ -1,7 +1,4 @@
mod definition;
pub use definition::{
BaseModule,
ModuleTrait,
};
pub use definition::{BaseModule, ModuleTrait};
pub(crate) mod all;

View file

@ -1,19 +1,14 @@
use crate::{Lazy, app, trace};
use crate::core::hook::add_hook;
use super::ModuleTrait;
use crate::core::hook::add_hook;
use crate::{app, trace, Lazy};
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
use crate::{
db::*,
run_now,
};
use crate::{db::*, run_now};
use std::sync::RwLock;
// Enabled modules.
static ENABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new())
});
static ENABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| RwLock::new(Vec::new()));
/* Disabled modules.
static DISABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
@ -34,7 +29,12 @@ fn enable(module: &'static dyn ModuleTrait) {
}
fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) {
if !ENABLED_MODULES.read().unwrap().iter().any(|m| m.handler() == module.handler()) {
if !ENABLED_MODULES
.read()
.unwrap()
.iter()
.any(|m| m.handler() == module.handler())
{
if !list.iter().any(|m| m.handler() == module.handler()) {
trace::debug!("Enabling module \"{}\"", module.single_name());
list.push(module);
@ -80,5 +80,6 @@ pub fn run_migrations() {
}
}
Migrator::up(&app::db::DBCONN, None)
}).unwrap();
})
.unwrap();
}

View file

@ -1,5 +1,5 @@
use crate::{app, util};
use crate::core::hook::HookAction;
use crate::{app, util};
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
use crate::db::MigrationItem;
@ -25,8 +25,7 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
}
#[allow(unused_variables)]
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
}
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {}
fn actions(&self) -> Vec<HookAction> {
vec![]

View file

@ -1,7 +1,4 @@
mod definition;
pub use definition::{
BaseTheme,
ThemeTrait,
};
pub use definition::{BaseTheme, ThemeTrait};
pub(crate) mod all;

View file

@ -1,14 +1,12 @@
use crate::{Lazy, app, theme_static_files, trace};
use super::ThemeTrait;
use crate::{app, theme_static_files, trace, Lazy};
use std::sync::RwLock;
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
// Temas registrados.
static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new())
});
static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(|| RwLock::new(Vec::new()));
pub fn register_themes(themes: Vec<&'static dyn ThemeTrait>) {
for t in themes {
@ -25,9 +23,12 @@ fn register(theme: &'static dyn ThemeTrait) {
}
pub fn theme_by_single_name(single_name: &str) -> Option<&'static dyn ThemeTrait> {
match THEMES.write().unwrap().iter().find(
|t| t.single_name().to_lowercase() == single_name.to_lowercase()
) {
match THEMES
.write()
.unwrap()
.iter()
.find(|t| t.single_name().to_lowercase() == single_name.to_lowercase())
{
Some(theme) => Some(*theme),
_ => None,
}

View file

@ -1,9 +1,9 @@
use crate::{app, concat_string, util};
use crate::config::SETTINGS;
use crate::html::{Favicon, Markup, html};
use crate::core::component::{ComponentTrait, InContext, InContextOp};
use crate::response::page::Page;
use crate::base::component::Chunck;
use crate::config::SETTINGS;
use crate::core::component::{ComponentTrait, InContext, InContextOp};
use crate::html::{html, Favicon, Markup};
use crate::response::page::Page;
use crate::{app, concat_string, util};
pub trait BaseTheme {
fn single_name(&self) -> &'static str;
@ -22,14 +22,12 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
}
#[allow(unused_variables)]
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
}
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {}
#[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) {
page
.alter_context(InContextOp::Favicon(Some(Favicon::new()
.with_icon("/theme/favicon.png")
page.alter_context(InContextOp::Favicon(Some(
Favicon::new().with_icon("/theme/favicon.png"),
)));
}
@ -81,11 +79,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
}
#[allow(unused_variables)]
fn before_render_component(
&self,
component: &mut dyn ComponentTrait,
context: &mut InContext
) {
fn before_render_component(&self, component: &mut dyn ComponentTrait, context: &mut InContext) {
/*
Cómo usarlo:
@ -103,7 +97,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn render_component(
&self,
component: &dyn ComponentTrait,
context: &mut InContext
context: &mut InContext,
) -> Option<Markup> {
None
/*
@ -125,11 +119,14 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn render_error_page(&self, s: app::http::StatusCode) -> app::Result<Markup> {
Page::new()
.with_title(format!("Error {}", s.as_str()).as_str())
.add_to("content", Chunck::with(html! {
.add_to(
"content",
Chunck::with(html! {
div {
h1 { (s.as_str()) }
}
}))
}),
)
.render()
}
}

View file

@ -1,9 +1,9 @@
pub use maud::{DOCTYPE, Markup, PreEscaped, html};
pub use maud::{html, Markup, PreEscaped, DOCTYPE};
mod assets;
pub use assets::{Assets, AssetsOp, SourceValue};
pub use assets::javascript::{JavaScript, JSMode};
pub use assets::javascript::{JSMode, JavaScript};
pub use assets::stylesheet::StyleSheet;
pub use assets::{Assets, AssetsOp, SourceValue};
mod favicon;
pub use favicon::Favicon;
@ -15,4 +15,4 @@ mod identifier;
pub use identifier::IdentifierValue;
mod classes;
pub use classes::{Classes, ClassesOp, ClassValue};
pub use classes::{ClassValue, Classes, ClassesOp};

View file

@ -1,7 +1,7 @@
pub mod javascript;
pub mod stylesheet;
use crate::html::{Markup, html};
use crate::html::{html, Markup};
pub type SourceValue = &'static str;
@ -26,21 +26,23 @@ impl<T: AssetsTrait> Assets<T> {
pub fn alter(&mut self, op: AssetsOp<T>) -> &mut Self {
match op {
AssetsOp::Add(asset) => match self.0.iter().position(
|x| x.source() == asset.source()
) {
Some(index) => if self.0[index].weight() > asset.weight() {
AssetsOp::Add(asset) => {
match self.0.iter().position(|x| x.source() == asset.source()) {
Some(index) => {
if self.0[index].weight() > asset.weight() {
self.0.remove(index);
self.0.push(asset);
},
_ => self.0.push(asset)
}
AssetsOp::Remove(source) => if let Some(index) = self.0.iter().position(
|x| x.source() == source
) {
}
_ => self.0.push(asset),
}
}
AssetsOp::Remove(source) => {
if let Some(index) = self.0.iter().position(|x| x.source() == source) {
self.0.remove(index);
}
}
}
self
}

View file

@ -1,8 +1,12 @@
use crate::html::{Markup, html};
use super::{AssetsTrait, SourceValue};
use crate::html::{html, Markup};
#[derive(PartialEq)]
pub enum JSMode { Async, Defer, Normal }
pub enum JSMode {
Async,
Defer,
Normal,
}
pub struct JavaScript {
source : SourceValue,

View file

@ -1,5 +1,5 @@
use crate::html::{Markup, html};
use super::{AssetsTrait, SourceValue};
use crate::html::{html, Markup};
pub struct StyleSheet {
source : SourceValue,

View file

@ -38,7 +38,7 @@ impl Classes {
match op {
ClassesOp::Add => {
self.added = concat_string!(self.added, " ", classes).trim().to_owned()
},
}
ClassesOp::AddAfter(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
@ -47,7 +47,7 @@ impl Classes {
_ => v_added.push(classes),
}
self.added = v_added.join(" ");
},
}
ClassesOp::AddBefore(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
@ -56,11 +56,11 @@ impl Classes {
_ => v_added.insert(0, classes),
}
self.added = v_added.join(" ");
},
}
ClassesOp::AddFirst => {
self.added = concat_string!(classes, " ", self.added).trim().to_owned()
},
}
ClassesOp::Remove => {
let v_list: Vec<&str> = classes.split_ascii_whitespace().collect();
@ -71,7 +71,7 @@ impl Classes {
}
}
self.added = v_added.join(" ");
},
}
ClassesOp::Replace(class) => {
let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect();
@ -79,19 +79,21 @@ impl Classes {
Some(pos) => {
v_added.remove(pos);
v_added.insert(pos, classes);
},
}
_ => v_added.push(classes),
}
self.added = v_added.join(" ");
},
}
ClassesOp::Reset => self.added = classes.to_owned(),
ClassesOp::SetDefault => self.default = classes.to_owned(),
ClassesOp::SetDefaultIfEmpty => if self.default.is_empty() {
ClassesOp::SetDefaultIfEmpty => {
if self.default.is_empty() {
self.default = classes.to_owned()
},
}
}
}
self
}
@ -100,7 +102,11 @@ impl Classes {
if self.default.is_empty() && self.added.is_empty() {
None
} else {
Some(concat_string!(self.default, " ", self.added).trim().to_owned())
Some(
concat_string!(self.default, " ", self.added)
.trim()
.to_owned(),
)
}
}
}

View file

@ -1,4 +1,4 @@
use crate::html::{Markup, PreEscaped, html};
use crate::html::{html, Markup, PreEscaped};
pub struct Favicon(Vec<String>);
@ -29,32 +29,29 @@ impl Favicon {
pub fn with_theme_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"theme-color\" content=\"{}\">", color
"<meta name=\"theme-color\" content=\"{}\">",
color
));
self
}
pub fn with_ms_tile_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileColor\" content=\"{}\">", color
"<meta name=\"msapplication-TileColor\" content=\"{}\">",
color
));
self
}
pub fn with_ms_tile_image(mut self, image: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileImage\" content=\"{}\">", image
"<meta name=\"msapplication-TileImage\" content=\"{}\">",
image
));
self
}
fn add_item(
mut self,
rel : &str,
source: &str,
sizes : &str,
color : &str
) -> Self {
fn add_item(mut self, rel: &str, source: &str, sizes: &str, color: &str) -> Self {
let mut link: String = format!("<link rel=\"{}\"", rel);
if let Some(i) = source.rfind('.') {
link = match source[i..].to_owned().to_lowercase().as_str() {
@ -63,7 +60,7 @@ impl Favicon {
".jpg" => format!("{} type=\"image/jpg\"", link),
".png" => format!("{} type=\"image/png\"", link),
".svg" => format!("{} type=\"image/svg+xml\"", link),
_ => link
_ => link,
};
}
if !sizes.is_empty() {

View file

@ -1,32 +1,42 @@
// External re-exports.
// EXTERNAL RE-EXPORTS.
pub use once_cell::sync::Lazy;
pub use concat_string::concat_string;
pub use doc_comment::doc_comment;
pub use once_cell::sync::Lazy;
// Local.
// LOCAL.
#[allow(unused_imports)]
pub(crate) use futures::executor::block_on as run_now;
// Public APIs.
// PUBLIC APIs.
pub mod config; // Gestión de la configuración.
pub mod trace; // Registro de trazas y eventos de la aplicación.
pub mod locale; // Localización.
pub mod html; // HTML en código.
// Gestión de la configuración.
pub mod config;
// Registro de trazas y eventos de la aplicación.
pub mod trace;
// Localización.
pub mod locale;
// HTML en código.
pub mod html;
// Acceso a base de datos.
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub mod db; // Acceso a base de datos.
pub mod db;
pub mod app; // Prepare and run the application.
// Prepare and run the application.
pub mod app;
pub mod core; // Main APIs for components, hooks, modules and themes.
// Main APIs for components, hooks, modules and themes.
pub mod core;
pub mod response; // Tipos de respuestas web.
pub mod base; // Base de componentes, módulos y temas.
pub mod util; // Macros y funciones útiles.
// Tipos de respuestas web.
pub mod response;
// Base de componentes, módulos y temas.
pub mod base;
// Macros y funciones útiles.
pub mod util;
// Internal re-exports.
// INTERNAL RE-EXPORTS.
pub mod prelude;

View file

@ -1,6 +1,6 @@
pub use fluent_templates;
pub use fluent_templates::{Loader as Locale, static_loader as static_locale};
pub use fluent_templates::fluent_bundle::FluentValue;
pub use fluent_templates::{static_loader as static_locale, Loader as Locale};
#[macro_export]
/// Permite integrar fácilmente localización en temas, módulos y componentes.

View file

@ -1,41 +1,26 @@
//! Re-exporta recursos comunes.
// Global macros and helpers.
pub use crate::{
args,
concat_string,
theme_static_files,
util,
};
pub use crate::{args, concat_string, theme_static_files, util};
pub use crate::config::SETTINGS;
pub use crate::trace;
pub use crate::localize;
pub use crate::html::*;
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub use crate::{
db,
db::*,
pub_migration,
migration_item,
};
pub use crate::{db, db::*, migration_item, pub_migration};
pub use crate::app;
pub use crate::app::AppTrait;
pub use crate::app::application::Application;
pub use crate::app::AppTrait;
pub use crate::core::{
component::*,
hook::*,
module::*,
theme::*,
};
pub use crate::{
hook_action,
hook_before_render_component,
};
pub use crate::core::{component::*, hook::*, module::*, theme::*};
pub use crate::{hook_action, hook_before_render_component};
pub use crate::response::page::*;

View file

@ -1,8 +1,5 @@
mod hook;
pub use hook::{
HOOK_BEFORE_RENDER_PAGE,
BeforeRenderPageHook,
};
pub use hook::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};
mod definition;
pub use definition::Page;

View file

@ -1,9 +1,9 @@
use crate::{Lazy, app, trace};
use super::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};
use crate::config::SETTINGS;
use crate::html::*;
use crate::core::hook::{action_ref, run_actions};
use crate::core::component::*;
use super::{HOOK_BEFORE_RENDER_PAGE, BeforeRenderPageHook};
use crate::core::hook::{action_ref, run_actions};
use crate::html::*;
use crate::{app, trace, Lazy};
use std::collections::HashMap;
@ -34,7 +34,11 @@ static DEFAULT_DIRECTION: Lazy<Option<String>> = Lazy::new(|| {
}
});
pub enum TextDirection { Auto, LeftToRight, RightToLeft }
pub enum TextDirection {
Auto,
LeftToRight,
RightToLeft,
}
pub struct Page {
context : InContext,
@ -48,7 +52,6 @@ pub struct Page {
}
impl Page {
pub fn new() -> Self {
Page {
context : InContext::new(),
@ -100,15 +103,12 @@ impl Page {
self
}
pub fn add_to(
mut self,
region: &'static str,
component: impl ComponentTrait
) -> Self {
pub fn add_to(mut self, region: &'static str, component: impl ComponentTrait) -> Self {
if let Some(regions) = self.regions.get_mut(region) {
regions.add(component);
} else {
self.regions.insert(region, ComponentsBundle::new_with(component));
self.regions
.insert(region, ComponentsBundle::new_with(component));
}
self
}
@ -193,10 +193,9 @@ impl Page {
pub fn render(&mut self) -> app::Result<Markup> {
// Acciones de los módulos antes de renderizar la página.
run_actions(
HOOK_BEFORE_RENDER_PAGE,
|hook| action_ref::<BeforeRenderPageHook>(&**hook).run(self)
);
run_actions(HOOK_BEFORE_RENDER_PAGE, |hook| {
action_ref::<BeforeRenderPageHook>(&**hook).run(self)
});
// Acciones del tema antes de renderizar la página.
self.context.theme().before_render_page(self);
@ -208,7 +207,7 @@ impl Page {
let head = self.context.theme().render_page_head(self);
// Finalmente, renderizar la página.
return Ok(html! {
Ok(html! {
(DOCTYPE)
html lang=[self.language().get()] dir=[self.direction().get()] {
(head)
@ -220,10 +219,9 @@ impl Page {
pub fn render_region(&mut self, region: &str) -> Markup {
match self.regions.get_mut(region) {
Some(components) => components.render(&mut self.context),
None => html! {}
None => html! {},
}
}
// Page EXTRAS.
}

View file

@ -1,5 +1,5 @@
use crate::core::hook::{HookTrait, AnyHook};
use super::Page;
use crate::core::hook::{AnyHook, HookTrait};
pub const HOOK_BEFORE_RENDER_PAGE: &str = "pagetop::hook::before_render_page";

View file

@ -1,2 +1,2 @@
pub use tracing::{Level, event, span};
pub use tracing::{debug, error, info, trace, warn};
pub use tracing::{event, span, Level};

View file

@ -23,15 +23,11 @@ macro_rules! theme_static_files {
( $cfg:ident, $dir:expr ) => {{
let static_files = &$crate::config::SETTINGS.dev.static_files;
if static_files.is_empty() {
$cfg.service(actix_web_static_files::ResourceFiles::new(
$dir,
generate()
));
$cfg.service(actix_web_static_files::ResourceFiles::new($dir, generate()));
} else {
$cfg.service(actix_files::Files::new(
$dir,
&[static_files, $dir].join("")
).show_files_listing());
$cfg.service(
actix_files::Files::new($dir, &[static_files, $dir].join("")).show_files_listing(),
);
}
}};
}

View file

@ -2,8 +2,7 @@ use pagetop::prelude::*;
struct PageTopWebSite;
impl AppTrait for PageTopWebSite {
}
impl AppTrait for PageTopWebSite {}
#[actix_web::main]
async fn main() -> std::io::Result<()> {