Modifica la estructura de preparación de una app
This commit is contained in:
parent
af9afca777
commit
fcc022d164
42 changed files with 295 additions and 228 deletions
|
|
@ -1,12 +1,18 @@
|
|||
use pagetop::prelude::*;
|
||||
use pagetop::{prelude::*, core::app::AppTrait};
|
||||
|
||||
fn bootstrap() {
|
||||
include_module(&pagetop_admin::Admin);
|
||||
include_module(&pagetop_user::User);
|
||||
include_module(&pagetop_node::Node);
|
||||
struct Drust;
|
||||
|
||||
impl AppTrait for Drust {
|
||||
fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> {
|
||||
vec![
|
||||
&pagetop_admin::Admin,
|
||||
&pagetop_user::User,
|
||||
&pagetop_node::Node,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
Application::prepare(UsingBootstrap::Fn(bootstrap)).await?.run()?.await
|
||||
Application::prepare(Drust).await?.run()?.await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ impl ModuleTrait for Admin {
|
|||
);
|
||||
}
|
||||
|
||||
fn actions(&self) -> Vec<ActionItem> {
|
||||
fn actions(&self) -> Vec<HookItem> {
|
||||
vec![
|
||||
action_item!(ActionBeforeRenderPage => before_render_page)
|
||||
hook_item!(BeforeRenderPageHook => before_render_page)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ impl ModuleTrait for Node {
|
|||
cfg.route("/node", app::web::get().to(node));
|
||||
}
|
||||
|
||||
fn actions(&self) -> Vec<ActionItem> {
|
||||
fn actions(&self) -> Vec<HookItem> {
|
||||
vec![
|
||||
action_item!(ActionBeforeRenderPage => before_render_page, -1)
|
||||
hook_item!(BeforeRenderPageHook => before_render_page, -1)
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ impl Form {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn with_action(mut self, action: &str) -> Self {
|
||||
pub fn with_hook(mut self, action: &str) -> Self {
|
||||
self.alter_action(action);
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +1,63 @@
|
|||
use crate::{Lazy, app, base, trace};
|
||||
use crate::{Lazy, base, trace};
|
||||
use crate::config::SETTINGS;
|
||||
use crate::api::{module, theme};
|
||||
use crate::core::{module, theme};
|
||||
use super::AppTrait;
|
||||
|
||||
use std::io::Error;
|
||||
use actix_web::middleware::normalize::{NormalizePath, TrailingSlash};
|
||||
|
||||
pub struct Application {
|
||||
server: app::Server,
|
||||
server: super::Server,
|
||||
}
|
||||
|
||||
pub enum UsingBootstrap {Fn(fn()), No}
|
||||
|
||||
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.
|
||||
app::banner::print_on_startup();
|
||||
super::banner::print_on_startup();
|
||||
|
||||
// Inicia registro de trazas y eventos.
|
||||
Lazy::force(&app::tracing::TRACING);
|
||||
Lazy::force(&super::tracing::TRACING);
|
||||
|
||||
// Valida el identificador de idioma.
|
||||
Lazy::force(&app::locale::LANGID);
|
||||
Lazy::force(&super::locale::LANGID);
|
||||
|
||||
// Conecta con la base de datos (opcional).
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
Lazy::force(&app::db::DBCONN);
|
||||
Lazy::force(&super::db::DBCONN);
|
||||
|
||||
// Registra los temas predeterminados.
|
||||
theme::register_theme(&base::theme::aliner::Aliner);
|
||||
theme::register_theme(&base::theme::minimal::Minimal);
|
||||
theme::register_theme(&base::theme::bootsier::Bootsier);
|
||||
theme::register_theme(&base::theme::bulmix::Bulmix);
|
||||
theme::register_themes(vec![
|
||||
&base::theme::aliner::Aliner,
|
||||
&base::theme::minimal::Minimal,
|
||||
&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.
|
||||
trace::info!("Calling application bootstrap");
|
||||
brrrz.bootstrap();
|
||||
/*
|
||||
if let UsingBootstrap::Fn(bootstrap) = 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).
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
module::all::run_migrations();
|
||||
|
||||
// Prepara el servidor web.
|
||||
let server = app::HttpServer::new(move || {
|
||||
app::App::new()
|
||||
let server = super::HttpServer::new(move || {
|
||||
super::App::new()
|
||||
.wrap(tracing_actix_web::TracingLogger)
|
||||
.wrap(NormalizePath::new(TrailingSlash::Trim))
|
||||
.configure(&module::all::modules)
|
||||
|
|
@ -66,7 +72,7 @@ impl Application {
|
|||
Ok(Self { server })
|
||||
}
|
||||
|
||||
pub fn run(self) -> Result<app::Server, Error> {
|
||||
pub fn run(self) -> Result<super::Server, Error> {
|
||||
Ok(self.server)
|
||||
}
|
||||
}
|
||||
19
pagetop/src/core/app/definition.rs
Normal file
19
pagetop/src/core/app/definition.rs
Normal 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![]
|
||||
}
|
||||
}
|
||||
|
|
@ -12,4 +12,7 @@ pub mod locale;
|
|||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
pub mod db;
|
||||
|
||||
mod definition;
|
||||
pub use definition::AppTrait;
|
||||
|
||||
pub mod application;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Lazy, base, concat_string, util};
|
||||
use crate::config::SETTINGS;
|
||||
use crate::html::{Markup, PreEscaped, html};
|
||||
use crate::api::theme::*;
|
||||
use crate::core::theme::*;
|
||||
|
||||
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
|
||||
match theme_by_single_name(&SETTINGS.app.theme) {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::util;
|
||||
use crate::html::{Markup, html};
|
||||
use crate::api::action::{action_ref, run_actions};
|
||||
use super::{BEFORE_RENDER_COMPONENT_ACTION, BeforeRenderComponentAction};
|
||||
use crate::core::hook::{hook_ref, run_hooks};
|
||||
use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook};
|
||||
use super::Assets;
|
||||
|
||||
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);
|
||||
|
||||
// Acciones de los módulos antes de renderizar el componente.
|
||||
run_actions(
|
||||
BEFORE_RENDER_COMPONENT_ACTION,
|
||||
|a| action_ref::<BeforeRenderComponentAction>(&**a).run(component, assets)
|
||||
run_hooks(
|
||||
BEFORE_RENDER_COMPONENT_HOOK,
|
||||
|a| hook_ref::<BeforeRenderComponentHook>(&**a).run(component, assets)
|
||||
);
|
||||
|
||||
// Acciones del tema antes de renderizar el componente.
|
||||
48
pagetop/src/core/component/hook.rs
Normal file
48
pagetop/src/core/component/hook.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
mod action;
|
||||
pub use action::{
|
||||
BEFORE_RENDER_COMPONENT_ACTION,
|
||||
BeforeRenderComponentAction,
|
||||
mod hook;
|
||||
pub use hook::{
|
||||
BEFORE_RENDER_COMPONENT_HOOK,
|
||||
BeforeRenderComponentHook,
|
||||
};
|
||||
|
||||
mod assets;
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
use crate::Lazy;
|
||||
use super::{ActionItem, ActionsHolder};
|
||||
use super::{HookItem, HooksHolder};
|
||||
|
||||
use std::sync::RwLock;
|
||||
use std::collections::HashMap;
|
||||
|
||||
// Registered actions.
|
||||
static ACTIONS: Lazy<RwLock<HashMap<&str, ActionsHolder>>> = Lazy::new(|| {
|
||||
static ACTIONS: Lazy<RwLock<HashMap<&str, HooksHolder>>> = Lazy::new(|| {
|
||||
RwLock::new(HashMap::new())
|
||||
});
|
||||
|
||||
pub fn add_action(action: ActionItem) {
|
||||
pub fn add_hook(action: HookItem) {
|
||||
let mut hmap = ACTIONS.write().unwrap();
|
||||
let action_handler = action.handler();
|
||||
if let Some(actions) = hmap.get_mut(action_handler) {
|
||||
actions.add(action);
|
||||
} 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) {
|
||||
actions.iter_map(f)
|
||||
}
|
||||
17
pagetop/src/core/hook/definition.rs
Normal file
17
pagetop/src/core/hook/definition.rs
Normal 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()
|
||||
}
|
||||
|
|
@ -1,36 +1,36 @@
|
|||
use super::ActionTrait;
|
||||
use super::HookTrait;
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub type ActionItem = Box<dyn ActionTrait>;
|
||||
pub type HookItem = Box<dyn HookTrait>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! action_item {
|
||||
macro_rules! hook_item {
|
||||
( $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 {
|
||||
ActionsHolder(Arc::new(RwLock::new(Vec::new())))
|
||||
HooksHolder(Arc::new(RwLock::new(Vec::new())))
|
||||
}
|
||||
|
||||
pub fn new_with(action: ActionItem) -> Self {
|
||||
let mut container = ActionsHolder::new();
|
||||
pub fn new_with(action: HookItem) -> Self {
|
||||
let mut container = HooksHolder::new();
|
||||
container.add(action);
|
||||
container
|
||||
}
|
||||
|
||||
pub fn add(&mut self, action: ActionItem) {
|
||||
pub fn add(&mut self, action: HookItem) {
|
||||
let mut actions = self.0.write().unwrap();
|
||||
actions.push(action);
|
||||
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();
|
||||
}
|
||||
}
|
||||
14
pagetop/src/core/hook/mod.rs
Normal file
14
pagetop/src/core/hook/mod.rs
Normal 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;
|
||||
|
|
@ -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 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.
|
||||
|
|
@ -1,26 +1,38 @@
|
|||
use crate::{Lazy, app, run_now, trace};
|
||||
use crate::api::action::add_action;
|
||||
use crate::{Lazy, run_now, trace};
|
||||
use crate::core::app;
|
||||
use crate::core::hook::add_hook;
|
||||
use crate::db::*;
|
||||
use super::ModuleTrait;
|
||||
|
||||
use std::sync::RwLock;
|
||||
|
||||
// Módulos registrados.
|
||||
static MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::new(|| {
|
||||
// Enabled modules.
|
||||
static ENABLED_MODULES: Lazy<RwLock<Vec<&dyn ModuleTrait>>> = Lazy::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();
|
||||
add_to(&mut list, module);
|
||||
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) {
|
||||
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()) {
|
||||
trace::debug!("Including module \"{}\"", module.single_name());
|
||||
trace::debug!("Enabling module \"{}\"", module.single_name());
|
||||
list.push(module);
|
||||
|
||||
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) {
|
||||
for m in MODULES.read().unwrap().iter() {
|
||||
for m in ENABLED_MODULES.read().unwrap().iter() {
|
||||
m.configure_service(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_actions() {
|
||||
for m in MODULES.read().unwrap().iter() {
|
||||
pub fn register_hooks() {
|
||||
for m in ENABLED_MODULES.read().unwrap().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 {
|
||||
fn migrations() -> Vec<MigrationItem> {
|
||||
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
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{app, util};
|
||||
use crate::api::action::ActionItem;
|
||||
use crate::util;
|
||||
use crate::core::app;
|
||||
use crate::core::hook::HookItem;
|
||||
|
||||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
use crate::db::MigrationItem;
|
||||
|
|
@ -28,7 +29,7 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
|
|||
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
|
||||
}
|
||||
|
||||
fn actions(&self) -> Vec<ActionItem> {
|
||||
fn actions(&self) -> Vec<HookItem> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
|
|
@ -6,5 +6,7 @@ pub use definition::{
|
|||
|
||||
pub(crate) mod all;
|
||||
pub use all::{
|
||||
include_module,
|
||||
disable_module,
|
||||
enable_module,
|
||||
enable_modules,
|
||||
};
|
||||
|
|
@ -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 std::sync::RwLock;
|
||||
|
|
@ -10,6 +11,12 @@ 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 {
|
||||
register_theme(t)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_theme(theme: &'static dyn ThemeTrait) {
|
||||
let mut themes = THEMES.write().unwrap();
|
||||
if !themes.iter().any(|t| t.handler() == theme.handler()) {
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{app, concat_string, util};
|
||||
use crate::{concat_string, util};
|
||||
use crate::config::SETTINGS;
|
||||
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::base::component::Chunck;
|
||||
|
||||
|
|
@ -7,5 +7,6 @@ pub use definition::{
|
|||
pub(crate) mod all;
|
||||
pub use all::{
|
||||
register_theme,
|
||||
register_themes,
|
||||
theme_by_single_name,
|
||||
};
|
||||
|
|
@ -18,10 +18,10 @@ pub mod html; // HTML en código.
|
|||
#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))]
|
||||
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 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 util; // Macros y funciones útiles.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub use fluent_templates::fluent_bundle::FluentValue;
|
|||
macro_rules! localize {
|
||||
( $dir_locales:literal $(, $core_locales:literal)? ) => {
|
||||
use $crate::locale::*;
|
||||
use $crate::app::locale::LANGID;
|
||||
use $crate::core::app::locale::LANGID;
|
||||
|
||||
static_locale! {
|
||||
static LOCALES = {
|
||||
|
|
|
|||
|
|
@ -20,17 +20,20 @@ pub use crate::{
|
|||
migration_item,
|
||||
};
|
||||
|
||||
pub use crate::{action_item, api::{
|
||||
action::*,
|
||||
pub use crate::{hook_item, core::{
|
||||
// app::*,
|
||||
component::*,
|
||||
hook::*,
|
||||
module::*,
|
||||
theme::*,
|
||||
}};
|
||||
pub use crate::core::app;
|
||||
pub use crate::core::app::application::Application;
|
||||
|
||||
pub use crate::response::page::*;
|
||||
|
||||
pub use crate::app;
|
||||
pub use crate::app::application::{Application, UsingBootstrap};
|
||||
//pub use crate::app;
|
||||
//pub use crate::app::application::{Application, UsingBootstrap};
|
||||
|
||||
pub use crate::base::component::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
48
pagetop/src/response/page/hook.rs
Normal file
48
pagetop/src/response/page/hook.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
mod action;
|
||||
pub use action::{
|
||||
BEFORE_RENDER_PAGE_ACTION,
|
||||
ActionBeforeRenderPage,
|
||||
mod hook;
|
||||
pub use hook::{
|
||||
BEFORE_RENDER_PAGE_HOOK,
|
||||
BeforeRenderPageHook,
|
||||
};
|
||||
|
||||
mod page;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use crate::{Lazy, app, trace};
|
||||
use crate::{Lazy, trace};
|
||||
use crate::config::SETTINGS;
|
||||
use crate::html::*;
|
||||
use crate::api::action::{action_ref, run_actions};
|
||||
use crate::api::component::*;
|
||||
use super::{BEFORE_RENDER_PAGE_ACTION, ActionBeforeRenderPage};
|
||||
use crate::core::app;
|
||||
use crate::core::hook::{hook_ref, run_hooks};
|
||||
use crate::core::component::*;
|
||||
use super::{BEFORE_RENDER_PAGE_HOOK, BeforeRenderPageHook};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -151,9 +152,9 @@ impl<'a> Page<'a> {
|
|||
|
||||
pub fn render(&mut self) -> app::Result<Markup> {
|
||||
// Acciones de los módulos antes de renderizar la página.
|
||||
run_actions(
|
||||
BEFORE_RENDER_PAGE_ACTION,
|
||||
|a| action_ref::<ActionBeforeRenderPage>(&**a).run(self)
|
||||
run_hooks(
|
||||
BEFORE_RENDER_PAGE_HOOK,
|
||||
|a| hook_ref::<BeforeRenderPageHook>(&**a).run(self)
|
||||
);
|
||||
|
||||
// Acciones del tema antes de renderizar la página.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue