Modifica la estructura de preparación de una app

This commit is contained in:
Manuel Cillero 2022-05-08 11:10:18 +02:00
parent af9afca777
commit fcc022d164
42 changed files with 295 additions and 228 deletions

View file

@ -1,12 +1,18 @@
use pagetop::prelude::*; use pagetop::{prelude::*, core::app::AppTrait};
fn bootstrap() { struct Drust;
include_module(&pagetop_admin::Admin);
include_module(&pagetop_user::User); impl AppTrait for Drust {
include_module(&pagetop_node::Node); fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> {
vec![
&pagetop_admin::Admin,
&pagetop_user::User,
&pagetop_node::Node,
]
}
} }
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
Application::prepare(UsingBootstrap::Fn(bootstrap)).await?.run()?.await Application::prepare(Drust).await?.run()?.await
} }

View file

@ -28,9 +28,9 @@ impl ModuleTrait for Admin {
); );
} }
fn actions(&self) -> Vec<ActionItem> { fn actions(&self) -> Vec<HookItem> {
vec![ vec![
action_item!(ActionBeforeRenderPage => before_render_page) hook_item!(BeforeRenderPageHook => before_render_page)
] ]
} }
} }

View file

@ -26,9 +26,9 @@ impl ModuleTrait for Node {
cfg.route("/node", app::web::get().to(node)); cfg.route("/node", app::web::get().to(node));
} }
fn actions(&self) -> Vec<ActionItem> { fn actions(&self) -> Vec<HookItem> {
vec![ vec![
action_item!(ActionBeforeRenderPage => before_render_page, -1) hook_item!(BeforeRenderPageHook => before_render_page, -1)
] ]
} }

View file

@ -1,17 +0,0 @@
pub use std::any::Any as AnyAction;
pub trait ActionTrait: AnyAction + Send + Sync {
fn new() -> Self where Self: Sized;
fn handler(&self) -> &'static str;
fn weight(&self) -> isize {
0
}
fn as_ref_any(&self) -> &dyn AnyAction;
}
pub fn action_ref<A: 'static>(action: &dyn ActionTrait) -> &A {
action.as_ref_any().downcast_ref::<A>().unwrap()
}

View file

@ -1,14 +0,0 @@
mod definition;
pub use definition::{
ActionTrait,
AnyAction,
action_ref,
};
mod holder;
pub use holder::ActionItem;
use holder::ActionsHolder;
mod all;
pub use all::run_actions;
pub(crate) use all::add_action;

View file

@ -1,48 +0,0 @@
use crate::api::action::{ActionTrait, AnyAction};
use super::{Assets, ComponentTrait};
pub const BEFORE_RENDER_COMPONENT_ACTION: &str = "pagetop::action::before_render_component";
pub struct BeforeRenderComponentAction {
action: Option<fn(&mut dyn ComponentTrait, &mut Assets)>,
weight: isize,
}
impl ActionTrait for BeforeRenderComponentAction {
fn new() -> Self {
BeforeRenderComponentAction {
action: None,
weight: 0,
}
}
fn handler(&self) -> &'static str {
BEFORE_RENDER_COMPONENT_ACTION
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyAction {
self
}
}
impl BeforeRenderComponentAction {
pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self {
self.action = Some(action);
self
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) {
if let Some(action) = self.action {
action(component, assets)
}
}
}

View file

@ -95,7 +95,7 @@ impl Form {
self self
} }
pub fn with_action(mut self, action: &str) -> Self { pub fn with_hook(mut self, action: &str) -> Self {
self.alter_action(action); self.alter_action(action);
self self
} }

View file

