⏪ Revierte cambio "themes" por "layouts"
This commit is contained in:
parent
c379b37809
commit
53144eab91
31 changed files with 135 additions and 121 deletions
16
Cargo.toml
16
Cargo.toml
|
|
@ -8,13 +8,13 @@ members = [
|
|||
# PageTop
|
||||
"pagetop",
|
||||
|
||||
# Layouts
|
||||
#"layouts/pagetop-aliner",
|
||||
#"layouts/pagetop-bootsier",
|
||||
|
||||
# Packages
|
||||
"packages/pagetop-seaorm",
|
||||
|
||||
# Themes
|
||||
#"packages/pagetop-aliner",
|
||||
#"packages/pagetop-bootsier",
|
||||
|
||||
# App
|
||||
"drust",
|
||||
]
|
||||
|
|
@ -37,9 +37,9 @@ pagetop-macros = { version = "0.0", path = "helpers/pagetop-macros" }
|
|||
# PageTop
|
||||
pagetop = { version = "0.0", path = "pagetop" }
|
||||
|
||||
# Layouts
|
||||
#pagetop-aliner = { version = "0.0", path = "layouts/pagetop-aliner" }
|
||||
#pagetop-bootsier = { version = "0.0", path = "layouts/pagetop-bootsier" }
|
||||
|
||||
# Packages
|
||||
pagetop-seaorm = { version = "0.0", path = "packages/pagetop-seaorm" }
|
||||
|
||||
# Themes
|
||||
#pagetop-aliner = { version = "0.0", path = "packages/pagetop-aliner" }
|
||||
#pagetop-bootsier = { version = "0.0", path = "packages/pagetop-bootsier" }
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ pueden implementar, extender o adaptar a las necesidades de cada solución web,
|
|||
interceptando su flujo de ejecución.
|
||||
* **Componentes** (*components*). Para encapsular HTML, CSS y JavaScript en unidades funcionales,
|
||||
configurables y bien definidas.
|
||||
* **Diseños** (*layouts*). Permiten a los desarrolladores modificar la apariencia de páginas y
|
||||
componentes sin afectar a su funcionalidad.
|
||||
* **Paquetes** (*packages*). Extienden o personalizan funcionalidades existentes interactuando con
|
||||
las APIs de `PageTop` o de paquetes de terceros.
|
||||
* **Temas** (*themes*). Permiten a los desarrolladores modificar la apariencia de páginas y
|
||||
componentes sin afectar a su funcionalidad.
|
||||
|
||||
|
||||
# ⚡️ Guía rápida
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[app]
|
||||
#layout = "Aliner"
|
||||
#layout = "Bootsier"
|
||||
#theme = "Aliner"
|
||||
#theme = "Bootsier"
|
||||
language = "es-ES"
|
||||
|
||||
[log]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
[app]
|
||||
name = "My App"
|
||||
description = "Developed with the amazing PageTop framework."
|
||||
# Default layout.
|
||||
layout = "Default"
|
||||
# Default theme.
|
||||
theme = "Default"
|
||||
# Default language (localization).
|
||||
language = "en-US"
|
||||
# Default text direction: "ltr", "rtl", or "auto".
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ struct Drust;
|
|||
impl PackageTrait for Drust {
|
||||
fn dependencies(&self) -> Vec<PackageRef> {
|
||||
vec![
|
||||
// Layouts.
|
||||
//&pagetop_bootsier::Bootsier,
|
||||
|
||||
// Packages.
|
||||
//&pagetop_admin::Admin,
|
||||
//&pagetop_user::User,
|
||||
//&pagetop_node::Node,
|
||||
|
||||
// Themes.
|
||||
//&pagetop_bootsier::Bootsier,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ pub mod action;
|
|||
|
||||
pub mod component;
|
||||
|
||||
pub mod layout;
|
||||
|
||||
pub mod package;
|
||||
|
||||
pub mod theme;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ pub type FnActionWithPage = fn(page: &mut Page);
|
|||
|
||||
pub mod component;
|
||||
|
||||
pub mod layout;
|
||||
pub mod theme;
|
||||
|
||||
pub mod page;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent;
|
|||
|
||||
pub struct AfterRender<C: ComponentTrait> {
|
||||
f: FnActionWithComponent<C>,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> ActionTrait for AfterRender<C> {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
self.layout_type_id
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
self.theme_type_id
|
||||
}
|
||||
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for AfterRender<C> {
|
|||
}
|
||||
|
||||
impl<C: ComponentTrait> AfterRender<C> {
|
||||
pub fn new(layout: LayoutRef, f: FnActionWithComponent<C>) -> Self {
|
||||
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
|
||||
AfterRender {
|
||||
f,
|
||||
layout_type_id: Some(layout.type_id()),
|
||||
theme_type_id: Some(theme.type_id()),
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ impl<C: ComponentTrait> AfterRender<C> {
|
|||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
Some(cx.layout().type_id()),
|
||||
Some(cx.theme().type_id()),
|
||||
Some(UniqueId::of::<C>()),
|
||||
None,
|
||||
),
|
||||
|
|
@ -4,20 +4,20 @@ use crate::base::action::FnActionWithPage;
|
|||
|
||||
pub struct AfterRenderBody {
|
||||
f: FnActionWithPage,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
}
|
||||
|
||||
impl ActionTrait for AfterRenderBody {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
self.layout_type_id
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
self.theme_type_id
|
||||
}
|
||||
}
|
||||
|
||||
impl AfterRenderBody {
|
||||
pub fn new(layout: LayoutRef, f: FnActionWithPage) -> Self {
|
||||
pub fn new(theme: ThemeRef, f: FnActionWithPage) -> Self {
|
||||
AfterRenderBody {
|
||||
f,
|
||||
layout_type_id: Some(layout.type_id()),
|
||||
theme_type_id: Some(theme.type_id()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ impl AfterRenderBody {
|
|||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
Some(page.context().layout().type_id()),
|
||||
Some(page.context().theme().type_id()),
|
||||
None,
|
||||
None,
|
||||
),
|
||||
|
|
@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent;
|
|||
|
||||
pub struct BeforeRender<C: ComponentTrait> {
|
||||
f: FnActionWithComponent<C>,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> ActionTrait for BeforeRender<C> {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
self.layout_type_id
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
self.theme_type_id
|
||||
}
|
||||
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for BeforeRender<C> {
|
|||
}
|
||||
|
||||
impl<C: ComponentTrait> BeforeRender<C> {
|
||||
pub fn new(layout: LayoutRef, f: FnActionWithComponent<C>) -> Self {
|
||||
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
|
||||
BeforeRender {
|
||||
f,
|
||||
layout_type_id: Some(layout.type_id()),
|
||||
theme_type_id: Some(theme.type_id()),
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ impl<C: ComponentTrait> BeforeRender<C> {
|
|||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
Some(cx.layout().type_id()),
|
||||
Some(cx.theme().type_id()),
|
||||
Some(UniqueId::of::<C>()),
|
||||
None,
|
||||
),
|
||||
|
|
@ -4,20 +4,20 @@ use crate::base::action::FnActionWithPage;
|
|||
|
||||
pub struct BeforeRenderBody {
|
||||
f: FnActionWithPage,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
}
|
||||
|
||||
impl ActionTrait for BeforeRenderBody {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
self.layout_type_id
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
self.theme_type_id
|
||||
}
|
||||
}
|
||||
|
||||
impl BeforeRenderBody {
|
||||
pub fn new(layout: LayoutRef, f: FnActionWithPage) -> Self {
|
||||
pub fn new(theme: ThemeRef, f: FnActionWithPage) -> Self {
|
||||
BeforeRenderBody {
|
||||
f,
|
||||
layout_type_id: Some(layout.type_id()),
|
||||
theme_type_id: Some(theme.type_id()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ impl BeforeRenderBody {
|
|||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
Some(page.context().layout().type_id()),
|
||||
Some(page.context().theme().type_id()),
|
||||
None,
|
||||
None,
|
||||
),
|
||||
|
|
@ -4,13 +4,13 @@ pub type FnRenderComponent<C> = fn(component: &C, cx: &mut Context) -> Option<Ma
|
|||
|
||||
pub struct RenderComponent<C: ComponentTrait> {
|
||||
f: FnRenderComponent<C>,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> ActionTrait for RenderComponent<C> {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
self.layout_type_id
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
self.theme_type_id
|
||||
}
|
||||
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for RenderComponent<C> {
|
|||
}
|
||||
|
||||
impl<C: ComponentTrait> RenderComponent<C> {
|
||||
pub fn new(layout: LayoutRef, f: FnRenderComponent<C>) -> Self {
|
||||
pub fn new(theme: ThemeRef, f: FnRenderComponent<C>) -> Self {
|
||||
RenderComponent {
|
||||
f,
|
||||
layout_type_id: Some(layout.type_id()),
|
||||
theme_type_id: Some(theme.type_id()),
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ impl<C: ComponentTrait> RenderComponent<C> {
|
|||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
Some(cx.layout().type_id()),
|
||||
Some(cx.theme().type_id()),
|
||||
Some(UniqueId::of::<C>()),
|
||||
None,
|
||||
),
|
||||
|
|
@ -19,7 +19,7 @@ impl PackageTrait for Welcome {
|
|||
async fn homepage(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
|
||||
Page::new(request)
|
||||
.with_title(L10n::l("welcome_page"))
|
||||
.with_assets(AssetsOp::Layout("Basic"))
|
||||
.with_assets(AssetsOp::Theme("Basic"))
|
||||
.with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##"
|
||||
body {
|
||||
background-color: #f3d060;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ use crate::prelude::*;
|
|||
pub struct Basic;
|
||||
|
||||
impl PackageTrait for Basic {
|
||||
fn layout(&self) -> Option<LayoutRef> {
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
Some(&Basic)
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutTrait for Basic {}
|
||||
impl ThemeTrait for Basic {}
|
||||
|
|
@ -80,8 +80,8 @@ pub mod action;
|
|||
// API to build new components.
|
||||
pub mod component;
|
||||
|
||||
// API to add new layouts.
|
||||
pub mod layout;
|
||||
|
||||
// API to add new features with packages.
|
||||
pub mod package;
|
||||
|
||||
// API to add new themes.
|
||||
pub mod theme;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub type ActionBox = Box<dyn ActionTrait>;
|
|||
#[derive(Eq, PartialEq, Hash)]
|
||||
pub struct ActionKey {
|
||||
action_type_id: UniqueId,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
referer_id: Option<String>,
|
||||
}
|
||||
|
|
@ -14,13 +14,13 @@ pub struct ActionKey {
|
|||
impl ActionKey {
|
||||
pub fn new(
|
||||
action_type_id: UniqueId,
|
||||
layout_type_id: Option<UniqueId>,
|
||||
theme_type_id: Option<UniqueId>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
referer_id: Option<String>,
|
||||
) -> Self {
|
||||
ActionKey {
|
||||
action_type_id,
|
||||
layout_type_id,
|
||||
theme_type_id,
|
||||
referer_type_id,
|
||||
referer_id,
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ pub trait ActionBase {
|
|||
}
|
||||
|
||||
pub trait ActionTrait: ActionBase + AnyBase + Send + Sync {
|
||||
fn layout_type_id(&self) -> Option<UniqueId> {
|
||||
fn theme_type_id(&self) -> Option<UniqueId> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ impl<A: ActionTrait> ActionBase for A {
|
|||
fn key(&self) -> ActionKey {
|
||||
ActionKey {
|
||||
action_type_id: self.type_id(),
|
||||
layout_type_id: self.layout_type_id(),
|
||||
theme_type_id: self.theme_type_id(),
|
||||
referer_type_id: self.referer_type_id(),
|
||||
referer_id: self.referer_id(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::core::component::ChildOp;
|
||||
use crate::core::layout::all::{layout_by_short_name, DEFAULT_LAYOUT};
|
||||
use crate::core::layout::{ChildrenInRegions, LayoutRef};
|
||||
use crate::core::theme::all::{theme_by_short_name, DEFAULT_THEME};
|
||||
use crate::core::theme::{ChildrenInRegions, ThemeRef};
|
||||
use crate::html::{html, Markup};
|
||||
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
||||
use crate::locale::{LanguageIdentifier, DEFAULT_LANGID};
|
||||
|
|
@ -17,6 +17,7 @@ use std::fmt;
|
|||
|
||||
pub enum AssetsOp {
|
||||
LangId(&'static LanguageIdentifier),
|
||||
Theme(&'static str),
|
||||
Layout(&'static str),
|
||||
// Favicon.
|
||||
SetFavicon(Option<Favicon>),
|
||||
|
|
@ -50,7 +51,8 @@ impl Error for ErrorParam {}
|
|||
pub struct Context {
|
||||
request : HttpRequest,
|
||||
langid : &'static LanguageIdentifier,
|
||||
layout : LayoutRef,
|
||||
theme : ThemeRef,
|
||||
layout : &'static str,
|
||||
favicon : Option<Favicon>,
|
||||
stylesheet: Assets<StyleSheet>,
|
||||
javascript: Assets<JavaScript>,
|
||||
|
|
@ -65,7 +67,8 @@ impl Context {
|
|||
Context {
|
||||
request,
|
||||
langid : &DEFAULT_LANGID,
|
||||
layout : *DEFAULT_LAYOUT,
|
||||
theme : *DEFAULT_THEME,
|
||||
layout : "default",
|
||||
favicon : None,
|
||||
stylesheet: Assets::<StyleSheet>::new(),
|
||||
javascript: Assets::<JavaScript>::new(),
|
||||
|
|
@ -80,8 +83,11 @@ impl Context {
|
|||
AssetsOp::LangId(langid) => {
|
||||
self.langid = langid;
|
||||
}
|
||||
AssetsOp::Layout(layout_name) => {
|
||||
self.layout = layout_by_short_name(layout_name).unwrap_or(*DEFAULT_LAYOUT);
|
||||
AssetsOp::Theme(theme_name) => {
|
||||
self.theme = theme_by_short_name(theme_name).unwrap_or(*DEFAULT_THEME);
|
||||
}
|
||||
AssetsOp::Layout(layout) => {
|
||||
self.layout = layout;
|
||||
}
|
||||
// Favicon.
|
||||
AssetsOp::SetFavicon(favicon) => {
|
||||
|
|
@ -134,7 +140,11 @@ impl Context {
|
|||
self.langid
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> LayoutRef {
|
||||
pub fn theme(&self) -> ThemeRef {
|
||||
self.theme
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> &str {
|
||||
self.layout
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +173,7 @@ impl Context {
|
|||
|
||||
pub fn render_region(&mut self, region: impl Into<String>) -> Markup {
|
||||
self.regions
|
||||
.all_in_region(self.layout, ®ion.into())
|
||||
.all_in_region(self.theme, ®ion.into())
|
||||
.render(self)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,19 +41,19 @@ impl<C: ComponentTrait> ComponentBase for C {
|
|||
self.setup_before_prepare(cx);
|
||||
|
||||
// Acciones específicas del diseño antes de renderizar el componente.
|
||||
action::layout::BeforeRender::dispatch(self, cx);
|
||||
action::theme::BeforeRender::dispatch(self, cx);
|
||||
|
||||
// Acciones de los paquetes antes de renderizar el componente.
|
||||
action::component::BeforeRender::dispatch(self, cx);
|
||||
|
||||
// Renderiza el componente.
|
||||
let markup = match action::layout::RenderComponent::dispatch(self, cx) {
|
||||
let markup = match action::theme::RenderComponent::dispatch(self, cx) {
|
||||
Some(html) => html,
|
||||
None => self.prepare_component(cx).render(),
|
||||
};
|
||||
|
||||
// Acciones específicas del diseño después de renderizar el componente.
|
||||
action::layout::AfterRender::dispatch(self, cx);
|
||||
action::theme::AfterRender::dispatch(self, cx);
|
||||
|
||||
// Acciones de los paquetes después de renderizar el componente.
|
||||
action::component::AfterRender::dispatch(self, cx);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::core::action::add_action;
|
||||
use crate::core::layout::all::LAYOUTS;
|
||||
use crate::core::package::PackageRef;
|
||||
use crate::core::theme::all::THEMES;
|
||||
use crate::{global, include_files, include_files_service, service, trace};
|
||||
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
|
|
@ -19,8 +19,8 @@ pub fn register_packages(root_package: Option<PackageRef>) {
|
|||
// Initialize a list for packages to be enabled.
|
||||
let mut enabled_list: Vec<PackageRef> = Vec::new();
|
||||
|
||||
// Add default layout to the enabled list.
|
||||
add_to_enabled(&mut enabled_list, &crate::base::layout::Basic);
|
||||
// Add default theme to the enabled list.
|
||||
add_to_enabled(&mut enabled_list, &crate::base::theme::Basic);
|
||||
|
||||
// If a root package is provided, add it to the enabled list.
|
||||
if let Some(package) = root_package {
|
||||
|
|
@ -54,16 +54,16 @@ fn add_to_enabled(list: &mut Vec<PackageRef>, package: PackageRef) {
|
|||
// Add the package itself to the enabled list.
|
||||
list.push(package);
|
||||
|
||||
// Check if the package has an associated layout to register.
|
||||
if let Some(layout) = package.layout() {
|
||||
let mut registered_layouts = LAYOUTS.write().unwrap();
|
||||
// Ensure the layout is not already registered to avoid duplicates.
|
||||
if !registered_layouts
|
||||
// Check if the package has an associated theme to register.
|
||||
if let Some(theme) = package.theme() {
|
||||
let mut registered_themes = THEMES.write().unwrap();
|
||||
// Ensure the theme is not already registered to avoid duplicates.
|
||||
if !registered_themes
|
||||
.iter()
|
||||
.any(|t| t.type_id() == layout.type_id())
|
||||
.any(|t| t.type_id() == theme.type_id())
|
||||
{
|
||||
registered_layouts.push(layout);
|
||||
trace::debug!("Enabling \"{}\" layout", layout.short_name());
|
||||
registered_themes.push(theme);
|
||||
trace::debug!("Enabling \"{}\" theme", theme.short_name());
|
||||
}
|
||||
} else {
|
||||
trace::debug!("Enabling \"{}\" package", package.short_name());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::core::action::ActionBox;
|
||||
use crate::core::layout::LayoutRef;
|
||||
use crate::core::theme::ThemeRef;
|
||||
use crate::core::AnyBase;
|
||||
use crate::locale::L10n;
|
||||
use crate::{actions, service};
|
||||
|
|
@ -16,7 +16,7 @@ pub trait PackageTrait: AnyBase + Send + Sync {
|
|||
L10n::default()
|
||||
}
|
||||
|
||||
fn layout(&self) -> Option<LayoutRef> {
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
mod definition;
|
||||
pub use definition::{LayoutRef, LayoutTrait};
|
||||
pub use definition::{ThemeRef, ThemeTrait};
|
||||
|
||||
mod regions;
|
||||
pub(crate) use regions::ChildrenInRegions;
|
||||
|
|
@ -1,33 +1,31 @@
|
|||
use crate::core::layout::LayoutRef;
|
||||
use crate::core::theme::ThemeRef;
|
||||
use crate::global;
|
||||
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
|
||||
// THEMES ******************************************************************************************
|
||||
|
||||
pub static LAYOUTS: LazyLock<RwLock<Vec<LayoutRef>>> = LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
pub static THEMES: LazyLock<RwLock<Vec<ThemeRef>>> = LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
|
||||
// DEFAULT THEME ***********************************************************************************
|
||||
|
||||
pub static DEFAULT_LAYOUT: LazyLock<LayoutRef> =
|
||||
LazyLock::new(
|
||||
|| match layout_by_short_name(&global::SETTINGS.app.layout) {
|
||||
Some(layout) => layout,
|
||||
None => &crate::base::layout::Basic,
|
||||
},
|
||||
);
|
||||
pub static DEFAULT_THEME: LazyLock<ThemeRef> =
|
||||
LazyLock::new(|| match theme_by_short_name(&global::SETTINGS.app.theme) {
|
||||
Some(theme) => theme,
|
||||
None => &crate::base::theme::Basic,
|
||||
});
|
||||
|
||||
// THEME BY NAME ***********************************************************************************
|
||||
|
||||
pub fn layout_by_short_name(short_name: &str) -> Option<LayoutRef> {
|
||||
pub fn theme_by_short_name(short_name: &str) -> Option<ThemeRef> {
|
||||
let short_name = short_name.to_lowercase();
|
||||
match LAYOUTS
|
||||
match THEMES
|
||||
.read()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|t| t.short_name().to_lowercase() == short_name)
|
||||
{
|
||||
Some(layout) => Some(*layout),
|
||||
Some(theme) => Some(*theme),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@ use crate::html::{html, Markup};
|
|||
use crate::locale::L10n;
|
||||
use crate::response::page::Page;
|
||||
|
||||
pub type LayoutRef = &'static dyn LayoutTrait;
|
||||
pub type ThemeRef = &'static dyn ThemeTrait;
|
||||
|
||||
/// Los diseños deben implementar este "trait".
|
||||
pub trait LayoutTrait: PackageTrait + Send + Sync {
|
||||
pub trait ThemeTrait: PackageTrait + Send + Sync {
|
||||
fn regions(&self) -> Vec<(&'static str, L10n)> {
|
||||
vec![("content", L10n::l("content"))]
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::core::component::{ChildComponent, ChildOp, Children};
|
||||
use crate::core::layout::LayoutRef;
|
||||
use crate::core::theme::ThemeRef;
|
||||
use crate::{fn_builder, AutoDefault, UniqueId};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
|
||||
static LAYOUT_REGIONS: LazyLock<RwLock<HashMap<UniqueId, ChildrenInRegions>>> =
|
||||
static THEME_REGIONS: LazyLock<RwLock<HashMap<UniqueId, ChildrenInRegions>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
static COMMON_REGIONS: LazyLock<RwLock<ChildrenInRegions>> =
|
||||
|
|
@ -33,9 +33,9 @@ impl ChildrenInRegions {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn all_in_region(&self, layout: LayoutRef, region: &str) -> Children {
|
||||
pub fn all_in_region(&self, theme: ThemeRef, region: &str) -> Children {
|
||||
let common = COMMON_REGIONS.read().unwrap();
|
||||
if let Some(r) = LAYOUT_REGIONS.read().unwrap().get(&layout.type_id()) {
|
||||
if let Some(r) = THEME_REGIONS.read().unwrap().get(&theme.type_id()) {
|
||||
Children::merge(&[common.0.get(region), self.0.get(region), r.0.get(region)])
|
||||
} else {
|
||||
Children::merge(&[common.0.get(region), self.0.get(region)])
|
||||
|
|
@ -46,7 +46,7 @@ impl ChildrenInRegions {
|
|||
pub enum InRegion {
|
||||
Content,
|
||||
Named(&'static str),
|
||||
OfLayout(&'static str, LayoutRef),
|
||||
OfTheme(&'static str, ThemeRef),
|
||||
}
|
||||
|
||||
impl InRegion {
|
||||
|
|
@ -64,12 +64,12 @@ impl InRegion {
|
|||
.unwrap()
|
||||
.alter_in_region(name, ChildOp::Add(child));
|
||||
}
|
||||
InRegion::OfLayout(region, layout) => {
|
||||
let mut regions = LAYOUT_REGIONS.write().unwrap();
|
||||
if let Some(r) = regions.get_mut(&layout.type_id()) {
|
||||
InRegion::OfTheme(region, theme) => {
|
||||
let mut regions = THEME_REGIONS.write().unwrap();
|
||||
if let Some(r) = regions.get_mut(&theme.type_id()) {
|
||||
r.alter_in_region(region, ChildOp::Add(child));
|
||||
} else {
|
||||
regions.insert(layout.type_id(), ChildrenInRegions::with(region, child));
|
||||
regions.insert(theme.type_id(), ChildrenInRegions::with(region, child));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ include_config!(SETTINGS: Settings => [
|
|||
// [app]
|
||||
"app.name" => "My App",
|
||||
"app.description" => "Developed with the amazing PageTop framework.",
|
||||
"app.layout" => "",
|
||||
"app.theme" => "",
|
||||
"app.language" => "en-US",
|
||||
"app.text_direction" => "ltr",
|
||||
"app.startup_banner" => "Slant",
|
||||
|
|
@ -50,9 +50,9 @@ pub struct App {
|
|||
/// A brief description of the application.
|
||||
/// Default: *"Developed with the amazing PageTop framework."*.
|
||||
pub description: String,
|
||||
/// Default layout.
|
||||
/// Default theme.
|
||||
/// Default: *""*.
|
||||
pub layout: String,
|
||||
pub theme: String,
|
||||
/// Default language (localization).
|
||||
/// Default: *"en-US"*.
|
||||
pub language: String,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! **OptionClasses** implements a *helper* for dynamically adding class names to components.
|
||||
//!
|
||||
//! This *helper* differentiates between default classes (generally associated with styles provided
|
||||
//! by the layout) and user classes (for customizing components based on application styles).
|
||||
//! by the theme) and user classes (for customizing components based on application styles).
|
||||
//!
|
||||
//! Classes can be added using [Add]. Operations to [Remove], [Replace] or [Toggle] a class, as well
|
||||
//! as [Clear] all classes, are also provided.
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@
|
|||
//! comportamiento interno interceptando su flujo de ejecución.
|
||||
//! * **Componentes** (*components*). Para encapsular HTML, CSS y JavaScript en unidades
|
||||
//! funcionales, configurables y bien definidas.
|
||||
//! * **Diseños** (*layouts*). Permiten a los desarrolladores modificar la apariencia de páginas y
|
||||
//! componentes sin afectar a su funcionalidad.
|
||||
//! * **Paquetes** (*packages*). Extienden o personalizan funcionalidades existentes interactuando
|
||||
//! con las APIs de `PageTop` o de paquetes de terceros.
|
||||
//! * **Temas** (*themes*). Permiten a los desarrolladores modificar la apariencia de páginas y
|
||||
//! componentes sin afectar a su funcionalidad.
|
||||
//!
|
||||
//! # ⚡️ Guía rápida
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@ pub use crate::core::{AnyBase, AnyTo};
|
|||
|
||||
pub use crate::core::action::*;
|
||||
pub use crate::core::component::*;
|
||||
pub use crate::core::layout::*;
|
||||
pub use crate::core::package::*;
|
||||
pub use crate::core::theme::*;
|
||||
|
||||
pub use crate::response::{json::*, page::*, redirect::*, ResponseError};
|
||||
|
||||
pub use crate::base::action;
|
||||
pub use crate::base::component::*;
|
||||
pub use crate::base::layout;
|
||||
pub use crate::base::theme;
|
||||
|
||||
pub use crate::app::Application;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,12 @@ impl Page {
|
|||
self
|
||||
}
|
||||
|
||||
#[fn_builder]
|
||||
pub fn alter_theme(&mut self, theme: &'static str) -> &mut Self {
|
||||
self.context.alter_assets(AssetsOp::Theme(theme));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_builder]
|
||||
pub fn alter_layout(&mut self, layout: &'static str) -> &mut Self {
|
||||
self.context.alter_assets(AssetsOp::Layout(layout));
|
||||
|
|
@ -157,22 +163,22 @@ impl Page {
|
|||
|
||||
pub fn render(&mut self) -> ResultPage<Markup, ErrorPage> {
|
||||
// Acciones específicas del diseño antes de renderizar el <body>.
|
||||
action::layout::BeforeRenderBody::dispatch(self);
|
||||
action::theme::BeforeRenderBody::dispatch(self);
|
||||
|
||||
// Acciones de los paquetes antes de renderizar el <body>.
|
||||
action::page::BeforeRenderBody::dispatch(self);
|
||||
|
||||
// Renderiza el <body>.
|
||||
let body = self.context.layout().render_body(self);
|
||||
let body = self.context.theme().render_body(self);
|
||||
|
||||
// Acciones específicas del diseño después de renderizar el <body>.
|
||||
action::layout::AfterRenderBody::dispatch(self);
|
||||
action::theme::AfterRenderBody::dispatch(self);
|
||||
|
||||
// Acciones de los paquetes después de renderizar el <body>.
|
||||
action::page::AfterRenderBody::dispatch(self);
|
||||
|
||||
// Renderiza el <head>.
|
||||
let head = self.context.layout().render_head(self);
|
||||
let head = self.context.theme().render_head(self);
|
||||
|
||||
// Compone la página completa incluyendo los atributos de idioma y dirección del texto.
|
||||
let lang = &self.context.langid().language;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue