🎨 Improve registering packages

This commit is contained in:
Manuel Cillero 2024-11-30 18:53:35 +01:00
parent ddd27fd2a6
commit 3827c859e9
5 changed files with 52 additions and 22 deletions

View file

@ -4,14 +4,18 @@ use crate::util::TypeInfo;
use std::any::Any;
// Common definitions for core types.
/// A base trait that extends `Any` to provide metadata and dynamic type casting capabilities.
pub trait AnyBase: Any {
/// Returns the full name of the type.
fn type_name(&self) -> &'static str;
/// Returns a short name for the type.
fn short_name(&self) -> &'static str;
/// Returns a reference to `dyn Any` for dynamic type casting.
fn as_any_ref(&self) -> &dyn Any;
/// Returns a mutable reference to `dyn Any` for dynamic type casting.
fn as_any_mut(&mut self) -> &mut dyn Any;
}
@ -38,7 +42,9 @@ impl<T: Any> AnyBase for T {
}
}
/// A trait for advanced dynamic type manipulation and downcasting.
pub trait AnyTo: AnyBase {
/// Checks if the type is of the specified type `T`.
#[inline]
fn is<T>(&self) -> bool
where
@ -47,6 +53,7 @@ pub trait AnyTo: AnyBase {
self.as_any_ref().is::<T>()
}
/// Attempts to downcast a reference to the specified type `T`.
#[inline]
fn downcast_ref<T>(&self) -> Option<&T>
where
@ -55,6 +62,7 @@ pub trait AnyTo: AnyBase {
self.as_any_ref().downcast_ref()
}
/// Attempts to downcast a mutable reference to the specified type `T`.
#[inline]
fn downcast_mut<T>(&mut self) -> Option<&mut T>
where
@ -66,7 +74,7 @@ pub trait AnyTo: AnyBase {
impl<T: ?Sized + AnyBase> AnyTo for T {}
// API to define functions that alter the behavior of PageTop core.
// API to define functions that alter the predefined behavior of the code.
pub mod action;
// API to build new components.

View file

@ -5,8 +5,6 @@ use crate::{global, include_files, include_files_service, service, trace};
use std::sync::{LazyLock, RwLock};
include_files!(assets);
// PACKAGES ****************************************************************************************
static ENABLED_PACKAGES: LazyLock<RwLock<Vec<PackageRef>>> =
@ -24,15 +22,14 @@ pub fn register_packages(root_package: Option<PackageRef>) {
// Add default theme to the enabled list.
add_to_enabled(&mut enabled_list, &crate::base::theme::Basic);
// Add default welcome page package to the enabled list.
add_to_enabled(&mut enabled_list, &crate::base::package::Welcome);
// If a root package is provided, add it to the enabled list.
if let Some(package) = root_package {
add_to_enabled(&mut enabled_list, package);
}
// Reverse the order to ensure packages are sorted from none to most dependencies.
enabled_list.reverse();
// Add default welcome page package to the enabled list.
add_to_enabled(&mut enabled_list, &crate::base::package::Welcome);
// Save the final list of enabled packages.
ENABLED_PACKAGES.write().unwrap().append(&mut enabled_list);
@ -49,16 +46,14 @@ pub fn register_packages(root_package: Option<PackageRef>) {
fn add_to_enabled(list: &mut Vec<PackageRef>, package: PackageRef) {
// Check if the package is not already in the enabled list to avoid duplicates.
if !list.iter().any(|p| p.type_id() == package.type_id()) {
// Add the package to the enabled list.
list.push(package);
// Reverse dependencies to add them in correct order (dependencies first).
let mut dependencies = package.dependencies();
dependencies.reverse();
for d in &dependencies {
// Add the package dependencies in reverse order first.
for d in package.dependencies().iter().rev() {
add_to_enabled(list, *d);
}
// Add the package itself to the enabled list.
list.push(package);
// Check if the package has an associated theme to register.
if let Some(theme) = package.theme() {
let mut registered_themes = THEMES.write().unwrap();
@ -127,6 +122,8 @@ pub fn init_packages() {
// CONFIGURE SERVICES ******************************************************************************
include_files!(assets);
pub fn configure_services(scfg: &mut service::web::ServiceConfig) {
for m in ENABLED_PACKAGES.read().unwrap().iter() {
m.configure_service(scfg);

View file

@ -13,7 +13,7 @@ pub trait PackageTrait: AnyBase + Send + Sync {
}
fn description(&self) -> L10n {
L10n::none()
L10n::default()
}
fn theme(&self) -> Option<ThemeRef> {

View file

@ -79,7 +79,7 @@ pub trait ThemeTrait: PackageTrait + Send + Sync {
meta charset="utf-8";
@if let Some(title) = page.title() {
title { (global::SETTINGS.app.name) (" - ") (title) }
title { (global::SETTINGS.app.name) (" | ") (title) }
} @else {
title { (global::SETTINGS.app.name) }
}
@ -102,4 +102,33 @@ pub trait ThemeTrait: PackageTrait + Send + Sync {
}
})
}
/*
fn prepare_page_body(&self, page: &mut Page) -> PrepareMarkup {
PrepareMarkup::With(html! {
body id=[page.body_id().get()] class=[page.body_classes().get()] {
(page.body_content().render())
}
})
}
fn error_403(&self, request: service::HttpRequest) -> Page {
Page::new(request)
.with_title(L10n::n("Error FORBIDDEN"))
.with_body(PrepareMarkup::With(html! {
div {
h1 { ("FORBIDDEN ACCESS") }
}
}))
}
fn error_404(&self, request: service::HttpRequest) -> Page {
Page::new(request)
.with_title(L10n::n("Error RESOURCE NOT FOUND"))
.with_body(PrepareMarkup::With(html! {
div {
h1 { ("RESOURCE NOT FOUND") }
}
}))
}
*/
}

View file

@ -182,10 +182,6 @@ pub struct L10n {
}
impl L10n {
pub fn none() -> Self {
L10n::default()
}
pub fn n(text: impl Into<String>) -> Self {
L10n {
op: L10nOp::Text(text.into()),