Asignación de componentes predefinidos por tema

This commit is contained in:
Manuel Cillero 2023-06-07 22:52:20 +02:00
parent a2add5b09c
commit d8812433f1
7 changed files with 83 additions and 41 deletions

View file

@ -12,9 +12,5 @@ pub use one::OneComponent;
mod bundle;
pub use bundle::ComponentsBundle;
mod all;
pub use all::add_component_to;
pub(crate) use all::common_components;
mod renderable;
pub use renderable::{IsRenderable, Renderable};

View file

@ -1,21 +0,0 @@
use crate::core::component::{ComponentTrait, ComponentsBundle};
use crate::LazyStatic;
use std::collections::HashMap;
use std::sync::RwLock;
static COMPONENTS: LazyStatic<RwLock<HashMap<&str, ComponentsBundle>>> =
LazyStatic::new(|| RwLock::new(HashMap::new()));
pub fn add_component_to(region: &'static str, component: impl ComponentTrait) {
let mut hmap = COMPONENTS.write().unwrap();
if let Some(regions) = hmap.get_mut(region) {
regions.add(component);
} else {
hmap.insert(region, ComponentsBundle::new_with(component));
}
}
pub fn common_components() -> HashMap<&'static str, ComponentsBundle> {
COMPONENTS.read().unwrap().clone()
}

View file

@ -17,6 +17,20 @@ impl ComponentsBundle {
bundle
}
pub(crate) fn merge(one: Option<&ComponentsBundle>, other: Option<&ComponentsBundle>) -> Self {
if let Some(one) = one {
let mut components = one.0.clone();
if let Some(other) = other {
components.append(&mut other.0.clone());
}
ComponentsBundle(components)
} else if let Some(other) = other {
ComponentsBundle(other.0.clone())
} else {
ComponentsBundle::default()
}
}
pub fn add(&mut self, component: impl ComponentTrait) {
self.0.push(Arc::new(RwLock::new(component)));
}

View file

@ -1,4 +1,8 @@
mod definition;
pub use definition::{ThemeStaticRef, ThemeTrait};
mod regions;
pub use regions::add_component_to;
pub(crate) use regions::ComponentsRegions;
pub(crate) mod all;

View file

@ -0,0 +1,46 @@
use crate::core::component::{ComponentTrait, ComponentsBundle};
use crate::LazyStatic;
use std::collections::HashMap;
use std::sync::RwLock;
static THEME_REGIONS: LazyStatic<RwLock<HashMap<&'static str, ComponentsRegions>>> =
LazyStatic::new(|| RwLock::new(HashMap::new()));
#[derive(Default)]
pub struct ComponentsRegions(HashMap<&'static str, ComponentsBundle>);
impl ComponentsRegions {
pub fn new() -> Self {
ComponentsRegions::default()
}
pub fn add_to(&mut self, region: &'static str, component: impl ComponentTrait) {
if let Some(region) = self.0.get_mut(region) {
region.add(component);
} else {
self.0.insert(region, ComponentsBundle::new_with(component));
}
}
pub fn get_extended_bundle(&self, theme: &str, region: &str) -> ComponentsBundle {
if let Some(hm_theme) = THEME_REGIONS.read().unwrap().get(theme) {
ComponentsBundle::merge(self.0.get(region), hm_theme.0.get(region))
} else {
ComponentsBundle::merge(self.0.get(region), None)
}
}
}
pub fn add_component_to(theme: &'static str, region: &'static str, component: impl ComponentTrait) {
let mut hm = THEME_REGIONS.write().unwrap();
if let Some(hm_theme) = hm.get_mut(theme) {
hm_theme.add_to(region, component);
} else {
hm.insert(theme, {
let mut regions = ComponentsRegions::new();
regions.add_to(region, component);
regions
});
}
}

View file

@ -228,6 +228,12 @@ impl<T: AsRef<str>> Render for PreEscaped<T> {
/// The `html!` macro expands to an expression of this type.
pub type Markup = PreEscaped<String>;
impl Markup {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl<T: AsRef<str> + Into<String>> PreEscaped<T> {
/// Converts the inner value to a string.
pub fn into_string(self) -> String {

View file

@ -1,8 +1,7 @@
use crate::base::component::L10n;
use crate::core::action::{action_ref, run_actions};
use crate::core::component::{
common_components, ComponentTrait, ComponentsBundle, ContextOp, OneComponent, RenderContext,
};
use crate::core::component::{ComponentTrait, ContextOp, OneComponent, RenderContext};
use crate::core::theme::ComponentsRegions;
use crate::html::{html, Classes, ClassesOp, Favicon, Markup, DOCTYPE};
use crate::locale::{langid_for, LanguageIdentifier};
use crate::response::fatal_error::FatalError;
@ -12,8 +11,6 @@ use crate::{fn_builder, server};
use unic_langid::CharacterDirection;
use std::collections::HashMap;
type PageTitle = OneComponent<L10n>;
type PageDescription = OneComponent<L10n>;
@ -26,7 +23,7 @@ pub struct Page {
favicon : Option<Favicon>,
context : RenderContext,
body_classes: Classes,
regions : HashMap<&'static str, ComponentsBundle>,
regions : ComponentsRegions,
template : String,
}
@ -41,7 +38,7 @@ impl Default for Page {
favicon : None,
context : RenderContext::new(),
body_classes: Classes::new().with_value(ClassesOp::SetDefault, "body"),
regions : common_components(),
regions : ComponentsRegions::new(),
template : "default".to_owned(),
}
}
@ -110,12 +107,7 @@ impl Page {
region: &'static str,
component: impl ComponentTrait,
) -> &mut Self {
if let Some(regions) = self.regions.get_mut(region) {
regions.add(component);
} else {
self.regions
.insert(region, ComponentsBundle::new_with(component));
}
self.regions.add_to(region, component);
self
}
@ -196,9 +188,14 @@ impl Page {
}
pub fn render_region(&mut self, region: &str) -> Option<Markup> {
match self.regions.get_mut(region) {
Some(components) => Some(components.render(&mut self.context)),
None => None,
let render = self
.regions
.get_extended_bundle(self.context.theme().single_name(), region)
.render(self.context());
if render.is_empty() {
None
} else {
Some(render)
}
}
}