Modifica gestión de páginas para normalizar código
This commit is contained in:
parent
9e65f89d2d
commit
db3efa9ef9
7 changed files with 128 additions and 92 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::Lazy;
|
use crate::Lazy;
|
||||||
use crate::config::SETTINGS;
|
|
||||||
use crate::core::theme::Theme;
|
use crate::core::theme::Theme;
|
||||||
use crate::core::module::Module;
|
use crate::core::module::Module;
|
||||||
use crate::core::response::page::PageContainer;
|
use crate::core::response::page::PageContainer;
|
||||||
|
|
@ -23,15 +22,6 @@ pub static THEMES: Lazy<RwLock<Vec<&dyn Theme>>> = Lazy::new(|| {
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|
||||||
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) {
|
pub fn themes(cfg: &mut server::web::ServiceConfig) {
|
||||||
cfg.service(actix_web_static_files::ResourceFiles::new(
|
cfg.service(actix_web_static_files::ResourceFiles::new(
|
||||||
"/theme",
|
"/theme",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
use crate::core::all::DEFAULT_THEME;
|
use crate::{Lazy, base};
|
||||||
|
use crate::config::SETTINGS;
|
||||||
|
use crate::core::all;
|
||||||
use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html};
|
use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html};
|
||||||
|
|
||||||
|
pub static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| {
|
||||||
|
for t in all::THEMES.read().unwrap().iter() {
|
||||||
|
if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() {
|
||||||
|
return *t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&base::theme::bootsier::BootsierTheme
|
||||||
|
});
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Favicon.
|
// Favicon.
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ pub trait Component: Downcast + Send + Sync {
|
||||||
|
|
||||||
fn prepare() -> Self where Self: Sized;
|
fn prepare() -> Self where Self: Sized;
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &'static str {
|
||||||
let name = type_name::<Self>();
|
let name = type_name::<Self>();
|
||||||
match name.rfind("::") {
|
match name.rfind("::") {
|
||||||
Some(position) => &name[(position + 2)..],
|
Some(position) => &name[(position + 2)..],
|
||||||
|
|
@ -17,12 +17,12 @@ pub trait Component: Downcast + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn qualified_name(&self) -> &str {
|
fn fullname(&self) -> String {
|
||||||
type_name::<Self>()
|
type_name::<Self>().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> String {
|
||||||
""
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_renderable(&self) -> bool {
|
fn is_renderable(&self) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use crate::core::all::COMPONENTS;
|
|
||||||
|
|
||||||
pub mod assets;
|
pub mod assets;
|
||||||
pub use assets::Assets as PageAssets;
|
pub use assets::Assets as PageAssets;
|
||||||
|
|
||||||
|
|
@ -12,12 +10,5 @@ pub use container::Container as PageContainer;
|
||||||
mod page;
|
mod page;
|
||||||
pub use page::Page;
|
pub use page::Page;
|
||||||
pub use page::render_component;
|
pub use page::render_component;
|
||||||
|
pub use page::add_component_to;
|
||||||
|
|
||||||
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,63 +1,96 @@
|
||||||
|
use crate::{Lazy, trace, util};
|
||||||
use crate::config::SETTINGS;
|
use crate::config::SETTINGS;
|
||||||
use crate::core::server;
|
use crate::core::{all, server};
|
||||||
use crate::core::all::COMPONENTS;
|
|
||||||
use crate::core::theme::{DOCTYPE, Markup, html};
|
use crate::core::theme::{DOCTYPE, Markup, html};
|
||||||
use crate::core::response::page::{PageAssets, PageComponent, PageContainer};
|
use crate::core::response::page::{PageAssets, PageComponent, PageContainer};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub enum TextDirection { LeftToRight, RightToLeft, Auto }
|
pub static DEFAULT_LANGUAGE: Lazy<Option<String>> = Lazy::new(|| {
|
||||||
|
let language = SETTINGS.app.language[..2].to_lowercase();
|
||||||
|
if !language.is_empty() {
|
||||||
|
Some(language)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static DEFAULT_DIRECTION: Lazy<Option<String>> = Lazy::new(|| {
|
||||||
|
let direction = SETTINGS.app.direction.to_lowercase();
|
||||||
|
match direction.as_str() {
|
||||||
|
"auto" => Some("auto".to_string()),
|
||||||
|
"ltr" => Some("ltr".to_string()),
|
||||||
|
"rtl" => Some("rtl".to_string()),
|
||||||
|
"" => None,
|
||||||
|
_ => {
|
||||||
|
trace::warn!(
|
||||||
|
"Text direction \"{}\" not valid. {}.",
|
||||||
|
SETTINGS.app.direction,
|
||||||
|
"Check the settings file"
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pub enum TextDirection { Auto, LeftToRight, RightToLeft }
|
||||||
|
|
||||||
pub struct Page<'a> {
|
pub struct Page<'a> {
|
||||||
language : &'a str,
|
language : Option<String>,
|
||||||
title : &'a str,
|
direction : Option<String>,
|
||||||
direction : &'a str,
|
title : Option<String>,
|
||||||
description : &'a str,
|
description : Option<String>,
|
||||||
body_classes: Cow<'a, str>,
|
|
||||||
assets : PageAssets,
|
assets : PageAssets,
|
||||||
|
body_classes: Cow<'a, str>,
|
||||||
regions : HashMap<&'a str, PageContainer>,
|
regions : HashMap<&'a str, PageContainer>,
|
||||||
template : &'a str,
|
template : Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Page<'a> {
|
impl<'a> Page<'a> {
|
||||||
|
|
||||||
pub fn prepare() -> Self {
|
pub fn prepare() -> Self {
|
||||||
Page {
|
Page {
|
||||||
language : &SETTINGS.app.language[..2],
|
language : match &*DEFAULT_LANGUAGE {
|
||||||
title : &SETTINGS.app.name,
|
Some(language) => Some(language.to_string()),
|
||||||
direction : "ltr",
|
_ => None,
|
||||||
description : "",
|
},
|
||||||
|
direction : match &*DEFAULT_DIRECTION {
|
||||||
|
Some(direction) => Some(direction.to_string()),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
title : None,
|
||||||
|
description : None,
|
||||||
body_classes: "body".into(),
|
body_classes: "body".into(),
|
||||||
assets : PageAssets::new(),
|
assets : PageAssets::new(),
|
||||||
regions : COMPONENTS.read().unwrap().clone(),
|
regions : all::COMPONENTS.read().unwrap().clone(),
|
||||||
template : "default",
|
template : Some("default".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page BUILDER.
|
// Page BUILDER.
|
||||||
|
|
||||||
pub fn with_language(&mut self, language: &'a str) -> &mut Self {
|
pub fn with_language(&mut self, language: &str) -> &mut Self {
|
||||||
self.language = language;
|
self.language = util::optional_value(language);
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_title(&mut self, title: &'a str) -> &mut Self {
|
|
||||||
self.title = title;
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self {
|
pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self {
|
||||||
self.direction = match dir {
|
self.direction = match dir {
|
||||||
TextDirection::LeftToRight => "ltr",
|
TextDirection::Auto => Some("auto".to_string()),
|
||||||
TextDirection::RightToLeft => "rtl",
|
TextDirection::LeftToRight => Some("ltr".to_string()),
|
||||||
_ => "auto"
|
TextDirection::RightToLeft => Some("rtl".to_string()),
|
||||||
};
|
};
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_description(&mut self, description: &'a str) -> &mut Self {
|
pub fn with_title(&mut self, title: &str) -> &mut Self {
|
||||||
self.description = description;
|
self.title = util::optional_value(title);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_description(&mut self, description: &str) -> &mut Self {
|
||||||
|
self.description = util::optional_value(description);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,31 +119,27 @@ impl<'a> Page<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn using_template(&mut self, template: &'a str) -> &mut Self {
|
pub fn using_template(&mut self, template: &str) -> &mut Self {
|
||||||
self.template = template;
|
self.template = util::optional_value(template);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page GETTERS.
|
// Page GETTERS.
|
||||||
|
|
||||||
pub fn language(&self) -> &str {
|
pub fn language(&self) -> &str {
|
||||||
self.language
|
util::assigned_value(&self.language)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn direction(&self) -> &str {
|
||||||
|
util::assigned_value(&self.direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title(&self) -> &str {
|
pub fn title(&self) -> &str {
|
||||||
self.title
|
util::assigned_value(&self.title)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn direction(&self) -> TextDirection {
|
|
||||||
match self.direction {
|
|
||||||
"ltr" => TextDirection::LeftToRight,
|
|
||||||
"rtl" => TextDirection::RightToLeft,
|
|
||||||
_ => TextDirection::Auto
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn description(&self) -> &str {
|
pub fn description(&self) -> &str {
|
||||||
self.description
|
util::assigned_value(&self.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn body_classes(&self) -> &str {
|
pub fn body_classes(&self) -> &str {
|
||||||
|
|
@ -125,7 +154,7 @@ impl<'a> Page<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn template(&self) -> &str {
|
pub fn template(&self) -> &str {
|
||||||
self.template
|
util::assigned_value(&self.template)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page RENDER.
|
// Page RENDER.
|
||||||
|
|
@ -143,7 +172,7 @@ impl<'a> Page<'a> {
|
||||||
// Finalmente, renderizar la página.
|
// Finalmente, renderizar la página.
|
||||||
return Ok(html! {
|
return Ok(html! {
|
||||||
(DOCTYPE)
|
(DOCTYPE)
|
||||||
html lang=(self.language) dir=(self.direction) {
|
html lang=[&self.language] dir=[&self.direction] {
|
||||||
(head)
|
(head)
|
||||||
(body)
|
(body)
|
||||||
}
|
}
|
||||||
|
|
@ -177,3 +206,12 @@ pub fn render_component(
|
||||||
false => html! {}
|
false => html! {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_component_to(region: &'static str, component: impl PageComponent) {
|
||||||
|
let mut hmap = all::COMPONENTS.write().unwrap();
|
||||||
|
if let Some(regions) = hmap.get_mut(region) {
|
||||||
|
regions.add(component);
|
||||||
|
} else {
|
||||||
|
hmap.insert(region, PageContainer::new_with(component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
use crate::core::server;
|
use crate::config::SETTINGS;
|
||||||
|
use crate::core::{all, server};
|
||||||
use crate::core::theme::{Markup, html};
|
use crate::core::theme::{Markup, html};
|
||||||
use crate::core::response::page::{Page, PageAssets, PageComponent};
|
use crate::core::response::page::{Page, PageAssets, PageComponent};
|
||||||
use crate::base::component::Chunck;
|
use crate::base::component::Chunck;
|
||||||
|
|
||||||
/// Los temas deben implementar este "trait".
|
/// Los temas deben implementar este "trait".
|
||||||
pub trait Theme: Send + Sync {
|
pub trait Theme: Send + Sync {
|
||||||
fn id(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
||||||
fn name(&self) -> String;
|
fn fullname(&self) -> String;
|
||||||
|
|
||||||
fn description(&self) -> String {
|
fn description(&self) -> String {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
|
|
@ -22,19 +23,26 @@ pub trait Theme: Send + Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_page_head(&self, page: &mut Page) -> Markup {
|
fn render_page_head(&self, page: &mut Page) -> Markup {
|
||||||
let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no";
|
let title = page.title();
|
||||||
|
let title = if title.is_empty() {
|
||||||
|
SETTINGS.app.name.to_string()
|
||||||
|
} else {
|
||||||
|
[SETTINGS.app.name.to_string(), title.to_string()].join(" | ")
|
||||||
|
};
|
||||||
let description = page.description();
|
let description = page.description();
|
||||||
|
let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no";
|
||||||
html! {
|
html! {
|
||||||
head {
|
head {
|
||||||
meta charset="utf-8";
|
meta charset="utf-8";
|
||||||
|
|
||||||
meta http-equiv="X-UA-Compatible" content="IE=edge";
|
title { (title) }
|
||||||
meta name="viewport" content=(viewport);
|
|
||||||
@if !description.is_empty() {
|
@if !description.is_empty() {
|
||||||
meta name="description" content=(description);
|
meta name="description" content=(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
title { (page.title()) }
|
meta http-equiv="X-UA-Compatible" content="IE=edge";
|
||||||
|
meta name="viewport" content=(viewport);
|
||||||
|
|
||||||
(page.assets().render())
|
(page.assets().render())
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +80,8 @@ pub trait Theme: Send + Sync {
|
||||||
/*
|
/*
|
||||||
Cómo usarlo:
|
Cómo usarlo:
|
||||||
|
|
||||||
match component.type_name() {
|
match component.handle() {
|
||||||
"Block" => {
|
"block" => {
|
||||||
let block = component.downcast_mut::<Block>().unwrap();
|
let block = component.downcast_mut::<Block>().unwrap();
|
||||||
match block.template() {
|
match block.template() {
|
||||||
"default" => Some(block_default(block)),
|
"default" => Some(block_default(block)),
|
||||||
|
|
@ -96,3 +104,15 @@ pub trait Theme: Send + Sync {
|
||||||
.render()
|
.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn register_theme(t: &'static (dyn Theme + 'static)) {
|
||||||
|
all::THEMES.write().unwrap().push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> {
|
||||||
|
let themes = all::THEMES.write().unwrap();
|
||||||
|
match themes.iter().find(|t| t.name() == name) {
|
||||||
|
Some(theme) => Some(*theme),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,4 @@
|
||||||
use crate::core::all::THEMES;
|
|
||||||
|
|
||||||
pub use maud::{DOCTYPE, Markup, PreEscaped, html};
|
pub use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
pub use api::Theme;
|
pub use api::{Theme, find_theme, register_theme};
|
||||||
|
|
||||||
pub fn register_theme(t: &'static (dyn Theme + 'static)) {
|
|
||||||
THEMES.write().unwrap().push(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_theme(id: &str) -> Option<&'static (dyn Theme + 'static)> {
|
|
||||||
let themes = THEMES.write().unwrap();
|
|
||||||
match themes.iter().find(|t| t.id() == id) {
|
|
||||||
Some(theme) => Some(*theme),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue