🔥 [pagetop] Saca temas y jQuery de PageTop

This commit is contained in:
Manuel Cillero 2023-02-01 20:22:50 +01:00
parent f8a4e82297
commit 80e433b20d
29 changed files with 90 additions and 330 deletions

View file

@ -2,12 +2,19 @@
members = [
"pagetop",
# Utilities.
"pagetop-macros",
"pagetop-build",
"pagetop-jquery",
# Modules.
"pagetop-admin",
"pagetop-user",
"pagetop-node",
# Themes.
"pagetop-minimal",
"pagetop-aliner",
"pagetop-bootsier",
"pagetop-bulmix",
]
exclude = [

View file

@ -16,6 +16,12 @@ license = "Apache-2.0 OR MIT"
[dependencies]
actix-web = "4.2.1"
pagetop = { path = "../pagetop", version = "0.0", features = ["mysql"], default-features = false }
# Modules.
pagetop-admin = { path = "../pagetop-admin", version = "0.0" }
pagetop-user = { path = "../pagetop-user", version = "0.0" }
pagetop-node = { path = "../pagetop-node", version = "0.0" }
# Themes.
pagetop-minimal = { path = "../pagetop-minimal", version = "0.0" }
pagetop-aliner = { path = "../pagetop-aliner", version = "0.0" }
pagetop-bootsier = { path = "../pagetop-bootsier", version = "0.0" }
pagetop-bulmix = { path = "../pagetop-bulmix", version = "0.0" }

View file

@ -11,9 +11,15 @@ impl ModuleTrait for Drust {
fn dependencies(&self) -> Vec<ModuleStaticRef> {
vec![
// Modules.
&pagetop_admin::Admin,
&pagetop_user::User,
&pagetop_node::Node,
// Themes.
&pagetop_minimal::Minimal,
&pagetop_aliner::Aliner,
&pagetop_bootsier::Bootsier,
&pagetop_bulmix::Bulmix,
]
}

View file

@ -1,6 +1,3 @@
fn main() -> std::io::Result<()> {
pagetop_build::bundle_resources("./static/theme", "theme", None)?;
pagetop_build::bundle_resources("./static/aliner", "aliner", None)?;
pagetop_build::bundle_resources("./static/bootsier", "bootsier", None)?;
pagetop_build::bundle_resources("./static/bulmix", "bulmix", None)
pagetop_build::bundle_resources("./static/theme", "theme", None)
}

View file

@ -2,7 +2,7 @@
name = "PageTop Application"
description = "Developed with the amazing PageTop framework."
# Tema predeterminado.
theme = "Bootsier"
theme = "Saturn"
# Idioma (localización) predeterminado.
language = "en-US"
# Dirección predeterminada para el texto: "ltr", "rtl" o "auto".

View file

@ -1,5 +1,4 @@
use crate::core::module::ModuleStaticRef;
use crate::core::{module, theme};
use crate::core::{module, module::ModuleStaticRef};
use crate::html::Markup;
use crate::response::page::ResultPage;
use crate::response::FatalError;
@ -52,7 +51,6 @@ impl Application {
server::App::new()
.wrap(tracing_actix_web::TracingLogger::default())
.configure(module::all::configure_services)
.configure(theme::all::configure_services)
.default_service(server::web::route().to(service_not_found))
})
.bind(format!(

View file

@ -17,8 +17,8 @@ mod block;
pub use block::{Block, COMPONENT_BLOCK};
mod image;
pub use image::{Image, COMPONENT_IMAGE};
mod menu;
pub use menu::{Menu, MenuItem, MenuItemType, COMPONENT_MENU, COMPONENT_MENUITEM};
//mod menu;
//pub use menu::{Menu, MenuItem, MenuItemType, COMPONENT_MENU, COMPONENT_MENUITEM};
pub mod form_element;
pub use form_element::{Form, FormMethod, COMPONENT_FORM};

View file

@ -1,7 +1,30 @@
pub mod aliner;
use crate::prelude::*;
pub mod minimal;
pub_handle!(THEME_SATURN);
pub mod bootsier;
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
pub mod bulmix;
pub struct Saturn;
impl ModuleTrait for Saturn {
fn handle(&self) -> Handle {
THEME_SATURN
}
fn theme(&self) -> Option<ThemeStaticRef> {
Some(&Saturn)
}
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/theme", bundle_theme);
}
}
impl ThemeTrait for Saturn {
fn before_render_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/theme/css/styles.css").with_weight(-99),
));
}
}

View file

@ -1,24 +0,0 @@
use crate::prelude::*;
pub_handle!(THEME_ALINER);
include!(concat!(env!("OUT_DIR"), "/aliner.rs"));
pub struct Aliner;
impl ThemeTrait for Aliner {
fn handle(&self) -> Handle {
THEME_ALINER
}
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/aliner", bundle_aliner);
}
fn before_render_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
));
}
}

View file

@ -1,61 +0,0 @@
use crate::prelude::*;
pub_handle!(THEME_BOOTSIER);
pub_locale!("src/base/theme/bootsier/locales");
include!(concat!(env!("OUT_DIR"), "/bootsier.rs"));
pub struct Bootsier;
impl ThemeTrait for Bootsier {
fn handle(&self) -> Handle {
THEME_BOOTSIER
}
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/bootsier", bundle_bootsier);
}
fn before_render_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_context(ContextOp::AddJavaScript(
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_version("5.1.3")
.with_weight(-99),
))
.alter_context(ContextOp::AddJQuery);
}
fn error_404_not_found(&self) -> Container {
Container::new().with_component(Html::with(html! {
div class="jumbotron" {
div class="media" {
img
src="/bootsier/images/caution.png"
class="mr-4"
style="width: 20%; max-width: 188px"
alt="Caution!";
div class="media-body" {
h1 class="display-4" { ("RESOURCE NOT FOUND") }
p class="lead" { (l("e404-description")) }
hr class="my-4";
p { (l("e404-description")) }
a
class="btn btn-primary btn-lg"
href="/"
role="button"
{
(l("back-homepage"))
}
}
}
}
}))
}
}

View file

@ -1,5 +0,0 @@
e404-description = Oops! Page Not Found
e404-message = The page you are looking for may have been removed, had its name changed, or is temporarily unavailable.
e500-description = Oops! Unexpected Error
e500-message = We're having an issue. Please report this error to an administrator.
back-homepage = Back to homepage

View file

@ -1,5 +0,0 @@
e404-description = ¡Vaya! Página No Encontrada
e404-message = La página que está buscando puede haber sido eliminada, cambiada de nombre o no está disponible temporalmente.
e500-description = ¡Vaya! Error Inesperado
e500-message = Está ocurriendo una incidencia. Por favor, informe de este error a un administrador.
back-homepage = Volver al inicio

View file

@ -1,125 +0,0 @@
use crate::prelude::*;
pub_handle!(THEME_BULMIX);
include!(concat!(env!("OUT_DIR"), "/bulmix.rs"));
pub struct Bulmix;
impl ThemeTrait for Bulmix {
fn handle(&self) -> Handle {
THEME_BULMIX
}
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/bulmix", bundle_bulmix);
}
fn before_render_page(&self, page: &mut Page) {
page.alter_favicon(Some(Favicon::new().with_icon("/theme/favicon.ico")))
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::located("/bulmix/css/bulma.min.css")
.with_version("0.9.4")
.with_weight(-99),
))
.alter_context(ContextOp::AddJQuery);
}
#[rustfmt::skip]
fn before_render_component(
&self,
component: &mut dyn ComponentTrait,
_rcx: &mut RenderContext,
) {
match component.handle() {
COMPONENT_ANCHOR => {
let a = component_mut::<Anchor>(component);
a.alter_classes(
ClassesOp::SetDefault,
match a.anchor_type() {
AnchorType::Button => "button is-primary",
_ => "",
},
);
}
COMPONENT_HEADING => {
let h = component_mut::<Heading>(component);
h.alter_classes(
ClassesOp::SetDefault,
match h.display() {
HeadingDisplay::XxLarge => "title is-1",
HeadingDisplay::Large => "title is-2",
HeadingDisplay::Medium => "title is-3",
HeadingDisplay::Small => "title is-4",
HeadingDisplay::XxSmall => "title is-5",
HeadingDisplay::Normal => "title",
HeadingDisplay::Subtitle => "subtitle",
},
);
}
COMPONENT_PARAGRAPH => {
let p = component_mut::<Paragraph>(component);
p.alter_classes(
ClassesOp::SetDefault,
match p.display() {
ParagraphDisplay::XxLarge => "is-size-2",
ParagraphDisplay::Large => "is-size-3",
ParagraphDisplay::Medium => "is-size-4",
ParagraphDisplay::Small => "is-size-5",
ParagraphDisplay::XxSmall => "is-size-6",
ParagraphDisplay::Normal => "",
},
);
}
grid::COMPONENT_COLUMN => {
let col = component_mut::<grid::Column>(component);
col.alter_classes(
ClassesOp::SetDefault,
concat_string!(
"column",
match col.size() {
grid::ColumnSize::Default => "",
grid::ColumnSize::Is1of12 => " is-1",
grid::ColumnSize::Is2of12 => " is-2",
grid::ColumnSize::Is3of12 => " is-3",
grid::ColumnSize::Is4of12 => " is-4",
grid::ColumnSize::Is5of12 => " is-5",
grid::ColumnSize::Is6of12 => " is-6",
grid::ColumnSize::Is7of12 => " is-7",
grid::ColumnSize::Is8of12 => " is-8",
grid::ColumnSize::Is9of12 => " is-9",
grid::ColumnSize::Is10of12 => " is-10",
grid::ColumnSize::Is11of12 => " is-11",
grid::ColumnSize::IsFull => " is-12",
},
" content"
)
.as_str(),
);
}
grid::COMPONENT_ROW => {
let row = component_mut::<grid::Row>(component);
row.alter_classes(ClassesOp::SetDefault, "columns");
}
_ => {}
}
}
fn render_component(
&self,
component: &dyn ComponentTrait,
_rcx: &mut RenderContext,
) -> Option<Markup> {
match component.handle() {
COMPONENT_ICON => {
let icon = component_ref::<Icon>(component);
Some(html! {
span class="icon" {
i class=[icon.classes().get()] {};
}
})
}
_ => None,
}
}
}

View file

@ -1,11 +0,0 @@
use crate::prelude::*;
pub_handle!(THEME_MINIMAL);
pub struct Minimal;
impl ThemeTrait for Minimal {
fn handle(&self) -> Handle {
THEME_MINIMAL
}
}

View file

@ -1,12 +1,15 @@
use crate::core::theme::{all::theme_by_single_name, ThemeStaticRef};
use crate::html::{html, Assets, IdentifierValue, JavaScript, Markup, ModeJS, StyleSheet};
use crate::html::{html, Assets, IdentifierValue, JavaScript, Markup, StyleSheet};
use crate::server::HttpRequest;
use crate::{base, concat_string, config, util, LazyStatic};
use std::collections::HashMap;
use std::str::FromStr;
static DEFAULT_THEME: LazyStatic<ThemeStaticRef> =
LazyStatic::new(|| match theme_by_single_name(&config::SETTINGS.app.theme) {
Some(theme) => theme,
None => &base::theme::bootsier::Bootsier,
None => &base::theme::Saturn,
});
pub enum ContextOp {
@ -16,7 +19,6 @@ pub enum ContextOp {
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery,
}
#[rustfmt::skip]
@ -25,7 +27,7 @@ pub struct RenderContext {
request : Option<HttpRequest>,
stylesheets: Assets<StyleSheet>,
javascripts: Assets<JavaScript>,
with_jquery: bool,
params : HashMap<&'static str, String>,
id_counter : usize,
}
@ -37,7 +39,7 @@ impl Default for RenderContext {
request : None,
stylesheets: Assets::<StyleSheet>::new(),
javascripts: Assets::<JavaScript>::new(),
with_jquery: false,
params : HashMap::<&str, String>::new(),
id_counter : 0,
}
}
@ -68,18 +70,12 @@ impl RenderContext {
ContextOp::RemoveJavaScript(source) => {
self.javascripts.remove(source);
}
ContextOp::AddJQuery => {
if !self.with_jquery {
self.javascripts.add(
JavaScript::located("/theme/js/jquery.min.js")
.with_version("3.6.0")
.with_weight(isize::MIN)
.with_mode(ModeJS::Normal),
);
self.with_jquery = true;
}
}
self
}
pub fn set_param<T: FromStr + ToString>(&mut self, key: &'static str, value: T) -> &mut Self {
self.params.insert(key, value.to_string());
self
}
@ -93,6 +89,14 @@ impl RenderContext {
&self.request
}
pub fn get_param<T: FromStr + ToString>(&mut self, key: &'static str) -> Option<T> {
if let Some(value) = self.params.get(key) {
if let Ok(value) = T::from_str(value) {
return Some(value);
}
}
None
}
/// Context RENDER.
pub fn render(&mut self) -> Markup {

View file

@ -35,6 +35,7 @@ pub fn register_modules(app: ModuleStaticRef) {
// Enable default homepage.
add_to_enabled(&mut list, &module::homepage::DefaultHomePage);
add_to_enabled(&mut list, &crate::base::theme::Saturn);
list.reverse();
ENABLED_MODULES.write().unwrap().append(&mut list);
@ -82,7 +83,7 @@ fn add_to_enabled(list: &mut Vec<ModuleStaticRef>, module: ModuleStaticRef) {
pub fn register_themes() {
for m in ENABLED_MODULES.read().unwrap().iter() {
theme::all::register_themes(m.themes());
theme::all::register_theme(m.handle(), m.theme());
}
}

View file

@ -24,6 +24,10 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
None
}
fn theme(&self) -> Option<ThemeStaticRef> {
None
}
fn dependencies(&self) -> Vec<ModuleStaticRef> {
vec![]
}
@ -32,10 +36,6 @@ pub trait ModuleTrait: BaseModule + Send + Sync {
vec![]
}
fn themes(&self) -> Vec<ThemeStaticRef> {
vec![]
}
fn actions(&self) -> Vec<HookAction> {
vec![]
}

View file

@ -1,29 +1,19 @@
use super::ThemeStaticRef;
use crate::{base, serve_static_files, server, trace, LazyStatic};
use crate::util::Handle;
use crate::{trace, LazyStatic};
use std::sync::RwLock;
include!(concat!(env!("OUT_DIR"), "/theme.rs"));
// Temas registrados.
static THEMES: LazyStatic<RwLock<Vec<ThemeStaticRef>>> = LazyStatic::new(|| {
RwLock::new(vec![
&base::theme::aliner::Aliner,
&base::theme::minimal::Minimal,
&base::theme::bootsier::Bootsier,
&base::theme::bulmix::Bulmix,
])
});
static THEMES: LazyStatic<RwLock<Vec<(Handle, ThemeStaticRef)>>> =
LazyStatic::new(|| RwLock::new(Vec::new()));
pub fn register_themes(themes: Vec<ThemeStaticRef>) {
pub fn register_theme(handle: Handle, theme: Option<ThemeStaticRef>) {
if let Some(theme) = theme {
let mut registered_themes = THEMES.write().unwrap();
for theme in themes {
if !registered_themes
.iter()
.any(|t| t.handle() == theme.handle())
{
if !registered_themes.iter().any(|t| t.0 == handle) {
trace::debug!("Registering theme \"{}\"", theme.single_name());
registered_themes.push(theme);
registered_themes.push((handle, theme));
}
}
}
@ -33,17 +23,9 @@ pub fn theme_by_single_name(single_name: &str) -> Option<ThemeStaticRef> {
.write()
.unwrap()
.iter()
.find(|t| t.single_name().to_lowercase() == single_name.to_lowercase())
.find(|t| t.1.single_name().to_lowercase() == single_name.to_lowercase())
{
Some(theme) => Some(*theme),
Some((_, theme)) => Some(*theme),
_ => None,
}
}
pub fn configure_services(cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/theme", bundle_theme);
for t in THEMES.read().unwrap().iter() {
t.configure_service(cfg);
}
}

View file

@ -2,8 +2,8 @@ use crate::base::component::{Container, Html};
use crate::core::component::{ComponentTrait, RenderContext};
use crate::html::{html, Favicon, Markup};
use crate::response::page::Page;
use crate::util::{single_type_name, Handle};
use crate::{concat_string, config, server};
use crate::util::single_type_name;
use crate::{concat_string, config};
pub type ThemeStaticRef = &'static dyn ThemeTrait;
@ -13,19 +13,6 @@ pub trait BaseTheme {
/// Los temas deben implementar este "trait".
pub trait ThemeTrait: BaseTheme + Send + Sync {
fn handle(&self) -> Handle;
fn name(&self) -> String {
self.single_name().to_owned()
}
fn description(&self) -> Option<String> {
None
}
#[allow(unused_variables)]
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {}
#[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) {
if page.favicon().is_none() {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long