@ -1,57 +1,63 @@
use crate::{Lazy, app, base, trace}; use crate::{Lazy, base, trace};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::api::{module, theme}; use crate::core::{module, theme};
use super::AppTrait;
use std::io::Error; use std::io::Error;
use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash};
pub struct Application { pub struct Application {
server: app::Server, server: super::Server,
} }
pub enum UsingBootstrap {Fn(fn()), No}
impl Application { impl Application {
pub async fn prepare(bootstrap: UsingBootstrap) -> Result<Self, Error> { pub async fn prepare(brrrz: impl AppTrait) -> Result<Self, Error> {
// Rótulo de presentación. // Rótulo de presentación.
app::banner::print_on_startup(); super::banner::print_on_startup();
// Inicia registro de trazas y eventos. // Inicia registro de trazas y eventos.
Lazy::force(&app::tracing::TRACING); Lazy::force(&super::tracing::TRACING);
// Valida el identificador de idioma. // Valida el identificador de idioma.
Lazy::force(&app::locale::LANGID); Lazy::force(&super::locale::LANGID);
// Conecta con la base de datos (opcional). // Conecta con la base de datos (opcional).
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
Lazy::force(&app::db::DBCONN); Lazy::force(&super::db::DBCONN);
// Registra los temas predeterminados. // Registra los temas predeterminados.
theme::register_theme(&base::theme::aliner::Aliner); theme::register_themes(vec![
theme::register_theme(&base::theme::minimal::Minimal); &base::theme::aliner::Aliner,
theme::register_theme(&base::theme::bootsier::Bootsier); &base::theme::minimal::Minimal,
theme::register_theme(&base::theme::bulmix::Bulmix); &base::theme::bootsier::Bootsier,
&base::theme::bulmix::Bulmix,
]);
theme::register_themes(brrrz.register_themes());
// Habilita los módulos predeterminados.
module::enable_modules(brrrz.enabled_modules());
// Habilita el módulo de presentación de PageTop.
// Normalmente se sobrecargará en la función de inicio.
module::enable_module(&base::module::demopage::Demopage);
// Registra las acciones de todos los módulos.
module::all::register_hooks();
// 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");
brrrz.bootstrap();
/*
if let UsingBootstrap::Fn(bootstrap) = bootstrap { if let UsingBootstrap::Fn(bootstrap) = bootstrap {
let _ = &bootstrap(); let _ = &bootstrap();
} }*/
// Registra el módulo de presentación de PageTop.
// Normalmente se sobrecargará en la función de inicio.
module::include_module(&base::module::demopage::Demopage);
// Registra las acciones de todos los módulos.
module::all::register_actions();
// 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"))]
module::all::run_migrations(); module::all::run_migrations();
// Prepara el servidor web. // Prepara el servidor web.
let server = app::HttpServer::new(move || { let server = super::HttpServer::new(move || {
app::App::new() super::App::new()
.wrap(tracing_actix_web::TracingLogger) .wrap(tracing_actix_web::TracingLogger)
.wrap(NormalizePath::new(TrailingSlash::Trim)) .wrap(NormalizePath::new(TrailingSlash::Trim))
.configure(&module::all::modules) .configure(&module::all::modules)
@ -66,7 +72,7 @@ impl Application {
Ok(Self { server }) Ok(Self { server })
} }
pub fn run(self) -> Result<app::Server, Error> { pub fn run(self) -> Result<super::Server, Error> {
Ok(self.server) Ok(self.server)
} }
} }

View file

@ -0,0 +1,19 @@
use crate::core::module::ModuleTrait;
use crate::core::theme::ThemeTrait;
pub trait AppTrait: Send + Sync {
fn bootstrap(&self) {
}
fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> {
vec![]
}
fn disabled_modules(&self) -> Vec<&'static dyn ModuleTrait> {
vec![]
}
fn register_themes(&self) -> Vec<&'static dyn ThemeTrait> {
vec![]
}
}

View file

@ -12,4 +12,7 @@ pub mod locale;
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub mod db; pub mod db;
mod definition;
pub use definition::AppTrait;
pub mod application; pub mod application;

View file

@ -1,7 +1,7 @@
use crate::{Lazy, base, concat_string, util}; use crate::{Lazy, base, concat_string, util};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Markup, PreEscaped, html}; use crate::html::{Markup, PreEscaped, html};
use crate::api::theme::*; use crate::core::theme::*;
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
match theme_by_single_name(&SETTINGS.app.theme) { match theme_by_single_name(&SETTINGS.app.theme) {

View file

@ -1,7 +1,7 @@
use crate::util; use crate::util;
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use crate::api::action::{action_ref, run_actions}; use crate::core::hook::{hook_ref, run_hooks};
use super::{BEFORE_RENDER_COMPONENT_ACTION, BeforeRenderComponentAction}; use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook};
use super::Assets; use super::Assets;
pub use std::any::Any as AnyComponent; pub use std::any::Any as AnyComponent;
@ -54,9 +54,9 @@ pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets)
component.before_render(assets); component.before_render(assets);
// Acciones de los módulos antes de renderizar el componente. // Acciones de los módulos antes de renderizar el componente.
run_actions( run_hooks(
BEFORE_RENDER_COMPONENT_ACTION, BEFORE_RENDER_COMPONENT_HOOK,
|a| action_ref::<BeforeRenderComponentAction>(&**a).run(component, assets) |a| hook_ref::<BeforeRenderComponentHook>(&**a).run(component, assets)
); );
// Acciones del tema antes de renderizar el componente. // Acciones del tema antes de renderizar el componente.

View file

@ -0,0 +1,48 @@
use crate::core::hook::{HookTrait, AnyHook};
use super::{Assets, ComponentTrait};
pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::action::before_render_component";
pub struct BeforeRenderComponentHook {
hook: Option<fn(&mut dyn ComponentTrait, &mut Assets)>,
weight: isize,
}
impl HookTrait for BeforeRenderComponentHook {
fn new() -> Self {
BeforeRenderComponentHook {
hook: None,
weight: 0,
}
}
fn handler(&self) -> &'static str {
BEFORE_RENDER_COMPONENT_HOOK
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyHook {
self
}
}
impl BeforeRenderComponentHook {
pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self {
self.hook = Some(hook);
self
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) {
if let Some(hook) = self.hook {
hook(component, assets)
}
}
}

View file

@ -1,7 +1,7 @@
mod action; mod hook;
pub use action::{ pub use hook::{
BEFORE_RENDER_COMPONENT_ACTION, BEFORE_RENDER_COMPONENT_HOOK,
BeforeRenderComponentAction, BeforeRenderComponentHook,
}; };
mod assets; mod assets;

View file

@ -1,25 +1,25 @@
use crate::Lazy; use crate::Lazy;
use super::{ActionItem, ActionsHolder}; use super::{HookItem, HooksHolder};
use std::sync::RwLock; use std::sync::RwLock;
use std::collections::HashMap; use std::collections::HashMap;
// Registered actions. // Registered actions.
static ACTIONS: Lazy<RwLock<HashMap<&str, ActionsHolder>>> = Lazy::new(|| { static ACTIONS: Lazy<RwLock<HashMap<&str, HooksHolder>>> = Lazy::new(|| {
RwLock::new(HashMap::new()) RwLock::new(HashMap::new())
}); });
pub fn add_action(action: ActionItem) { pub fn add_hook(action: HookItem) {
let mut hmap = ACTIONS.write().unwrap(); let mut hmap = ACTIONS.write().unwrap();
let action_handler = action.handler(); let action_handler = action.handler();
if let Some(actions) = hmap.get_mut(action_handler) { if let Some(actions) = hmap.get_mut(action_handler) {
actions.add(action); actions.add(action);
} else { } else {
hmap.insert(action_handler, ActionsHolder::new_with(action)); hmap.insert(action_handler, HooksHolder::new_with(action));
} }
} }
pub fn run_actions<B, F>(action_handler: &str, f: F) where F: FnMut(&ActionItem) -> B { pub fn run_hooks<B, F>(action_handler: &str, f: F) where F: FnMut(&HookItem) -> B {
if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) { if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) {
actions.iter_map(f) actions.iter_map(f)
} }

View file

@ -0,0 +1,17 @@
pub use std::any::Any as AnyHook;
pub trait HookTrait: AnyHook + Send + Sync {
fn new() -> Self where Self: Sized;
fn handler(&self) -> &'static str;
fn weight(&self) -> isize {
0
}
fn as_ref_any(&self) -> &dyn AnyHook;
}
pub fn hook_ref<A: 'static>(action: &dyn HookTrait) -> &A {
action.as_ref_any().downcast_ref::<A>().unwrap()
}

View file

@ -1,36 +1,36 @@
use super::ActionTrait; use super::HookTrait;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
pub type ActionItem = Box<dyn ActionTrait>; pub type HookItem = Box<dyn HookTrait>;
#[macro_export] #[macro_export]
macro_rules! action_item { macro_rules! hook_item {
( $action:ident => $f:ident $(, $weight:expr)? ) => {{ ( $action:ident => $f:ident $(, $weight:expr)? ) => {{
Box::new($action::new().with_action($f)$(.with_weight($weight))?) Box::new($action::new().with_hook($f)$(.with_weight($weight))?)
}}; }};
} }
pub struct ActionsHolder(Arc<RwLock<Vec<ActionItem>>>); pub struct HooksHolder(Arc<RwLock<Vec<HookItem>>>);
impl ActionsHolder { impl HooksHolder {
pub fn new() -> Self { pub fn new() -> Self {
ActionsHolder(Arc::new(RwLock::new(Vec::new()))) HooksHolder(Arc::new(RwLock::new(Vec::new())))
} }
pub fn new_with(action: ActionItem) -> Self { pub fn new_with(action: HookItem) -> Self {
let mut container = ActionsHolder::new(); let mut container = HooksHolder::new();
container.add(action); container.add(action);
container container
} }
pub fn add(&mut self, action: ActionItem) { pub fn add(&mut self, action: HookItem) {
let mut actions = self.0.write().unwrap(); let mut actions = self.0.write().unwrap();
actions.push(action); actions.push(action);
actions.sort_by_key(|a| a.weight()); actions.sort_by_key(|a| a.weight());
} }
pub fn iter_map<B, F>(&self, f: F) where Self: Sized, F: FnMut(&ActionItem) -> B { pub fn iter_map<B, F>(&self, f: F) where Self: Sized, F: FnMut(&HookItem) -> B {
let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect(); let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect();
} }
} }

View file

@ -0,0 +1,14 @@
mod definition;
pub use definition::{
HookTrait,
AnyHook,
hook_ref,
};
mod holder;
pub use holder::HookItem;
use holder::HooksHolder;
mod all;
pub use all::run_hooks;
pub(crate) use all::add_hook;

View file

@ -1,4 +1,5 @@
pub mod action; // API to define functions that alter the behavior of PageTop core. pub mod app; // API to initialize the PageTop base application.
pub mod component; // API to build new components. 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 module; // API to add new features with modules.
pub mod theme; // API to create themes. pub mod theme; // API to create themes.

View file

@ -1,26 +1,38 @@
use crate::{Lazy, app, run_now, trace}; use crate::{Lazy, run_now, trace};
use crate::api::action::add_action; use crate::core::app;
use crate::core::hook::add_hook;
use crate::db::*; use crate::db::*;
use super::ModuleTrait; use super::ModuleTrait;
use std::sync::RwLock; use std::sync::RwLock;
// Módulos registrados. // Enabled modules.
static MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| { static ENABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new()) RwLock::new(Vec::new())
}); });
pub fn include_module(module: &'static dyn ModuleTrait) { /* Disabled modules.
static DISABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new())
}); */
pub fn enable_modules(modules: Vec<&'static dyn ModuleTrait>) {
for m in modules {
enable_module(m)
}
}
pub fn enable_module(module: &'static dyn ModuleTrait) {
let mut list: Vec<&dyn ModuleTrait> = Vec::new(); let mut list: Vec<&dyn ModuleTrait> = Vec::new();
add_to(&mut list, module); add_to(&mut list, module);
list.reverse(); list.reverse();
MODULES.write().unwrap().append(&mut list); ENABLED_MODULES.write().unwrap().append(&mut list);
} }
fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) {
if !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()) { if !list.iter().any(|m| m.handler() == module.handler()) {
trace::debug!("Including module \"{}\"", module.single_name()); trace::debug!("Enabling module \"{}\"", module.single_name());
list.push(module); list.push(module);
let mut dependencies = module.dependencies(); let mut dependencies = module.dependencies();
@ -32,16 +44,20 @@ fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) {
} }
} }
#[allow(unused_variables)]
pub fn disable_module(module: &'static dyn ModuleTrait) {
}
pub fn modules(cfg: &mut app::web::ServiceConfig) { pub fn modules(cfg: &mut app::web::ServiceConfig) {
for m in MODULES.read().unwrap().iter() { for m in ENABLED_MODULES.read().unwrap().iter() {
m.configure_service(cfg); m.configure_service(cfg);
} }
} }
pub fn register_actions() { pub fn register_hooks() {
for m in MODULES.read().unwrap().iter() { for m in ENABLED_MODULES.read().unwrap().iter() {
for a in m.actions().into_iter() { for a in m.actions().into_iter() {
add_action(a); add_hook(a);
} }
} }
} }
@ -53,7 +69,7 @@ pub fn run_migrations() {
impl MigratorTrait for Migrator { impl MigratorTrait for Migrator {
fn migrations() -> Vec<MigrationItem> { fn migrations() -> Vec<MigrationItem> {
let mut migrations = vec![]; let mut migrations = vec![];
for m in MODULES.read().unwrap().iter() { for m in ENABLED_MODULES.read().unwrap().iter() {
migrations.append(&mut m.migrations()); migrations.append(&mut m.migrations());
} }
migrations migrations

View file

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

View file

@ -6,5 +6,7 @@ pub use definition::{
pub(crate) mod all; pub(crate) mod all;
pub use all::{ pub use all::{
include_module, disable_module,
enable_module,
enable_modules,
}; };

View file

@ -1,4 +1,5 @@
use crate::{Lazy, app, theme_static_files, trace}; use crate::{Lazy, theme_static_files, trace};
use crate::core::app;
use super::ThemeTrait; use super::ThemeTrait;
use std::sync::RwLock; use std::sync::RwLock;
@ -10,6 +11,12 @@ static THEMES: Lazy<RwLock<Vec<&dyn ThemeTrait>>> = Lazy::new(|| {
RwLock::new(Vec::new()) RwLock::new(Vec::new())
}); });
pub fn register_themes(themes: Vec<&'static dyn ThemeTrait>) {
for t in themes {
register_theme(t)
}
}
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();
if !themes.iter().any(|t| t.handler() == theme.handler()) { if !themes.iter().any(|t| t.handler() == theme.handler()) {

View file

@ -1,7 +1,8 @@
use crate::{app, concat_string, util}; use crate::{concat_string, util};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use crate::api::component::{Assets, ComponentTrait, Favicon}; use crate::core::app;
use crate::core::component::{Assets, ComponentTrait, Favicon};
use crate::response::page::Page; use crate::response::page::Page;
use crate::base::component::Chunck; use crate::base::component::Chunck;

View file

@ -7,5 +7,6 @@ pub use definition::{
pub(crate) mod all; pub(crate) mod all;
pub use all::{ pub use all::{
register_theme, register_theme,
register_themes,
theme_by_single_name, theme_by_single_name,
}; };

View file

@ -18,10 +18,10 @@ pub mod html; // HTML en código.
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
pub mod db; // Acceso a base de datos. pub mod db; // Acceso a base de datos.
pub mod api; // Main APIs for actions, components, modules and themes. pub mod core; // Main APIs for actions, components, modules and themes.
pub mod response; // Tipos de respuestas web. pub mod response; // Tipos de respuestas web.
pub mod app; // Aplicación y servidor web. //pub mod app; // Aplicación y servidor web.
pub mod base; // Base de componentes, módulos y temas. pub mod base; // Base de componentes, módulos y temas.
pub mod util; // Macros y funciones útiles. pub mod util; // Macros y funciones útiles.

View file

@ -7,7 +7,7 @@ pub use fluent_templates::fluent_bundle::FluentValue;
macro_rules! localize { macro_rules! localize {
( $dir_locales:literal $(, $core_locales:literal)? ) => { ( $dir_locales:literal $(, $core_locales:literal)? ) => {
use $crate::locale::*; use $crate::locale::*;
use $crate::app::locale::LANGID; use $crate::core::app::locale::LANGID;
static_locale! { static_locale! {
static LOCALES = { static LOCALES = {

View file

@ -20,17 +20,20 @@ pub use crate::{
migration_item, migration_item,
}; };
pub use crate::{action_item, api::{ pub use crate::{hook_item, core::{
action::*, // app::*,
component::*, component::*,
hook::*,
module::*, module::*,
theme::*, theme::*,
}}; }};
pub use crate::core::app;
pub use crate::core::app::application::Application;
pub use crate::response::page::*; pub use crate::response::page::*;
pub use crate::app; //pub use crate::app;
pub use crate::app::application::{Application, UsingBootstrap}; //pub use crate::app::application::{Application, UsingBootstrap};
pub use crate::base::component::*; pub use crate::base::component::*;

View file

@ -1,48 +0,0 @@
use crate::api::action::{ActionTrait, AnyAction};
use super::Page;
pub const BEFORE_RENDER_PAGE_ACTION: &str = "pagetop::action::before_render_page";
pub struct ActionBeforeRenderPage {
action: Option<fn(&mut Page)>,
weight: isize,
}
impl ActionTrait for ActionBeforeRenderPage {
fn new() -> Self {
ActionBeforeRenderPage {
action: None,
weight: 0,
}
}
fn handler(&self) -> &'static str {
BEFORE_RENDER_PAGE_ACTION
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyAction {
self
}
}
impl ActionBeforeRenderPage {
pub fn with_action(mut self, action: fn(&mut Page)) -> Self {
self.action = Some(action);
self
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, page: &mut Page) {
if let Some(action) = self.action {
action(page)
}
}
}

View file

@ -0,0 +1,48 @@
use crate::core::hook::{HookTrait, AnyHook};
use super::Page;
pub const BEFORE_RENDER_PAGE_HOOK: &str = "pagetop::action::before_render_page";
pub struct BeforeRenderPageHook {
hook: Option<fn(&mut Page)>,
weight: isize,
}
impl HookTrait for BeforeRenderPageHook {
fn new() -> Self {
BeforeRenderPageHook {
hook: None,
weight: 0,
}
}
fn handler(&self) -> &'static str {
BEFORE_RENDER_PAGE_HOOK
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyHook {
self
}
}
impl BeforeRenderPageHook {
pub fn with_hook(mut self, hook: fn(&mut Page)) -> Self {
self.hook = Some(hook);
self
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, page: &mut Page) {
if let Some(hook) = self.hook {
hook(page)
}
}
}

View file

@ -1,7 +1,7 @@
mod action; mod hook;
pub use action::{ pub use hook::{
BEFORE_RENDER_PAGE_ACTION, BEFORE_RENDER_PAGE_HOOK,
ActionBeforeRenderPage, BeforeRenderPageHook,
}; };
mod page; mod page;

View file

@ -1,9 +1,10 @@
use crate::{Lazy, app, trace}; use crate::{Lazy, trace};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::*; use crate::html::*;
use crate::api::action::{action_ref, run_actions}; use crate::core::app;
use crate::api::component::*; use crate::core::hook::{hook_ref, run_hooks};
use super::{BEFORE_RENDER_PAGE_ACTION, ActionBeforeRenderPage}; use crate::core::component::*;
use super::{BEFORE_RENDER_PAGE_HOOK, BeforeRenderPageHook};
use std::collections::HashMap; use std::collections::HashMap;
@ -151,9 +152,9 @@ impl<'a> Page<'a> {
pub fn render(&mut self) -> app::Result<Markup> { pub fn render(&mut self) -> app::Result<Markup> {
// Acciones de los módulos antes de renderizar la página. // Acciones de los módulos antes de renderizar la página.
run_actions( run_hooks(
BEFORE_RENDER_PAGE_ACTION, BEFORE_RENDER_PAGE_HOOK,
|a| action_ref::<ActionBeforeRenderPage>(&**a).run(self) |a| hook_ref::<BeforeRenderPageHook>(&**a).run(self)
); );
// Acciones del tema antes de renderizar la página. // Acciones del tema antes de renderizar la página.