Añade elección de tema específico por página
Característica útil para facilitar que el módulo Admin pueda renderizar sus páginas siempre con el mismo tema, indepedientemente del tema por defecto. También podrá ser decisivo para permitir a los usuarios usar un tema diferente.
This commit is contained in:
parent
edf5ddf81b
commit
3764f707da
11 changed files with 127 additions and 86 deletions
|
|
@ -32,6 +32,9 @@ pub async fn summary() -> server::Result<Markup> {
|
|||
.add(MenuItem::label("Opción 4"));
|
||||
|
||||
Page::prepare()
|
||||
|
||||
.using_theme(&bootsier::BootsierTheme)
|
||||
|
||||
.with_title("Admin")
|
||||
|
||||
.add_to("top-menu", top_menu)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,69 @@
|
|||
use crate::core::{server, state};
|
||||
use crate::Lazy;
|
||||
use crate::config::SETTINGS;
|
||||
use crate::core::theme::Theme;
|
||||
use crate::core::module::Module;
|
||||
use crate::core::response::page::PageContainer;
|
||||
use crate::core::server;
|
||||
use crate::base;
|
||||
|
||||
use std::sync::RwLock;
|
||||
use std::collections::HashMap;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Temas registrados y tema por defecto.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| {
|
||||
RwLock::new(vec![
|
||||
&base::theme::aliner::AlinerTheme,
|
||||
&base::theme::minimal::MinimalTheme,
|
||||
&base::theme::bootsier::BootsierTheme,
|
||||
])
|
||||
});
|
||||
|
||||
pub static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| {
|
||||
for t in THEMES.read().unwrap().iter() {
|
||||
if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() {
|
||||
return *t;
|
||||
}
|
||||
}
|
||||
&base::theme::bootsier::BootsierTheme
|
||||
});
|
||||
|
||||
pub fn themes(cfg: &mut server::web::ServiceConfig) {
|
||||
cfg.service(actix_web_static_files::ResourceFiles::new(
|
||||
"/theme",
|
||||
assets()
|
||||
));
|
||||
|
||||
for t in state::THEMES.read().unwrap().iter() {
|
||||
for t in THEMES.read().unwrap().iter() {
|
||||
t.configure_theme(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Módulos registrados.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
|
||||
RwLock::new(vec![
|
||||
&base::module::admin::AdminModule,
|
||||
&base::module::user::UserModule,
|
||||
])
|
||||
});
|
||||
|
||||
pub fn modules(cfg: &mut server::web::ServiceConfig) {
|
||||
for m in state::MODULES.read().unwrap().iter() {
|
||||
for m in MODULES.read().unwrap().iter() {
|
||||
m.configure_module(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Componentes globales.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static COMPONENTS: Lazy<RwLock<HashMap<&str, PageContainer>>> = Lazy::new(
|
||||
|| { RwLock::new(HashMap::new()) }
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
pub use actix_web::dev::Server;
|
||||
|
||||
mod state;
|
||||
pub use state::register_theme;
|
||||
pub use state::register_module;
|
||||
pub use state::add_component_to;
|
||||
|
||||
mod all;
|
||||
|
||||
pub mod theme;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,16 @@
|
|||
use crate::core::all::MODULES;
|
||||
|
||||
mod api;
|
||||
pub use api::Module;
|
||||
|
||||
pub fn register_module(m: &'static (dyn Module + 'static)) {
|
||||
MODULES.write().unwrap().push(m);
|
||||
}
|
||||
|
||||
pub fn find_module(name: &str) -> Option<&'static (dyn Module + 'static)> {
|
||||
let modules = MODULES.write().unwrap();
|
||||
match modules.iter().find(|t| t.name() == name) {
|
||||
Some(module) => Some(*module),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::core::theme::{Markup, PreEscaped, html};
|
||||
use crate::core::all::DEFAULT_THEME;
|
||||
use crate::core::theme::{Markup, PreEscaped, Theme, html};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Favicon.
|
||||
|
|
@ -172,6 +173,7 @@ impl JavaScript {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub struct Assets {
|
||||
theme : &'static dyn Theme,
|
||||
favicon : Option<Favicon>,
|
||||
metadata : Vec<(String, String)>,
|
||||
stylesheets: Vec<StyleSheet>,
|
||||
|
|
@ -183,6 +185,7 @@ pub struct Assets {
|
|||
impl Assets {
|
||||
pub fn new() -> Self {
|
||||
Assets {
|
||||
theme : *DEFAULT_THEME,
|
||||
favicon : None,
|
||||
metadata : Vec::new(),
|
||||
stylesheets: Vec::new(),
|
||||
|
|
@ -192,6 +195,11 @@ impl Assets {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn using_theme(&mut self, theme: &'static dyn Theme) -> &mut Self {
|
||||
self.theme = theme;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self {
|
||||
self.favicon = Some(favicon);
|
||||
self
|
||||
|
|
@ -238,6 +246,14 @@ impl Assets {
|
|||
self
|
||||
}
|
||||
|
||||
/// Assets GETTERS.
|
||||
|
||||
pub fn theme(&mut self) -> &'static dyn Theme {
|
||||
self.theme
|
||||
}
|
||||
|
||||
/// Assets RENDER.
|
||||
|
||||
pub fn render(&mut self) -> Markup {
|
||||
let ordered_css = &mut self.stylesheets;
|
||||
ordered_css.sort_by_key(|o| o.weight);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use crate::core::all::COMPONENTS;
|
||||
|
||||
pub mod assets;
|
||||
pub use assets::Assets as PageAssets;
|
||||
|
||||
|
|
@ -10,3 +12,12 @@ pub use container::Container as PageContainer;
|
|||
mod page;
|
||||
pub use page::Page;
|
||||
pub use page::render_component;
|
||||
|
||||
pub fn add_component_to(region: &'static str, component: impl PageComponent) {
|
||||
let mut hmap = COMPONENTS.write().unwrap();
|
||||
if let Some(regions) = hmap.get_mut(region) {
|
||||
regions.add(component);
|
||||
} else {
|
||||
hmap.insert(region, PageContainer::new_with(component));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::config::SETTINGS;
|
||||
use crate::core::server;
|
||||
use crate::core::state::{COMPONENTS, THEME};
|
||||
use crate::core::theme::{DOCTYPE, Markup, html};
|
||||
use crate::core::all::COMPONENTS;
|
||||
use crate::core::theme::{DOCTYPE, Markup, Theme, html};
|
||||
use crate::core::response::page::{PageAssets, PageComponent, PageContainer};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
|
@ -132,13 +132,13 @@ impl<'a> Page<'a> {
|
|||
|
||||
pub fn render(&mut self) -> server::Result<Markup> {
|
||||
// Acciones del tema antes de renderizar la página.
|
||||
THEME.before_render_page(self);
|
||||
self.assets.theme().before_render_page(self);
|
||||
|
||||
// Primero, renderizar el cuerpo.
|
||||
let body = THEME.render_page_body(self);
|
||||
let body = self.assets.theme().render_page_body(self);
|
||||
|
||||
// Luego, renderizar la cabecera.
|
||||
let head = THEME.render_page_head(self);
|
||||
let head = self.assets.theme().render_page_head(self);
|
||||
|
||||
// Finalmente, renderizar la página.
|
||||
return Ok(html! {
|
||||
|
|
@ -156,6 +156,13 @@ impl<'a> Page<'a> {
|
|||
None => html! {}
|
||||
}
|
||||
}
|
||||
|
||||
// Page EXTRAS.
|
||||
|
||||
pub fn using_theme(&mut self, theme: &'static dyn Theme) -> &mut Self {
|
||||
self.assets.using_theme(theme);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_component(
|
||||
|
|
@ -163,7 +170,7 @@ pub fn render_component(
|
|||
assets: &mut PageAssets
|
||||
) -> Markup {
|
||||
match component.is_renderable() {
|
||||
true => match THEME.render_component(component, assets) {
|
||||
true => match assets.theme().render_component(component, assets) {
|
||||
Some(markup) => markup,
|
||||
None => component.default_render(assets)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{base, trace};
|
||||
use crate::config::SETTINGS;
|
||||
use crate::core::{Server, all, register_module, server};
|
||||
use crate::core::{Server, all, server};
|
||||
use crate::core::module::register_module;
|
||||
|
||||
use tracing_log::LogTracer;
|
||||
use tracing_subscriber::{EnvFilter, Registry};
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
use crate::Lazy;
|
||||
use crate::config::SETTINGS;
|
||||
use crate::core::theme::Theme;
|
||||
use crate::core::module::Module;
|
||||
use crate::core::response::page::{PageComponent, PageContainer};
|
||||
use crate::base;
|
||||
|
||||
use std::sync::RwLock;
|
||||
use std::collections::HashMap;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Temas registrados.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| {
|
||||
RwLock::new(vec![
|
||||
&base::theme::aliner::AlinerTheme,
|
||||
&base::theme::minimal::MinimalTheme,
|
||||
&base::theme::bootsier::BootsierTheme,
|
||||
])
|
||||
});
|
||||
|
||||
pub static THEME: Lazy<&dyn Theme> = Lazy::new(|| {
|
||||
for t in THEMES.read().unwrap().iter() {
|
||||
if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() {
|
||||
return *t;
|
||||
}
|
||||
}
|
||||
&base::theme::bootsier::BootsierTheme
|
||||
});
|
||||
|
||||
pub fn register_theme(t: &'static (dyn Theme + 'static)) {
|
||||
THEMES.write().unwrap().push(t);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Módulos registrados.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
|
||||
RwLock::new(vec![
|
||||
&base::module::admin::AdminModule,
|
||||
&base::module::user::UserModule,
|
||||
])
|
||||
});
|
||||
|
||||
pub fn register_module(m: &'static (dyn Module + 'static)) {
|
||||
MODULES.write().unwrap().push(m);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Componentes globales.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub static COMPONENTS: Lazy<RwLock<HashMap<&str, PageContainer>>> = Lazy::new(
|
||||
|| { RwLock::new(HashMap::new()) }
|
||||
);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn add_component_to(region: &'static str, component: impl PageComponent) {
|
||||
let mut hmap = COMPONENTS.write().unwrap();
|
||||
if let Some(regions) = hmap.get_mut(region) {
|
||||
regions.add(component);
|
||||
} else {
|
||||
hmap.insert(region, PageContainer::new_with(component));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,18 @@
|
|||
use crate::core::all::THEMES;
|
||||
|
||||
pub use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||
|
||||
mod api;
|
||||
pub use api::Theme;
|
||||
|
||||
pub fn register_theme(t: &'static (dyn Theme + 'static)) {
|
||||
THEMES.write().unwrap().push(t);
|
||||
}
|
||||
|
||||
pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> {
|
||||
let themes = THEMES.write().unwrap();
|
||||
match themes.iter().find(|t| t.name() == name) {
|
||||
Some(theme) => Some(*theme),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ pub use crate::core::response::page::*;
|
|||
pub use crate::core::response::page::assets::*;
|
||||
|
||||
pub use crate::core::server;
|
||||
pub use crate::core::register_theme;
|
||||
pub use crate::core::register_module;
|
||||
pub use crate::core::add_component_to;
|
||||
|
||||
pub use crate::base::theme::*;
|
||||
pub use crate::base::component::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue