Añade hook previo antes de renderizar componentes
This commit is contained in:
parent
166f209dab
commit
616d7ee207
16 changed files with 145 additions and 75 deletions
|
|
@ -27,6 +27,7 @@ doc-comment = "0.3.3"
|
|||
figlet-rs = "0.1.3"
|
||||
futures = "0.3.21"
|
||||
once_cell = "1.12.0"
|
||||
paste = "1.0.7"
|
||||
substring = "1.4.5"
|
||||
term_size = "0.3.2"
|
||||
url = "2.2.2"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ use crate::prelude::*;
|
|||
|
||||
pub const COMPONENT_BLOCK: &str = "pagetop::component::block";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_BLOCK = "pagetop::action::before_render_block",
|
||||
Block
|
||||
);
|
||||
|
||||
pub struct Block {
|
||||
weight : isize,
|
||||
renderable: Renderable,
|
||||
|
|
@ -37,6 +42,10 @@ impl ComponentTrait for Block {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
let id = context.required_id::<Block>(self.id());
|
||||
html! {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ use crate::prelude::*;
|
|||
|
||||
pub const COMPONENT_CONTAINER: &str = "pagetop::component::container";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_CONTAINER = "pagetop::action::before_render_container",
|
||||
Container
|
||||
);
|
||||
|
||||
pub enum ContainerType { Header, Footer, Main, Section, Wrapper }
|
||||
|
||||
pub struct Container {
|
||||
|
|
@ -41,6 +46,10 @@ impl ComponentTrait for Container {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
match self.container_type() {
|
||||
ContainerType::Header => html! {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ use crate::prelude::*;
|
|||
|
||||
pub const COMPONENT_FORM: &str = "pagetop::component::form";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_FORM = "pagetop::action::before_render_form",
|
||||
Form
|
||||
);
|
||||
|
||||
pub enum FormMethod {Get, Post}
|
||||
|
||||
pub struct Form {
|
||||
|
|
@ -43,6 +48,10 @@ impl ComponentTrait for Form {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
let method = match self.method() {
|
||||
FormMethod::Get => None,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ use crate::prelude::*;
|
|||
|
||||
pub const COMPONENT_COLUMN: &str = "pagetop::component::grid::column";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_COLUMN = "pagetop::action::before_render_column",
|
||||
Column
|
||||
);
|
||||
|
||||
const SIZE_DEFAULT: &str = "col-md";
|
||||
const SIZE_1_OF_12: &str = "col-md-1";
|
||||
const SIZE_2_OF_12: &str = "col-md-2";
|
||||
|
|
@ -66,6 +71,10 @@ impl ComponentTrait for Column {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
html! {
|
||||
div id=[self.id().get()] class=[self.classes().get()] {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ use crate::prelude::*;
|
|||
|
||||
pub const COMPONENT_ROW: &str = "pagetop::component::grid::row";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_ROW = "pagetop::action::before_render_row",
|
||||
Row
|
||||
);
|
||||
|
||||
pub struct Row {
|
||||
weight : isize,
|
||||
renderable: Renderable,
|
||||
|
|
@ -35,6 +40,10 @@ impl ComponentTrait for Row {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
html! {
|
||||
div id=[self.id().get()] class=[self.classes().get()] {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
pub const COMPONENT_MENU: &str = "pagetop::component::menu";
|
||||
pub const COMPONENT_MENUITEM: &str = "pagetop::component::menu_item";
|
||||
|
||||
pub enum MenuItemType {
|
||||
|
|
@ -173,6 +172,13 @@ impl MenuItem {
|
|||
|
||||
// Menu.
|
||||
|
||||
pub const COMPONENT_MENU: &str = "pagetop::component::menu";
|
||||
|
||||
hook_before_render_component!(
|
||||
HOOK_BEFORE_RENDER_MENU = "pagetop::action::before_render_menu",
|
||||
Menu
|
||||
);
|
||||
|
||||
pub struct Menu {
|
||||
weight : isize,
|
||||
renderable: Renderable,
|
||||
|
|
@ -206,6 +212,10 @@ impl ComponentTrait for Menu {
|
|||
(self.renderable)(context)
|
||||
}
|
||||
|
||||
fn before_render(&mut self, context: &mut InContext) {
|
||||
before_render_inline(self, context);
|
||||
}
|
||||
|
||||
fn default_render(&self, context: &mut InContext) -> Markup {
|
||||
context
|
||||
.alter(InContextOp::StyleSheet(AssetsOp::Add(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,3 @@
|
|||
mod hook;
|
||||
pub use hook::{
|
||||
HOOK_BEFORE_RENDER_COMPONENT,
|
||||
BeforeRenderComponentHook,
|
||||
};
|
||||
|
||||
mod context;
|
||||
pub use context::{InContext, InContextOp};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::util;
|
||||
use crate::html::{Markup, html};
|
||||
use crate::core::hook::{hook_ref, run_hooks};
|
||||
use super::{HOOK_BEFORE_RENDER_COMPONENT, BeforeRenderComponentHook, InContext};
|
||||
use super::InContext;
|
||||
|
||||
pub use std::any::Any as AnyComponent;
|
||||
|
||||
|
|
@ -50,11 +49,8 @@ pub fn component_mut<C: 'static>(component: &mut dyn ComponentTrait) -> &mut C {
|
|||
}
|
||||
|
||||
pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InContext) -> Markup {
|
||||
// Acciones de los módulos antes de renderizar el componente.
|
||||
run_hooks(
|
||||
HOOK_BEFORE_RENDER_COMPONENT,
|
||||
|hook| hook_ref::<BeforeRenderComponentHook>(&**hook).run(component, context)
|
||||
);
|
||||
// Acciones del componente antes de renderizar.
|
||||
component.before_render(context);
|
||||
|
||||
// Acciones del tema antes de renderizar el componente.
|
||||
context.theme().before_render_component(component, context);
|
||||
|
|
@ -67,3 +63,68 @@ pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InCont
|
|||
false => html! {}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! hook_before_render_component {
|
||||
( $ACTION_HANDLER:ident = $handler:literal, $Component:ty ) => {
|
||||
paste::paste! {
|
||||
const $ACTION_HANDLER: &str = $handler;
|
||||
|
||||
type Action = fn(&$Component, &mut InContext);
|
||||
|
||||
pub struct [< BeforeRender $Component >] {
|
||||
action: Option<Action>,
|
||||
weight: isize,
|
||||
}
|
||||
|
||||
impl HookTrait for [< BeforeRender $Component >] {
|
||||
fn new() -> Self {
|
||||
[< BeforeRender $Component >] {
|
||||
action: None,
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn handler(&self) -> &'static str {
|
||||
$ACTION_HANDLER
|
||||
}
|
||||
|
||||
fn weight(&self) -> isize {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn as_ref_any(&self) -> &dyn AnyHook {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl [< BeforeRender $Component >] {
|
||||
#[allow(dead_code)]
|
||||
pub fn with_hook(mut self, action: Action) -> Self {
|
||||
self.action = Some(action);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn with_weight(mut self, weight: isize) -> Self {
|
||||
self.weight = weight;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn run(&self, component: &mut $Component, context: &mut InContext) {
|
||||
if let Some(action) = self.action {
|
||||
action(component, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn before_render_inline(component: &mut $Component, context: &mut InContext) {
|
||||
run_actions(
|
||||
$ACTION_HANDLER,
|
||||
|action| action_ref::<[< BeforeRender $Component >]>(&**action).run(component, context)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
use crate::core::hook::{HookTrait, AnyHook};
|
||||
use super::{ComponentTrait, InContext};
|
||||
|
||||
pub const HOOK_BEFORE_RENDER_COMPONENT: &str = "pagetop::hook::before_render_component";
|
||||
|
||||
pub struct BeforeRenderComponentHook {
|
||||
hook: Option<fn(&mut dyn ComponentTrait, &mut InContext)>,
|
||||
weight: isize,
|
||||
}
|
||||
|
||||
impl HookTrait for BeforeRenderComponentHook {
|
||||
fn new() -> Self {
|
||||
BeforeRenderComponentHook {
|
||||
hook: None,
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn handler(&self) -> &'static str {
|
||||
HOOK_BEFORE_RENDER_COMPONENT
|
||||
}
|
||||
|
||||
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 InContext)) -> 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, context: &mut InContext) {
|
||||
if let Some(hook) = self.hook {
|
||||
hook(component, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
mod definition;
|
||||
pub use definition::{
|
||||
HookTrait,
|
||||
AnyHook,
|
||||
hook_ref,
|
||||
HookTrait,
|
||||
action_ref,
|
||||
};
|
||||
|
||||
mod holder;
|
||||
|
|
@ -10,5 +10,5 @@ pub use holder::HookAction;
|
|||
use holder::HooksHolder;
|
||||
|
||||
mod all;
|
||||
pub use all::run_hooks;
|
||||
pub use all::run_actions;
|
||||
pub(crate) use all::add_hook;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pub fn add_hook(hook: HookAction) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run_hooks<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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ pub trait HookTrait: AnyHook + Send + Sync {
|
|||
fn as_ref_any(&self) -> &dyn AnyHook;
|
||||
}
|
||||
|
||||
pub fn hook_ref<A: 'static>(hook: &dyn HookTrait) -> &A {
|
||||
pub fn action_ref<A: 'static>(hook: &dyn HookTrait) -> &A {
|
||||
hook.as_ref_any().downcast_ref::<A>().unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//! Re-exporta recursos comunes.
|
||||
|
||||
// Macros, globals and helpers.
|
||||
// Global macros and helpers.
|
||||
pub use crate::{
|
||||
args,
|
||||
concat_string,
|
||||
|
|
@ -25,12 +25,17 @@ pub use crate::app;
|
|||
pub use crate::app::AppTrait;
|
||||
pub use crate::app::application::Application;
|
||||
|
||||
pub use crate::{hook_action, core::{
|
||||
pub use crate::core::{
|
||||
component::*,
|
||||
hook::*,
|
||||
module::*,
|
||||
theme::*,
|
||||
}};
|
||||
};
|
||||
pub use crate::{
|
||||
hook_action,
|
||||
hook_before_render_component,
|
||||
};
|
||||
|
||||
|
||||
pub use crate::response::page::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{Lazy, app, trace};
|
||||
use crate::config::SETTINGS;
|
||||
use crate::html::*;
|
||||
use crate::core::hook::{hook_ref, run_hooks};
|
||||
use crate::core::hook::{action_ref, run_actions};
|
||||
use crate::core::component::*;
|
||||
use super::{HOOK_BEFORE_RENDER_PAGE, BeforeRenderPageHook};
|
||||
|
||||
|
|
@ -193,9 +193,9 @@ impl Page {
|
|||
|
||||
pub fn render(&mut self) -> app::Result<Markup> {
|
||||
// Acciones de los módulos antes de renderizar la página.
|
||||
run_hooks(
|
||||
run_actions(
|
||||
HOOK_BEFORE_RENDER_PAGE,
|
||||
|hook| hook_ref::<BeforeRenderPageHook>(&**hook).run(self)
|
||||
|hook| action_ref::<BeforeRenderPageHook>(&**hook).run(self)
|
||||
);
|
||||
|
||||
// Acciones del tema antes de renderizar la página.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ use super::Page;
|
|||
|
||||
pub const HOOK_BEFORE_RENDER_PAGE: &str = "pagetop::hook::before_render_page";
|
||||
|
||||
type Hook = fn(&mut Page);
|
||||
|
||||
pub struct BeforeRenderPageHook {
|
||||
hook: Option<fn(&mut Page)>,
|
||||
hook: Option<Hook>,
|
||||
weight: isize,
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +32,7 @@ impl HookTrait for BeforeRenderPageHook {
|
|||
}
|
||||
|
||||
impl BeforeRenderPageHook {
|
||||
pub fn with_hook(mut self, hook: fn(&mut Page)) -> Self {
|
||||
pub fn with_hook(mut self, hook: Hook) -> Self {
|
||||
self.hook = Some(hook);
|
||||
self
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue