From 8e0a1d5994ad1ef8db2029bfebc8208f68e63fb7 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 4 Dec 2024 20:24:54 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Cambia=20"Temas"=20(themes)=20po?= =?UTF-8?q?r=20"Dise=C3=B1os"=20(layouts)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 13 +- README.md | 18 ++- config/default.toml | 4 +- config/predefined.toml | 4 +- drust/README.md | 6 + drust/src/main.rs | 4 +- drust/tools/create-drust-db.sh | 119 ++++++++++++++++++ drust/tools/drop-drust-db.sh | 105 ++++++++++++++++ helpers/pagetop-build/src/lib.rs | 2 +- pagetop/src/base.rs | 6 +- pagetop/src/base/action.rs | 8 +- .../src/base/action/{theme.rs => layout.rs} | 0 .../after_prepare_component.rs | 12 +- .../before_prepare_component.rs | 12 +- .../{theme => layout}/render_component.rs | 12 +- pagetop/src/base/{theme.rs => layout.rs} | 4 +- pagetop/src/base/package.rs | 2 +- pagetop/src/core.rs | 8 +- pagetop/src/core/action/definition.rs | 10 +- pagetop/src/core/component/context.rs | 26 ++-- pagetop/src/core/component/definition.rs | 10 +- pagetop/src/core/{theme.rs => layout.rs} | 2 +- pagetop/src/core/{theme => layout}/all.rs | 22 ++-- .../src/core/{theme => layout}/definition.rs | 6 +- pagetop/src/core/{theme => layout}/regions.rs | 18 +-- pagetop/src/core/package/all.rs | 22 ++-- pagetop/src/core/package/definition.rs | 4 +- pagetop/src/global.rs | 6 +- pagetop/src/html/opt_classes.rs | 2 +- pagetop/src/lib.rs | 12 +- pagetop/src/prelude.rs | 4 +- pagetop/src/response/page.rs | 12 +- 32 files changed, 361 insertions(+), 134 deletions(-) create mode 100755 drust/tools/create-drust-db.sh create mode 100755 drust/tools/drop-drust-db.sh rename pagetop/src/base/action/{theme.rs => layout.rs} (100%) rename pagetop/src/base/action/{theme => layout}/after_prepare_component.rs (75%) rename pagetop/src/base/action/{theme => layout}/before_prepare_component.rs (75%) rename pagetop/src/base/action/{theme => layout}/render_component.rs (80%) rename pagetop/src/base/{theme.rs => layout.rs} (58%) rename pagetop/src/core/{theme.rs => layout.rs} (72%) rename pagetop/src/core/{theme => layout}/all.rs (52%) rename pagetop/src/core/{theme => layout}/definition.rs (92%) rename pagetop/src/core/{theme => layout}/regions.rs (76%) diff --git a/Cargo.toml b/Cargo.toml index 58c55d38..fb8450d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,11 @@ members = [ # PageTop "pagetop", + # Layouts + #"layouts/pagetop-aliner", + #"layouts/pagetop-bootsier", + # Packages - #"packages/pagetop-aliner", - #"packages/pagetop-bootsier", #"packages/pagetop-seaorm", # App @@ -35,6 +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-aliner = { version = "0.0", path = "packages/pagetop-aliner" } -#pagetop-bootsier = { version = "0.0", path = "packages/pagetop-bootsier" } +#pagetop-seaorm = { version = "0.0", path = "packages/pagetop-seaorm" } diff --git a/README.md b/README.md index e7f8731c..a5fa540a 100644 --- a/README.md +++ b/README.md @@ -13,24 +13,22 @@ -## Presentación - **PageTop** reúne algunos de los *crates* más estables y populares del ecosistema Rust para proporcionar un conjunto completo de funcionalidades que pueden extenderse y adaptarse a las necesidades específicas de cada aplicación web. PageTop reivindica la sencillez de la web clásica aplicando *renderizado en el servidor* (SSR), -HTML, CSS y JS, mediante acciones, componentes, paquetes y temas: +HTML, CSS y JS, mediante acciones, componentes, diseños y paquetes: - * **Acciones**. Las funciones y procedimientos que incorporen *acciones* en su lógica de programa + * **Acciones** (*actions*). Las funcionalidades que incorporen acciones en su lógica de programa estarán proporcionando a los desarrolladores herramientas para alterar su comportamiento interno interceptando su flujo de ejecución. - * **Componentes**. Encapsulan HTML, CSS y JavaScript en unidades funcionales, configurables y bien - definidas. - * **Paquetes**. Extienden o personalizan funcionalidades existentes interactuando con las APIs de - PageTop o de paquetes de terceros. - * **Temas**. Permiten a los desarrolladores alterar la apariencia de las páginas y componentes sin - afectar su funcionalidad. + * **Componentes** (*components*). Encapsulan 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. # ⚡️ Inicio rápido diff --git a/config/default.toml b/config/default.toml index 3c61765c..7ec78a84 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,6 +1,6 @@ [app] -#theme = "Aliner" -#theme = "Bootsier" +#layout = "Aliner" +#layout = "Bootsier" language = "es-ES" [log] diff --git a/config/predefined.toml b/config/predefined.toml index 08571a92..75665b61 100644 --- a/config/predefined.toml +++ b/config/predefined.toml @@ -1,8 +1,8 @@ [app] name = "My App" description = "Developed with the amazing PageTop framework." -# Default theme. -theme = "Default" +# Default layout. +layout = "Default" # Default language (localization). language = "en-US" # Default text direction: "ltr", "rtl", or "auto". diff --git a/drust/README.md b/drust/README.md index 2e00c72d..86eab1dc 100644 --- a/drust/README.md +++ b/drust/README.md @@ -10,6 +10,12 @@ +Modestamente inspirado en [Drupal](https://www.drupal.org), **Drust** exprime **PageTop** para +desarrollar un *Sistema de Gestión de Contenidos* (CMS) básico, que permita construir sitios web +dinámicos, manejables y personalizables; y facilite a los usuarios la gestión de una variedad de +contenidos de manera sencilla. + + # 📦 Sobre PageTop [PageTop](https://docs.rs/pagetop) es un entorno de desarrollo con convenciones que reivindican la diff --git a/drust/src/main.rs b/drust/src/main.rs index 44fb54bd..90fee5cf 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -5,8 +5,10 @@ struct Drust; impl PackageTrait for Drust { fn dependencies(&self) -> Vec { vec![ - // Packages. + // Layouts. //&pagetop_bootsier::Bootsier, + + // Packages. //&pagetop_admin::Admin, //&pagetop_user::User, //&pagetop_node::Node, diff --git a/drust/tools/create-drust-db.sh b/drust/tools/create-drust-db.sh new file mode 100755 index 00000000..55d086b1 --- /dev/null +++ b/drust/tools/create-drust-db.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +# Ask the user which database system to use +read -p "Which database system are you using? (mysql/postgresql/sqlite): " DB_SYSTEM + +# Check if selected database system is installed +if [ "$DB_SYSTEM" == "mysql" ]; then + if ! command -v mysql &> /dev/null; then + echo "mysql is not installed or not found in PATH. Please install mysql and try again." + exit 1 + fi +elif [ "$DB_SYSTEM" == "postgresql" ]; then + if ! command -v psql &> /dev/null; then + echo "postgresql is not installed or not found in PATH. Please install postgresql and try again." + exit 1 + fi +elif [ "$DB_SYSTEM" == "sqlite" ]; then + if ! command -v sqlite3 &> /dev/null; then + echo "sqlite3 is not installed or not found in PATH. Please install sqlite3 and try again." + exit 1 + fi +else + echo "Invalid database system selected. Please choose either 'mysql', 'postgresql', or 'sqlite'." + exit 1 +fi + +EXIT_CODE=0 + +echo +echo "You will be prompted to provide details for creating the Drust database." +echo "Press ENTER to accept the default values." +echo + +if [ "$DB_SYSTEM" == "sqlite" ]; then + DEFAULT_DB_NAME="drust.db" + + # Only prompt for database name, as user and password are not used by SQLite + read -p "Enter database name [$DEFAULT_DB_NAME]: " DB_NAME + DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME} + + # For SQLite, just check if the database file exists and create it if it doesn't + if [ ! -f "$DB_NAME" ]; then + echo "Creating SQLite database file: $DB_NAME" + sqlite3 "$DB_NAME" ".quit" + EXIT_CODE=$? + else + echo "SQLite database file $DB_NAME already exists." + exit 1 + fi +else + DEFAULT_DB_NAME="drust" + DEFAULT_DB_USER="drust" + DEFAULT_DB_PASS="demo" + DEFAULT_DB_HOST="localhost" + DEFAULT_DB_ADMIN="root" + + # Prompt for database details, allow defaults + read -p "Enter database name [$DEFAULT_DB_NAME]: " DB_NAME + DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME} + + read -p "Enter database user [$DEFAULT_DB_USER]: " DB_USER + DB_USER=${DB_USER:-$DEFAULT_DB_USER} + + read -p "Enter database password [$DEFAULT_DB_PASS]: " DB_PASS + DB_PASS=${DB_PASS:-$DEFAULT_DB_PASS} + + read -p "Enter database host [$DEFAULT_DB_HOST]: " DB_HOST + DB_HOST=${DB_HOST:-$DEFAULT_DB_HOST} + + # Prompt for database system root or another privileged user's credentials + echo + read -p "Enter $DB_SYSTEM admin user [$DEFAULT_DB_ADMIN]: " DB_ADMIN + DB_ADMIN=${DB_ADMIN:-$DEFAULT_DB_ADMIN} + read -sp "Enter $DB_SYSTEM admin password: " DB_ADMIN_PASS + echo + + # Confirm before proceeding + echo + echo "You are about to create the database \"$DB_NAME\" and assign privileges to user \"$DB_USER\"." + read -p "Are you sure you want to proceed? (y/N): " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + echo "Operation cancelled." + exit 1 + fi + + # Execute commands for MySQL or PostgreSQL + if [ "$DB_SYSTEM" == "mysql" ]; then + MYSQL_PWD="$DB_ADMIN_PASS" mysql -u "$DB_ADMIN" -h "$DB_HOST" < /dev/null; then + echo "mysql is not installed or not found in PATH. Please install mysql and try again." + exit 1 + fi +elif [ "$DB_SYSTEM" == "postgresql" ]; then + if ! command -v psql &> /dev/null; then + echo "postgresql is not installed or not found in PATH. Please install postgresql and try again." + exit 1 + fi +elif [ "$DB_SYSTEM" == "sqlite" ]; then + if ! command -v sqlite3 &> /dev/null; then + echo "sqlite3 is not installed or not found in PATH. Please install sqlite3 and try again." + exit 1 + fi +else + echo "Invalid database system selected. Please choose either 'mysql', 'postgresql', or 'sqlite'." + exit 1 +fi + +EXIT_CODE=0 + +echo +echo "You will be prompted to provide details to delete the Drust database." +echo "Press ENTER to accept the default values." +echo + +if [ "$DB_SYSTEM" == "sqlite" ]; then + DEFAULT_DB_NAME="drust.db" + + # Only prompt for database name + read -p "Enter database name to delete [$DEFAULT_DB_NAME]: " DB_NAME + DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME} + + # For SQLite, check if the database file exists and delete it + if [ -f "$DB_NAME" ]; then + echo "Deleting SQLite database file: $DB_NAME" + rm "$DB_NAME" + EXIT_CODE=$? + else + echo "SQLite database file $DB_NAME does not exist." + exit 1 + fi +else + DEFAULT_DB_NAME="drust" + DEFAULT_DB_USER="drust" + DEFAULT_DB_HOST="localhost" + DEFAULT_DB_ADMIN="root" + + # Prompt for database details, allow defaults + read -p "Enter database name to delete [$DEFAULT_DB_NAME]: " DB_NAME + DB_NAME=${DB_NAME:-$DEFAULT_DB_NAME} + + read -p "Enter database user to delete [$DEFAULT_DB_USER]: " DB_USER + DB_USER=${DB_USER:-$DEFAULT_DB_USER} + + read -p "Enter database host [$DEFAULT_DB_HOST]: " DB_HOST + DB_HOST=${DB_HOST:-$DEFAULT_DB_HOST} + + # Prompt for database system root or another privileged user's credentials + echo + read -p "Enter $DB_SYSTEM admin user [$DEFAULT_DB_ADMIN]: " DB_ADMIN + DB_ADMIN=${DB_ADMIN:-$DEFAULT_DB_ADMIN} + read -sp "Enter $DB_SYSTEM admin password: " DB_ADMIN_PASS + echo + + # Confirm before proceeding + echo + echo "You are about to delete the database \"$DB_NAME\"." + read -p "Are you sure you want to proceed? (y/N): " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + echo "Operation cancelled." + exit 1 + fi + + # Execute commands for MySQL or PostgreSQL + if [ "$DB_SYSTEM" == "mysql" ]; then + MYSQL_PWD="$DB_ADMIN_PASS" mysql -u "$DB_ADMIN" -h "$DB_HOST" < = fn(component: &mut C, cx: &mut Context); -pub mod page; - -pub mod theme; - pub mod component; + +pub mod layout; + +pub mod page; diff --git a/pagetop/src/base/action/theme.rs b/pagetop/src/base/action/layout.rs similarity index 100% rename from pagetop/src/base/action/theme.rs rename to pagetop/src/base/action/layout.rs diff --git a/pagetop/src/base/action/theme/after_prepare_component.rs b/pagetop/src/base/action/layout/after_prepare_component.rs similarity index 75% rename from pagetop/src/base/action/theme/after_prepare_component.rs rename to pagetop/src/base/action/layout/after_prepare_component.rs index 7285aec1..62adfa21 100644 --- a/pagetop/src/base/action/theme/after_prepare_component.rs +++ b/pagetop/src/base/action/layout/after_prepare_component.rs @@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent; pub struct AfterPrepare { f: FnActionWithComponent, - theme_type_id: Option, + layout_type_id: Option, referer_type_id: Option, } impl ActionTrait for AfterPrepare { - fn theme_type_id(&self) -> Option { - self.theme_type_id + fn layout_type_id(&self) -> Option { + self.layout_type_id } fn referer_type_id(&self) -> Option { @@ -19,10 +19,10 @@ impl ActionTrait for AfterPrepare { } impl AfterPrepare { - pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { + pub fn new(layout: LayoutRef, f: FnActionWithComponent) -> Self { AfterPrepare { f, - theme_type_id: Some(theme.type_id()), + layout_type_id: Some(layout.type_id()), referer_type_id: Some(TypeId::of::()), } } @@ -33,7 +33,7 @@ impl AfterPrepare { dispatch_actions( &ActionKey::new( TypeId::of::(), - Some(cx.theme().type_id()), + Some(cx.layout().type_id()), Some(TypeId::of::()), None, ), diff --git a/pagetop/src/base/action/theme/before_prepare_component.rs b/pagetop/src/base/action/layout/before_prepare_component.rs similarity index 75% rename from pagetop/src/base/action/theme/before_prepare_component.rs rename to pagetop/src/base/action/layout/before_prepare_component.rs index 7c80a655..1ab35bba 100644 --- a/pagetop/src/base/action/theme/before_prepare_component.rs +++ b/pagetop/src/base/action/layout/before_prepare_component.rs @@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent; pub struct BeforePrepare { f: FnActionWithComponent, - theme_type_id: Option, + layout_type_id: Option, referer_type_id: Option, } impl ActionTrait for BeforePrepare { - fn theme_type_id(&self) -> Option { - self.theme_type_id + fn layout_type_id(&self) -> Option { + self.layout_type_id } fn referer_type_id(&self) -> Option { @@ -19,10 +19,10 @@ impl ActionTrait for BeforePrepare { } impl BeforePrepare { - pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { + pub fn new(layout: LayoutRef, f: FnActionWithComponent) -> Self { BeforePrepare { f, - theme_type_id: Some(theme.type_id()), + layout_type_id: Some(layout.type_id()), referer_type_id: Some(TypeId::of::()), } } @@ -33,7 +33,7 @@ impl BeforePrepare { dispatch_actions( &ActionKey::new( TypeId::of::(), - Some(cx.theme().type_id()), + Some(cx.layout().type_id()), Some(TypeId::of::()), None, ), diff --git a/pagetop/src/base/action/theme/render_component.rs b/pagetop/src/base/action/layout/render_component.rs similarity index 80% rename from pagetop/src/base/action/theme/render_component.rs rename to pagetop/src/base/action/layout/render_component.rs index e79c5c92..b20f48f1 100644 --- a/pagetop/src/base/action/theme/render_component.rs +++ b/pagetop/src/base/action/layout/render_component.rs @@ -4,13 +4,13 @@ pub type FnRenderComponent = fn(component: &C, cx: &mut Context) -> Option { f: FnRenderComponent, - theme_type_id: Option, + layout_type_id: Option, referer_type_id: Option, } impl ActionTrait for RenderComponent { - fn theme_type_id(&self) -> Option { - self.theme_type_id + fn layout_type_id(&self) -> Option { + self.layout_type_id } fn referer_type_id(&self) -> Option { @@ -19,10 +19,10 @@ impl ActionTrait for RenderComponent { } impl RenderComponent { - pub fn new(theme: ThemeRef, f: FnRenderComponent) -> Self { + pub fn new(layout: LayoutRef, f: FnRenderComponent) -> Self { RenderComponent { f, - theme_type_id: Some(theme.type_id()), + layout_type_id: Some(layout.type_id()), referer_type_id: Some(TypeId::of::()), } } @@ -34,7 +34,7 @@ impl RenderComponent { dispatch_actions( &ActionKey::new( TypeId::of::(), - Some(cx.theme().type_id()), + Some(cx.layout().type_id()), Some(TypeId::of::()), None, ), diff --git a/pagetop/src/base/theme.rs b/pagetop/src/base/layout.rs similarity index 58% rename from pagetop/src/base/theme.rs rename to pagetop/src/base/layout.rs index c07ffc56..42ba2b48 100644 --- a/pagetop/src/base/theme.rs +++ b/pagetop/src/base/layout.rs @@ -3,9 +3,9 @@ use crate::prelude::*; pub struct Basic; impl PackageTrait for Basic { - fn theme(&self) -> Option { + fn layout(&self) -> Option { Some(&Basic) } } -impl ThemeTrait for Basic {} +impl LayoutTrait for Basic {} diff --git a/pagetop/src/base/package.rs b/pagetop/src/base/package.rs index 7b633f33..37becfd8 100644 --- a/pagetop/src/base/package.rs +++ b/pagetop/src/base/package.rs @@ -19,7 +19,7 @@ impl PackageTrait for Welcome { async fn homepage(request: HttpRequest) -> ResultPage { Page::new(request) .with_title(L10n::l("welcome_page")) - .with_assets(AssetsOp::Theme("Basic")) + .with_assets(AssetsOp::Layout("Basic")) .with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##" body { background-color: #f3d060; diff --git a/pagetop/src/core.rs b/pagetop/src/core.rs index 2d65eadf..f7a47bd0 100644 --- a/pagetop/src/core.rs +++ b/pagetop/src/core.rs @@ -1,4 +1,4 @@ -//! Key types and functions for creating actions, components, packages, and themes. +//! Key types and functions for creating actions, components, layouts, and packages. use crate::util::TypeInfo; @@ -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 layouts with themes. -pub mod theme; diff --git a/pagetop/src/core/action/definition.rs b/pagetop/src/core/action/definition.rs index 05ff8b79..094da455 100644 --- a/pagetop/src/core/action/definition.rs +++ b/pagetop/src/core/action/definition.rs @@ -6,7 +6,7 @@ pub type ActionBox = Box; #[derive(Eq, PartialEq, Hash)] pub struct ActionKey { action_type_id: TypeId, - theme_type_id: Option, + layout_type_id: Option, referer_type_id: Option, referer_id: Option, } @@ -14,13 +14,13 @@ pub struct ActionKey { impl ActionKey { pub fn new( action_type_id: TypeId, - theme_type_id: Option, + layout_type_id: Option, referer_type_id: Option, referer_id: Option, ) -> Self { ActionKey { action_type_id, - theme_type_id, + layout_type_id, referer_type_id, referer_id, } @@ -32,7 +32,7 @@ pub trait ActionBase { } pub trait ActionTrait: ActionBase + AnyBase + Send + Sync { - fn theme_type_id(&self) -> Option { + fn layout_type_id(&self) -> Option { None } @@ -53,7 +53,7 @@ impl ActionBase for A { fn key(&self) -> ActionKey { ActionKey { action_type_id: self.type_id(), - theme_type_id: self.theme_type_id(), + layout_type_id: self.layout_type_id(), referer_type_id: self.referer_type_id(), referer_id: self.referer_id(), } diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs index 45bdcb87..924c626d 100644 --- a/pagetop/src/core/component/context.rs +++ b/pagetop/src/core/component/context.rs @@ -1,7 +1,7 @@ use crate::concat_string; use crate::core::component::ChildOp; -use crate::core::theme::all::{theme_by_short_name, DEFAULT_THEME}; -use crate::core::theme::{ChildrenInRegions, ThemeRef}; +use crate::core::layout::all::{layout_by_short_name, DEFAULT_LAYOUT}; +use crate::core::layout::{ChildrenInRegions, LayoutRef}; use crate::html::{html, Markup}; use crate::html::{Assets, Favicon, JavaScript, StyleSheet}; use crate::locale::{LanguageIdentifier, DEFAULT_LANGID}; @@ -16,7 +16,6 @@ use std::fmt; pub enum AssetsOp { LangId(&'static LanguageIdentifier), - Theme(&'static str), Layout(&'static str), // Favicon. SetFavicon(Option), @@ -50,8 +49,7 @@ impl Error for ErrorParam {} pub struct Context { request : HttpRequest, langid : &'static LanguageIdentifier, - theme : ThemeRef, - layout : &'static str, + layout : LayoutRef, favicon : Option, stylesheet: Assets, javascript: Assets, @@ -66,8 +64,7 @@ impl Context { Context { request, langid : &DEFAULT_LANGID, - theme : *DEFAULT_THEME, - layout : "default", + layout : *DEFAULT_LAYOUT, favicon : None, stylesheet: Assets::::new(), javascript: Assets::::new(), @@ -82,11 +79,8 @@ impl Context { AssetsOp::LangId(langid) => { self.langid = langid; } - AssetsOp::Theme(theme_name) => { - self.theme = theme_by_short_name(theme_name).unwrap_or(*DEFAULT_THEME); - } - AssetsOp::Layout(layout) => { - self.layout = layout; + AssetsOp::Layout(layout_name) => { + self.layout = layout_by_short_name(layout_name).unwrap_or(*DEFAULT_LAYOUT); } // Favicon. AssetsOp::SetFavicon(favicon) => { @@ -135,11 +129,7 @@ impl Context { self.langid } - pub fn theme(&self) -> ThemeRef { - self.theme - } - - pub fn layout(&self) -> &str { + pub fn layout(&self) -> LayoutRef { self.layout } @@ -168,7 +158,7 @@ impl Context { pub fn render_region(&mut self, region: impl Into) -> Markup { self.regions - .all_in_region(self.theme, ®ion.into()) + .all_in_region(self.layout, ®ion.into()) .render(self) } diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index af33c943..315b5de9 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -40,20 +40,20 @@ impl ComponentBase for C { // Comprueba el componente antes de prepararlo. self.setup_before_prepare(cx); - // Acciones del tema antes de preparar el componente. - action::theme::BeforePrepare::dispatch(self, cx); + // Acciones del diseño antes de preparar el componente. + action::layout::BeforePrepare::dispatch(self, cx); // Acciones de los módulos antes de preparar el componente. action::component::BeforePrepare::dispatch(self, cx); // Renderiza el componente. - let markup = match action::theme::RenderComponent::dispatch(self, cx) { + let markup = match action::layout::RenderComponent::dispatch(self, cx) { Some(html) => html, None => self.prepare_component(cx).render(), }; - // Acciones del tema después de preparar el componente. - action::theme::AfterPrepare::dispatch(self, cx); + // Acciones del diseño después de preparar el componente. + action::layout::AfterPrepare::dispatch(self, cx); // Acciones de los módulos después de preparar el componente. action::component::AfterPrepare::dispatch(self, cx); diff --git a/pagetop/src/core/theme.rs b/pagetop/src/core/layout.rs similarity index 72% rename from pagetop/src/core/theme.rs rename to pagetop/src/core/layout.rs index adb99d59..d7a50c10 100644 --- a/pagetop/src/core/theme.rs +++ b/pagetop/src/core/layout.rs @@ -1,5 +1,5 @@ mod definition; -pub use definition::{ThemeRef, ThemeTrait}; +pub use definition::{LayoutRef, LayoutTrait}; mod regions; pub(crate) use regions::ChildrenInRegions; diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/core/layout/all.rs similarity index 52% rename from pagetop/src/core/theme/all.rs rename to pagetop/src/core/layout/all.rs index 6e10eae7..3e2a7ab5 100644 --- a/pagetop/src/core/theme/all.rs +++ b/pagetop/src/core/layout/all.rs @@ -1,31 +1,33 @@ -use crate::core::theme::ThemeRef; +use crate::core::layout::LayoutRef; use crate::global; use std::sync::{LazyLock, RwLock}; // THEMES ****************************************************************************************** -pub static THEMES: LazyLock>> = LazyLock::new(|| RwLock::new(Vec::new())); +pub static LAYOUTS: LazyLock>> = LazyLock::new(|| RwLock::new(Vec::new())); // DEFAULT THEME *********************************************************************************** -pub static DEFAULT_THEME: LazyLock = - LazyLock::new(|| match theme_by_short_name(&global::SETTINGS.app.theme) { - Some(theme) => theme, - None => &crate::base::theme::Basic, - }); +pub static DEFAULT_LAYOUT: LazyLock = + LazyLock::new( + || match layout_by_short_name(&global::SETTINGS.app.layout) { + Some(layout) => layout, + None => &crate::base::layout::Basic, + }, + ); // THEME BY NAME *********************************************************************************** -pub fn theme_by_short_name(short_name: &str) -> Option { +pub fn layout_by_short_name(short_name: &str) -> Option { let short_name = short_name.to_lowercase(); - match THEMES + match LAYOUTS .read() .unwrap() .iter() .find(|t| t.short_name().to_lowercase() == short_name) { - Some(theme) => Some(*theme), + Some(layout) => Some(*layout), _ => None, } } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/layout/definition.rs similarity index 92% rename from pagetop/src/core/theme/definition.rs rename to pagetop/src/core/layout/definition.rs index 01e1cb04..c34891e0 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/layout/definition.rs @@ -4,10 +4,10 @@ use crate::html::{html, Markup}; use crate::locale::L10n; use crate::response::page::Page; -pub type ThemeRef = &'static dyn ThemeTrait; +pub type LayoutRef = &'static dyn LayoutTrait; -/// Los temas deben implementar este "trait". -pub trait ThemeTrait: PackageTrait + Send + Sync { +/// Los diseños deben implementar este "trait". +pub trait LayoutTrait: PackageTrait + Send + Sync { fn regions(&self) -> Vec<(&'static str, L10n)> { vec![("content", L10n::l("content"))] } diff --git a/pagetop/src/core/theme/regions.rs b/pagetop/src/core/layout/regions.rs similarity index 76% rename from pagetop/src/core/theme/regions.rs rename to pagetop/src/core/layout/regions.rs index 7e8128c5..68df24ba 100644 --- a/pagetop/src/core/theme/regions.rs +++ b/pagetop/src/core/layout/regions.rs @@ -1,11 +1,11 @@ use crate::core::component::{ChildComponent, ChildOp, Children}; -use crate::core::theme::ThemeRef; +use crate::core::layout::LayoutRef; use crate::{fn_builder, AutoDefault, TypeId}; use std::collections::HashMap; use std::sync::{LazyLock, RwLock}; -static THEME_REGIONS: LazyLock>> = +static LAYOUT_REGIONS: LazyLock>> = LazyLock::new(|| RwLock::new(HashMap::new())); static COMMON_REGIONS: LazyLock> = @@ -33,9 +33,9 @@ impl ChildrenInRegions { self } - pub fn all_in_region(&self, theme: ThemeRef, region: &str) -> Children { + pub fn all_in_region(&self, layout: LayoutRef, region: &str) -> Children { let common = COMMON_REGIONS.read().unwrap(); - if let Some(r) = THEME_REGIONS.read().unwrap().get(&theme.type_id()) { + if let Some(r) = LAYOUT_REGIONS.read().unwrap().get(&layout.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), - OfTheme(&'static str, ThemeRef), + OfLayout(&'static str, LayoutRef), } impl InRegion { @@ -64,12 +64,12 @@ impl InRegion { .unwrap() .set_in_region(name, ChildOp::Add(child)); } - InRegion::OfTheme(region, theme) => { - let mut regions = THEME_REGIONS.write().unwrap(); - if let Some(r) = regions.get_mut(&theme.type_id()) { + InRegion::OfLayout(region, layout) => { + let mut regions = LAYOUT_REGIONS.write().unwrap(); + if let Some(r) = regions.get_mut(&layout.type_id()) { r.set_in_region(region, ChildOp::Add(child)); } else { - regions.insert(theme.type_id(), ChildrenInRegions::with(region, child)); + regions.insert(layout.type_id(), ChildrenInRegions::with(region, child)); } } } diff --git a/pagetop/src/core/package/all.rs b/pagetop/src/core/package/all.rs index 301d3a02..d906b56d 100644 --- a/pagetop/src/core/package/all.rs +++ b/pagetop/src/core/package/all.rs @@ -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) { // Initialize a list for packages to be enabled. let mut enabled_list: Vec = Vec::new(); - // Add default theme to the enabled list. - add_to_enabled(&mut enabled_list, &crate::base::theme::Basic); + // Add default layout to the enabled list. + add_to_enabled(&mut enabled_list, &crate::base::layout::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, package: PackageRef) { // 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(); - // Ensure the theme is not already registered to avoid duplicates. - if !registered_themes + // 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 .iter() - .any(|t| t.type_id() == theme.type_id()) + .any(|t| t.type_id() == layout.type_id()) { - registered_themes.push(theme); - trace::debug!("Enabling \"{}\" theme", theme.short_name()); + registered_layouts.push(layout); + trace::debug!("Enabling \"{}\" layout", layout.short_name()); } } else { trace::debug!("Enabling \"{}\" package", package.short_name()); diff --git a/pagetop/src/core/package/definition.rs b/pagetop/src/core/package/definition.rs index b1d0a8c9..b4a5d73f 100644 --- a/pagetop/src/core/package/definition.rs +++ b/pagetop/src/core/package/definition.rs @@ -1,5 +1,5 @@ use crate::core::action::ActionBox; -use crate::core::theme::ThemeRef; +use crate::core::layout::LayoutRef; 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 theme(&self) -> Option { + fn layout(&self) -> Option { None } diff --git a/pagetop/src/global.rs b/pagetop/src/global.rs index e538958b..970d9687 100644 --- a/pagetop/src/global.rs +++ b/pagetop/src/global.rs @@ -8,7 +8,7 @@ include_config!(SETTINGS: Settings => [ // [app] "app.name" => "My App", "app.description" => "Developed with the amazing PageTop framework.", - "app.theme" => "", + "app.layout" => "", "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 theme. + /// Default layout. /// Default: *""*. - pub theme: String, + pub layout: String, /// Default language (localization). /// Default: *"en-US"*. pub language: String, diff --git a/pagetop/src/html/opt_classes.rs b/pagetop/src/html/opt_classes.rs index 453991cd..c9df2892 100644 --- a/pagetop/src/html/opt_classes.rs +++ b/pagetop/src/html/opt_classes.rs @@ -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 theme) and user classes (for customizing components based on application styles). +//! by the layout) 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. diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index a5369718..0a1ea105 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -15,17 +15,17 @@ //! //! //! The `PageTop` core API provides a comprehensive toolkit for extending its functionalities to -//! specific requirements and application scenarios through actions, components, packages, and -//! themes: +//! specific requirements and application scenarios through actions, components, layouts, and +//! packages: //! //! * **Actions** serve as a mechanism to customize `PageTop`'s internal behavior by intercepting //! its execution flow. //! * **Components** encapsulate HTML, CSS, and JavaScript into functional, configurable, and //! well-defined units. +//! * **Layouts** enable developers to alter the appearance of pages and components without +//! affecting their functionality. //! * **Packages** extend or customize existing functionality by interacting with `PageTop` APIs //! or third-party package APIs. -//! * **Themes** enable developers to alter the appearance of pages and components without -//! affecting their functionality. //! //! # ⚡️ Quick start //! @@ -105,11 +105,11 @@ pub mod locale; pub mod datetime; // Essential web framework. pub mod service; -// Key types and functions for creating actions, components, packages, and themes. +// Key types and functions for creating actions, components, layouts, and packages. pub mod core; // Web request response variants. pub mod response; -// Base actions, components, packages, and themes. +// Base actions, components, layouts, and packages. pub mod base; // Prepare and run the application. pub mod app; diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 9d0d465f..d7dbe183 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -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::theme; +pub use crate::base::layout; pub use crate::app::Application; diff --git a/pagetop/src/response/page.rs b/pagetop/src/response/page.rs index 340bd0c7..ede1855a 100644 --- a/pagetop/src/response/page.rs +++ b/pagetop/src/response/page.rs @@ -156,23 +156,23 @@ impl Page { // Page RENDER. pub fn render(&mut self) -> ResultPage { - // Theme-specific operations before rendering the page body. - self.context.theme().before_render_body(self); + // Layout-specific operations before rendering the page body. + self.context.layout().before_render_body(self); // Execute package actions before rendering the page body. action::page::BeforeRenderBody::dispatch(self); // Render the page body. - let body = self.context.theme().render_body(self); + let body = self.context.layout().render_body(self); - // Theme-specific operations after rendering the page body. - self.context.theme().after_render_body(self); + // Layout-specific operations after rendering the page body. + self.context.layout().after_render_body(self); // Execute package actions after rendering the page body. action::page::AfterRenderBody::dispatch(self); // Render the page head. - let head = self.context.theme().render_head(self); + let head = self.context.layout().render_head(self); // Render the full page with language and direction attributes. let lang = &self.context.langid().language;