🎨 Cambia "Temas" (themes) por "Diseños" (layouts)
This commit is contained in:
parent
0380aade57
commit
8e0a1d5994
32 changed files with 361 additions and 134 deletions
13
Cargo.toml
13
Cargo.toml
|
|
@ -8,9 +8,11 @@ members = [
|
||||||
# PageTop
|
# PageTop
|
||||||
"pagetop",
|
"pagetop",
|
||||||
|
|
||||||
|
# Layouts
|
||||||
|
#"layouts/pagetop-aliner",
|
||||||
|
#"layouts/pagetop-bootsier",
|
||||||
|
|
||||||
# Packages
|
# Packages
|
||||||
#"packages/pagetop-aliner",
|
|
||||||
#"packages/pagetop-bootsier",
|
|
||||||
#"packages/pagetop-seaorm",
|
#"packages/pagetop-seaorm",
|
||||||
|
|
||||||
# App
|
# App
|
||||||
|
|
@ -35,6 +37,9 @@ pagetop-macros = { version = "0.0", path = "helpers/pagetop-macros" }
|
||||||
# PageTop
|
# PageTop
|
||||||
pagetop = { version = "0.0", path = "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
|
# Packages
|
||||||
#pagetop-aliner = { version = "0.0", path = "packages/pagetop-aliner" }
|
#pagetop-seaorm = { version = "0.0", path = "packages/pagetop-seaorm" }
|
||||||
#pagetop-bootsier = { version = "0.0", path = "packages/pagetop-bootsier" }
|
|
||||||
|
|
|
||||||
18
README.md
18
README.md
|
|
@ -13,24 +13,22 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Presentación
|
|
||||||
|
|
||||||
**PageTop** reúne algunos de los *crates* más estables y populares del ecosistema Rust para
|
**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
|
proporcionar un conjunto completo de funcionalidades que pueden extenderse y adaptarse a las
|
||||||
necesidades específicas de cada aplicación web.
|
necesidades específicas de cada aplicación web.
|
||||||
|
|
||||||
PageTop reivindica la sencillez de la web clásica aplicando *renderizado en el servidor* (SSR),
|
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
|
estarán proporcionando a los desarrolladores herramientas para alterar su comportamiento interno
|
||||||
interceptando su flujo de ejecución.
|
interceptando su flujo de ejecución.
|
||||||
* **Componentes**. Encapsulan HTML, CSS y JavaScript en unidades funcionales, configurables y bien
|
* **Componentes** (*components*). Encapsulan HTML, CSS y JavaScript en unidades funcionales,
|
||||||
definidas.
|
configurables y bien definidas.
|
||||||
* **Paquetes**. Extienden o personalizan funcionalidades existentes interactuando con las APIs de
|
* **Diseños** (*layouts*). Permiten a los desarrolladores modificar la apariencia de páginas y
|
||||||
PageTop o de paquetes de terceros.
|
componentes sin afectar a su funcionalidad.
|
||||||
* **Temas**. Permiten a los desarrolladores alterar la apariencia de las páginas y componentes sin
|
* **Paquetes** (*packages*). Extienden o personalizan funcionalidades existentes interactuando con
|
||||||
afectar su funcionalidad.
|
las APIs de PageTop o de paquetes de terceros.
|
||||||
|
|
||||||
|
|
||||||
# ⚡️ Inicio rápido
|
# ⚡️ Inicio rápido
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[app]
|
[app]
|
||||||
#theme = "Aliner"
|
#layout = "Aliner"
|
||||||
#theme = "Bootsier"
|
#layout = "Bootsier"
|
||||||
language = "es-ES"
|
language = "es-ES"
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
[app]
|
[app]
|
||||||
name = "My App"
|
name = "My App"
|
||||||
description = "Developed with the amazing PageTop framework."
|
description = "Developed with the amazing PageTop framework."
|
||||||
# Default theme.
|
# Default layout.
|
||||||
theme = "Default"
|
layout = "Default"
|
||||||
# Default language (localization).
|
# Default language (localization).
|
||||||
language = "en-US"
|
language = "en-US"
|
||||||
# Default text direction: "ltr", "rtl", or "auto".
|
# Default text direction: "ltr", "rtl", or "auto".
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
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
|
# 📦 Sobre PageTop
|
||||||
|
|
||||||
[PageTop](https://docs.rs/pagetop) es un entorno de desarrollo con convenciones que reivindican la
|
[PageTop](https://docs.rs/pagetop) es un entorno de desarrollo con convenciones que reivindican la
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ struct Drust;
|
||||||
impl PackageTrait for Drust {
|
impl PackageTrait for Drust {
|
||||||
fn dependencies(&self) -> Vec<PackageRef> {
|
fn dependencies(&self) -> Vec<PackageRef> {
|
||||||
vec![
|
vec![
|
||||||
// Packages.
|
// Layouts.
|
||||||
//&pagetop_bootsier::Bootsier,
|
//&pagetop_bootsier::Bootsier,
|
||||||
|
|
||||||
|
// Packages.
|
||||||
//&pagetop_admin::Admin,
|
//&pagetop_admin::Admin,
|
||||||
//&pagetop_user::User,
|
//&pagetop_user::User,
|
||||||
//&pagetop_node::Node,
|
//&pagetop_node::Node,
|
||||||
|
|
|
||||||
119
drust/tools/create-drust-db.sh
Executable file
119
drust/tools/create-drust-db.sh
Executable file
|
|
@ -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" <<EOF
|
||||||
|
CREATE DATABASE IF NOT EXISTS $DB_NAME;
|
||||||
|
CREATE USER IF NOT EXISTS '$DB_USER'@'$DB_HOST' IDENTIFIED BY '$DB_PASS';
|
||||||
|
GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'$DB_HOST';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EOF
|
||||||
|
elif [ "$DB_SYSTEM" == "postgresql" ]; then
|
||||||
|
PGPASSWORD="$DB_ADMIN_PASS" psql -U "$DB_ADMIN" -h "$DB_HOST" <<EOF
|
||||||
|
CREATE DATABASE IF NOT EXISTS $DB_NAME;
|
||||||
|
DO \$\$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT FROM pg_catalog.pg_user
|
||||||
|
WHERE usename = '$DB_USER') THEN
|
||||||
|
CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASS';
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
\$\$;
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
EXIT_CODE=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $EXIT_CODE -eq 0 ]; then
|
||||||
|
echo "Operation completed."
|
||||||
|
else
|
||||||
|
echo "An error occurred. Exit code: $EXIT_CODE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit the script with the mysql command's exit code
|
||||||
|
exit $EXIT_CODE
|
||||||
105
drust/tools/drop-drust-db.sh
Executable file
105
drust/tools/drop-drust-db.sh
Executable file
|
|
@ -0,0 +1,105 @@
|
||||||
|
#!/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 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" <<EOF
|
||||||
|
DROP DATABASE $DB_NAME;
|
||||||
|
DROP USER '$DB_USER'@'$DB_HOST';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EOF
|
||||||
|
elif [ "$DB_SYSTEM" == "postgresql" ]; then
|
||||||
|
PGPASSWORD="$DB_ADMIN_PASS" psql -U "$DB_ADMIN" -h "$DB_HOST" <<EOF
|
||||||
|
DROP DATABASE $DB_NAME;
|
||||||
|
DROP ROLE IF EXISTS $DB_USER;
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
EXIT_CODE=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $EXIT_CODE -eq 0 ]; then
|
||||||
|
echo "Database deletion completed successfully."
|
||||||
|
else
|
||||||
|
echo "An error occurred during database deletion. Exit code: $EXIT_CODE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit the script with the mysql command's exit code
|
||||||
|
exit $EXIT_CODE
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Crea luego un archivo `build.rs` para definir cómo se van a incluir los archivos estáticos o
|
//! Crea luego un archivo `build.rs` para definir cómo se van a incluir los archivos estáticos o
|
||||||
//! archivos SCSS en tu aplicación, paquete o tema de PageTop. Ejemplos de uso:
|
//! archivos SCSS en tu aplicación, diseño o paquete de PageTop. Ejemplos de uso:
|
||||||
//!
|
//!
|
||||||
//! ## 1. Incluir archivos estáticos desde un directorio
|
//! ## 1. Incluir archivos estáticos desde un directorio
|
||||||
//!
|
//!
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
//! Base actions, components, packages, and themes.
|
//! Base actions, components, layouts, and packages.
|
||||||
|
|
||||||
pub mod action;
|
pub mod action;
|
||||||
|
|
||||||
pub mod component;
|
pub mod component;
|
||||||
|
|
||||||
pub mod package;
|
pub mod layout;
|
||||||
|
|
||||||
pub mod theme;
|
pub mod package;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use crate::prelude::*;
|
||||||
|
|
||||||
pub type FnActionWithComponent<C> = fn(component: &mut C, cx: &mut Context);
|
pub type FnActionWithComponent<C> = fn(component: &mut C, cx: &mut Context);
|
||||||
|
|
||||||
pub mod page;
|
|
||||||
|
|
||||||
pub mod theme;
|
|
||||||
|
|
||||||
pub mod component;
|
pub mod component;
|
||||||
|
|
||||||
|
pub mod layout;
|
||||||
|
|
||||||
|
pub mod page;
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent;
|
||||||
|
|
||||||
pub struct AfterPrepare<C: ComponentTrait> {
|
pub struct AfterPrepare<C: ComponentTrait> {
|
||||||
f: FnActionWithComponent<C>,
|
f: FnActionWithComponent<C>,
|
||||||
theme_type_id: Option<TypeId>,
|
layout_type_id: Option<TypeId>,
|
||||||
referer_type_id: Option<TypeId>,
|
referer_type_id: Option<TypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> ActionTrait for AfterPrepare<C> {
|
impl<C: ComponentTrait> ActionTrait for AfterPrepare<C> {
|
||||||
fn theme_type_id(&self) -> Option<TypeId> {
|
fn layout_type_id(&self) -> Option<TypeId> {
|
||||||
self.theme_type_id
|
self.layout_type_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn referer_type_id(&self) -> Option<TypeId> {
|
fn referer_type_id(&self) -> Option<TypeId> {
|
||||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for AfterPrepare<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> AfterPrepare<C> {
|
impl<C: ComponentTrait> AfterPrepare<C> {
|
||||||
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
|
pub fn new(layout: LayoutRef, f: FnActionWithComponent<C>) -> Self {
|
||||||
AfterPrepare {
|
AfterPrepare {
|
||||||
f,
|
f,
|
||||||
theme_type_id: Some(theme.type_id()),
|
layout_type_id: Some(layout.type_id()),
|
||||||
referer_type_id: Some(TypeId::of::<C>()),
|
referer_type_id: Some(TypeId::of::<C>()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ impl<C: ComponentTrait> AfterPrepare<C> {
|
||||||
dispatch_actions(
|
dispatch_actions(
|
||||||
&ActionKey::new(
|
&ActionKey::new(
|
||||||
TypeId::of::<Self>(),
|
TypeId::of::<Self>(),
|
||||||
Some(cx.theme().type_id()),
|
Some(cx.layout().type_id()),
|
||||||
Some(TypeId::of::<C>()),
|
Some(TypeId::of::<C>()),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
|
@ -4,13 +4,13 @@ use crate::base::action::FnActionWithComponent;
|
||||||
|
|
||||||
pub struct BeforePrepare<C: ComponentTrait> {
|
pub struct BeforePrepare<C: ComponentTrait> {
|
||||||
f: FnActionWithComponent<C>,
|
f: FnActionWithComponent<C>,
|
||||||
theme_type_id: Option<TypeId>,
|
layout_type_id: Option<TypeId>,
|
||||||
referer_type_id: Option<TypeId>,
|
referer_type_id: Option<TypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> ActionTrait for BeforePrepare<C> {
|
impl<C: ComponentTrait> ActionTrait for BeforePrepare<C> {
|
||||||
fn theme_type_id(&self) -> Option<TypeId> {
|
fn layout_type_id(&self) -> Option<TypeId> {
|
||||||
self.theme_type_id
|
self.layout_type_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn referer_type_id(&self) -> Option<TypeId> {
|
fn referer_type_id(&self) -> Option<TypeId> {
|
||||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for BeforePrepare<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> BeforePrepare<C> {
|
impl<C: ComponentTrait> BeforePrepare<C> {
|
||||||
pub fn new(theme: ThemeRef, f: FnActionWithComponent<C>) -> Self {
|
pub fn new(layout: LayoutRef, f: FnActionWithComponent<C>) -> Self {
|
||||||
BeforePrepare {
|
BeforePrepare {
|
||||||
f,
|
f,
|
||||||
theme_type_id: Some(theme.type_id()),
|
layout_type_id: Some(layout.type_id()),
|
||||||
referer_type_id: Some(TypeId::of::<C>()),
|
referer_type_id: Some(TypeId::of::<C>()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ impl<C: ComponentTrait> BeforePrepare<C> {
|
||||||
dispatch_actions(
|
dispatch_actions(
|
||||||
&ActionKey::new(
|
&ActionKey::new(
|
||||||
TypeId::of::<Self>(),
|
TypeId::of::<Self>(),
|
||||||
Some(cx.theme().type_id()),
|
Some(cx.layout().type_id()),
|
||||||
Some(TypeId::of::<C>()),
|
Some(TypeId::of::<C>()),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
|
@ -4,13 +4,13 @@ pub type FnRenderComponent<C> = fn(component: &C, cx: &mut Context) -> Option<Ma
|
||||||
|
|
||||||
pub struct RenderComponent<C: ComponentTrait> {
|
pub struct RenderComponent<C: ComponentTrait> {
|
||||||
f: FnRenderComponent<C>,
|
f: FnRenderComponent<C>,
|
||||||
theme_type_id: Option<TypeId>,
|
layout_type_id: Option<TypeId>,
|
||||||
referer_type_id: Option<TypeId>,
|
referer_type_id: Option<TypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> ActionTrait for RenderComponent<C> {
|
impl<C: ComponentTrait> ActionTrait for RenderComponent<C> {
|
||||||
fn theme_type_id(&self) -> Option<TypeId> {
|
fn layout_type_id(&self) -> Option<TypeId> {
|
||||||
self.theme_type_id
|
self.layout_type_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn referer_type_id(&self) -> Option<TypeId> {
|
fn referer_type_id(&self) -> Option<TypeId> {
|
||||||
|
|
@ -19,10 +19,10 @@ impl<C: ComponentTrait> ActionTrait for RenderComponent<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: ComponentTrait> RenderComponent<C> {
|
impl<C: ComponentTrait> RenderComponent<C> {
|
||||||
pub fn new(theme: ThemeRef, f: FnRenderComponent<C>) -> Self {
|
pub fn new(layout: LayoutRef, f: FnRenderComponent<C>) -> Self {
|
||||||
RenderComponent {
|
RenderComponent {
|
||||||
f,
|
f,
|
||||||
theme_type_id: Some(theme.type_id()),
|
layout_type_id: Some(layout.type_id()),
|
||||||
referer_type_id: Some(TypeId::of::<C>()),
|
referer_type_id: Some(TypeId::of::<C>()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +34,7 @@ impl<C: ComponentTrait> RenderComponent<C> {
|
||||||
dispatch_actions(
|
dispatch_actions(
|
||||||
&ActionKey::new(
|
&ActionKey::new(
|
||||||
TypeId::of::<Self>(),
|
TypeId::of::<Self>(),
|
||||||
Some(cx.theme().type_id()),
|
Some(cx.layout().type_id()),
|
||||||
Some(TypeId::of::<C>()),
|
Some(TypeId::of::<C>()),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
|
|
@ -3,9 +3,9 @@ use crate::prelude::*;
|
||||||
pub struct Basic;
|
pub struct Basic;
|
||||||
|
|
||||||
impl PackageTrait for Basic {
|
impl PackageTrait for Basic {
|
||||||
fn theme(&self) -> Option<ThemeRef> {
|
fn layout(&self) -> Option<LayoutRef> {
|
||||||
Some(&Basic)
|
Some(&Basic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThemeTrait for Basic {}
|
impl LayoutTrait for Basic {}
|
||||||
|
|
@ -19,7 +19,7 @@ impl PackageTrait for Welcome {
|
||||||
async fn homepage(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
|
async fn homepage(request: HttpRequest) -> ResultPage<Markup, ErrorPage> {
|
||||||
Page::new(request)
|
Page::new(request)
|
||||||
.with_title(L10n::l("welcome_page"))
|
.with_title(L10n::l("welcome_page"))
|
||||||
.with_assets(AssetsOp::Theme("Basic"))
|
.with_assets(AssetsOp::Layout("Basic"))
|
||||||
.with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##"
|
.with_assets(AssetsOp::AddStyleSheet(StyleSheet::inline("styles", r##"
|
||||||
body {
|
body {
|
||||||
background-color: #f3d060;
|
background-color: #f3d060;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
use crate::util::TypeInfo;
|
||||||
|
|
||||||
|
|
@ -80,8 +80,8 @@ pub mod action;
|
||||||
// API to build new components.
|
// API to build new components.
|
||||||
pub mod component;
|
pub mod component;
|
||||||
|
|
||||||
|
// API to add new layouts.
|
||||||
|
pub mod layout;
|
||||||
|
|
||||||
// API to add new features with packages.
|
// API to add new features with packages.
|
||||||
pub mod package;
|
pub mod package;
|
||||||
|
|
||||||
// API to add new layouts with themes.
|
|
||||||
pub mod theme;
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub type ActionBox = Box<dyn ActionTrait>;
|
||||||
#[derive(Eq, PartialEq, Hash)]
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
pub struct ActionKey {
|
pub struct ActionKey {
|
||||||
action_type_id: TypeId,
|
action_type_id: TypeId,
|
||||||
theme_type_id: Option<TypeId>,
|
layout_type_id: Option<TypeId>,
|
||||||
referer_type_id: Option<TypeId>,
|
referer_type_id: Option<TypeId>,
|
||||||
referer_id: Option<String>,
|
referer_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
@ -14,13 +14,13 @@ pub struct ActionKey {
|
||||||
impl ActionKey {
|
impl ActionKey {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
action_type_id: TypeId,
|
action_type_id: TypeId,
|
||||||
theme_type_id: Option<TypeId>,
|
layout_type_id: Option<TypeId>,
|
||||||
referer_type_id: Option<TypeId>,
|
referer_type_id: Option<TypeId>,
|
||||||
referer_id: Option<String>,
|
referer_id: Option<String>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ActionKey {
|
ActionKey {
|
||||||
action_type_id,
|
action_type_id,
|
||||||
theme_type_id,
|
layout_type_id,
|
||||||
referer_type_id,
|
referer_type_id,
|
||||||
referer_id,
|
referer_id,
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ pub trait ActionBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ActionTrait: ActionBase + AnyBase + Send + Sync {
|
pub trait ActionTrait: ActionBase + AnyBase + Send + Sync {
|
||||||
fn theme_type_id(&self) -> Option<TypeId> {
|
fn layout_type_id(&self) -> Option<TypeId> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ impl<A: ActionTrait> ActionBase for A {
|
||||||
fn key(&self) -> ActionKey {
|
fn key(&self) -> ActionKey {
|
||||||
ActionKey {
|
ActionKey {
|
||||||
action_type_id: self.type_id(),
|
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_type_id: self.referer_type_id(),
|
||||||
referer_id: self.referer_id(),
|
referer_id: self.referer_id(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::concat_string;
|
use crate::concat_string;
|
||||||
use crate::core::component::ChildOp;
|
use crate::core::component::ChildOp;
|
||||||
use crate::core::theme::all::{theme_by_short_name, DEFAULT_THEME};
|
use crate::core::layout::all::{layout_by_short_name, DEFAULT_LAYOUT};
|
||||||
use crate::core::theme::{ChildrenInRegions, ThemeRef};
|
use crate::core::layout::{ChildrenInRegions, LayoutRef};
|
||||||
use crate::html::{html, Markup};
|
use crate::html::{html, Markup};
|
||||||
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
use crate::html::{Assets, Favicon, JavaScript, StyleSheet};
|
||||||
use crate::locale::{LanguageIdentifier, DEFAULT_LANGID};
|
use crate::locale::{LanguageIdentifier, DEFAULT_LANGID};
|
||||||
|
|
@ -16,7 +16,6 @@ use std::fmt;
|
||||||
|
|
||||||
pub enum AssetsOp {
|
pub enum AssetsOp {
|
||||||
LangId(&'static LanguageIdentifier),
|
LangId(&'static LanguageIdentifier),
|
||||||
Theme(&'static str),
|
|
||||||
Layout(&'static str),
|
Layout(&'static str),
|
||||||
// Favicon.
|
// Favicon.
|
||||||
SetFavicon(Option<Favicon>),
|
SetFavicon(Option<Favicon>),
|
||||||
|
|
@ -50,8 +49,7 @@ impl Error for ErrorParam {}
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
request : HttpRequest,
|
request : HttpRequest,
|
||||||
langid : &'static LanguageIdentifier,
|
langid : &'static LanguageIdentifier,
|
||||||
theme : ThemeRef,
|
layout : LayoutRef,
|
||||||
layout : &'static str,
|
|
||||||
favicon : Option<Favicon>,
|
favicon : Option<Favicon>,
|
||||||
stylesheet: Assets<StyleSheet>,
|
stylesheet: Assets<StyleSheet>,
|
||||||
javascript: Assets<JavaScript>,
|
javascript: Assets<JavaScript>,
|
||||||
|
|
@ -66,8 +64,7 @@ impl Context {
|
||||||
Context {
|
Context {
|
||||||
request,
|
request,
|
||||||
langid : &DEFAULT_LANGID,
|
langid : &DEFAULT_LANGID,
|
||||||
theme : *DEFAULT_THEME,
|
layout : *DEFAULT_LAYOUT,
|
||||||
layout : "default",
|
|
||||||
favicon : None,
|
favicon : None,
|
||||||
stylesheet: Assets::<StyleSheet>::new(),
|
stylesheet: Assets::<StyleSheet>::new(),
|
||||||
javascript: Assets::<JavaScript>::new(),
|
javascript: Assets::<JavaScript>::new(),
|
||||||
|
|
@ -82,11 +79,8 @@ impl Context {
|
||||||
AssetsOp::LangId(langid) => {
|
AssetsOp::LangId(langid) => {
|
||||||
self.langid = langid;
|
self.langid = langid;
|
||||||
}
|
}
|
||||||
AssetsOp::Theme(theme_name) => {
|
AssetsOp::Layout(layout_name) => {
|
||||||
self.theme = theme_by_short_name(theme_name).unwrap_or(*DEFAULT_THEME);
|
self.layout = layout_by_short_name(layout_name).unwrap_or(*DEFAULT_LAYOUT);
|
||||||
}
|
|
||||||
AssetsOp::Layout(layout) => {
|
|
||||||
self.layout = layout;
|
|
||||||
}
|
}
|
||||||
// Favicon.
|
// Favicon.
|
||||||
AssetsOp::SetFavicon(favicon) => {
|
AssetsOp::SetFavicon(favicon) => {
|
||||||
|
|
@ -135,11 +129,7 @@ impl Context {
|
||||||
self.langid
|
self.langid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn theme(&self) -> ThemeRef {
|
pub fn layout(&self) -> LayoutRef {
|
||||||
self.theme
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn layout(&self) -> &str {
|
|
||||||
self.layout
|
self.layout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +158,7 @@ impl Context {
|
||||||
|
|
||||||
pub fn render_region(&mut self, region: impl Into<String>) -> Markup {
|
pub fn render_region(&mut self, region: impl Into<String>) -> Markup {
|
||||||
self.regions
|
self.regions
|
||||||
.all_in_region(self.theme, ®ion.into())
|
.all_in_region(self.layout, ®ion.into())
|
||||||
.render(self)
|
.render(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,20 +40,20 @@ impl<C: ComponentTrait> ComponentBase for C {
|
||||||
// Comprueba el componente antes de prepararlo.
|
// Comprueba el componente antes de prepararlo.
|
||||||
self.setup_before_prepare(cx);
|
self.setup_before_prepare(cx);
|
||||||
|
|
||||||
// Acciones del tema antes de preparar el componente.
|
// Acciones del diseño antes de preparar el componente.
|
||||||
action::theme::BeforePrepare::dispatch(self, cx);
|
action::layout::BeforePrepare::dispatch(self, cx);
|
||||||
|
|
||||||
// Acciones de los módulos antes de preparar el componente.
|
// Acciones de los módulos antes de preparar el componente.
|
||||||
action::component::BeforePrepare::dispatch(self, cx);
|
action::component::BeforePrepare::dispatch(self, cx);
|
||||||
|
|
||||||
// Renderiza el componente.
|
// Renderiza el componente.
|
||||||
let markup = match action::theme::RenderComponent::dispatch(self, cx) {
|
let markup = match action::layout::RenderComponent::dispatch(self, cx) {
|
||||||
Some(html) => html,
|
Some(html) => html,
|
||||||
None => self.prepare_component(cx).render(),
|
None => self.prepare_component(cx).render(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Acciones del tema después de preparar el componente.
|
// Acciones del diseño después de preparar el componente.
|
||||||
action::theme::AfterPrepare::dispatch(self, cx);
|
action::layout::AfterPrepare::dispatch(self, cx);
|
||||||
|
|
||||||
// Acciones de los módulos después de preparar el componente.
|
// Acciones de los módulos después de preparar el componente.
|
||||||
action::component::AfterPrepare::dispatch(self, cx);
|
action::component::AfterPrepare::dispatch(self, cx);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
mod definition;
|
mod definition;
|
||||||
pub use definition::{ThemeRef, ThemeTrait};
|
pub use definition::{LayoutRef, LayoutTrait};
|
||||||
|
|
||||||
mod regions;
|
mod regions;
|
||||||
pub(crate) use regions::ChildrenInRegions;
|
pub(crate) use regions::ChildrenInRegions;
|
||||||
|
|
@ -1,31 +1,33 @@
|
||||||
use crate::core::theme::ThemeRef;
|
use crate::core::layout::LayoutRef;
|
||||||
use crate::global;
|
use crate::global;
|
||||||
|
|
||||||
use std::sync::{LazyLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
|
|
||||||
// THEMES ******************************************************************************************
|
// THEMES ******************************************************************************************
|
||||||
|
|
||||||
pub static THEMES: LazyLock<RwLock<Vec<ThemeRef>>> = LazyLock::new(|| RwLock::new(Vec::new()));
|
pub static LAYOUTS: LazyLock<RwLock<Vec<LayoutRef>>> = LazyLock::new(|| RwLock::new(Vec::new()));
|
||||||
|
|
||||||
// DEFAULT THEME ***********************************************************************************
|
// DEFAULT THEME ***********************************************************************************
|
||||||
|
|
||||||
pub static DEFAULT_THEME: LazyLock<ThemeRef> =
|
pub static DEFAULT_LAYOUT: LazyLock<LayoutRef> =
|
||||||
LazyLock::new(|| match theme_by_short_name(&global::SETTINGS.app.theme) {
|
LazyLock::new(
|
||||||
Some(theme) => theme,
|
|| match layout_by_short_name(&global::SETTINGS.app.layout) {
|
||||||
None => &crate::base::theme::Basic,
|
Some(layout) => layout,
|
||||||
});
|
None => &crate::base::layout::Basic,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// THEME BY NAME ***********************************************************************************
|
// THEME BY NAME ***********************************************************************************
|
||||||
|
|
||||||
pub fn theme_by_short_name(short_name: &str) -> Option<ThemeRef> {
|
pub fn layout_by_short_name(short_name: &str) -> Option<LayoutRef> {
|
||||||
let short_name = short_name.to_lowercase();
|
let short_name = short_name.to_lowercase();
|
||||||
match THEMES
|
match LAYOUTS
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|t| t.short_name().to_lowercase() == short_name)
|
.find(|t| t.short_name().to_lowercase() == short_name)
|
||||||
{
|
{
|
||||||
Some(theme) => Some(*theme),
|
Some(layout) => Some(*layout),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,10 @@ use crate::html::{html, Markup};
|
||||||
use crate::locale::L10n;
|
use crate::locale::L10n;
|
||||||
use crate::response::page::Page;
|
use crate::response::page::Page;
|
||||||
|
|
||||||
pub type ThemeRef = &'static dyn ThemeTrait;
|
pub type LayoutRef = &'static dyn LayoutTrait;
|
||||||
|
|
||||||
/// Los temas deben implementar este "trait".
|
/// Los diseños deben implementar este "trait".
|
||||||
pub trait ThemeTrait: PackageTrait + Send + Sync {
|
pub trait LayoutTrait: PackageTrait + Send + Sync {
|
||||||
fn regions(&self) -> Vec<(&'static str, L10n)> {
|
fn regions(&self) -> Vec<(&'static str, L10n)> {
|
||||||
vec![("content", L10n::l("content"))]
|
vec![("content", L10n::l("content"))]
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::core::component::{ChildComponent, ChildOp, Children};
|
use crate::core::component::{ChildComponent, ChildOp, Children};
|
||||||
use crate::core::theme::ThemeRef;
|
use crate::core::layout::LayoutRef;
|
||||||
use crate::{fn_builder, AutoDefault, TypeId};
|
use crate::{fn_builder, AutoDefault, TypeId};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{LazyLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
|
|
||||||
static THEME_REGIONS: LazyLock<RwLock<HashMap<TypeId, ChildrenInRegions>>> =
|
static LAYOUT_REGIONS: LazyLock<RwLock<HashMap<TypeId, ChildrenInRegions>>> =
|
||||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||||
|
|
||||||
static COMMON_REGIONS: LazyLock<RwLock<ChildrenInRegions>> =
|
static COMMON_REGIONS: LazyLock<RwLock<ChildrenInRegions>> =
|
||||||
|
|
@ -33,9 +33,9 @@ impl ChildrenInRegions {
|
||||||
self
|
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();
|
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)])
|
Children::merge(&[common.0.get(region), self.0.get(region), r.0.get(region)])
|
||||||
} else {
|
} else {
|
||||||
Children::merge(&[common.0.get(region), self.0.get(region)])
|
Children::merge(&[common.0.get(region), self.0.get(region)])
|
||||||
|
|
@ -46,7 +46,7 @@ impl ChildrenInRegions {
|
||||||
pub enum InRegion {
|
pub enum InRegion {
|
||||||
Content,
|
Content,
|
||||||
Named(&'static str),
|
Named(&'static str),
|
||||||
OfTheme(&'static str, ThemeRef),
|
OfLayout(&'static str, LayoutRef),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InRegion {
|
impl InRegion {
|
||||||
|
|
@ -64,12 +64,12 @@ impl InRegion {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_in_region(name, ChildOp::Add(child));
|
.set_in_region(name, ChildOp::Add(child));
|
||||||
}
|
}
|
||||||
InRegion::OfTheme(region, theme) => {
|
InRegion::OfLayout(region, layout) => {
|
||||||
let mut regions = THEME_REGIONS.write().unwrap();
|
let mut regions = LAYOUT_REGIONS.write().unwrap();
|
||||||
if let Some(r) = regions.get_mut(&theme.type_id()) {
|
if let Some(r) = regions.get_mut(&layout.type_id()) {
|
||||||
r.set_in_region(region, ChildOp::Add(child));
|
r.set_in_region(region, ChildOp::Add(child));
|
||||||
} else {
|
} else {
|
||||||
regions.insert(theme.type_id(), ChildrenInRegions::with(region, child));
|
regions.insert(layout.type_id(), ChildrenInRegions::with(region, child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::action::add_action;
|
use crate::core::action::add_action;
|
||||||
|
use crate::core::layout::all::LAYOUTS;
|
||||||
use crate::core::package::PackageRef;
|
use crate::core::package::PackageRef;
|
||||||
use crate::core::theme::all::THEMES;
|
|
||||||
use crate::{global, include_files, include_files_service, service, trace};
|
use crate::{global, include_files, include_files_service, service, trace};
|
||||||
|
|
||||||
use std::sync::{LazyLock, RwLock};
|
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.
|
// Initialize a list for packages to be enabled.
|
||||||
let mut enabled_list: Vec<PackageRef> = Vec::new();
|
let mut enabled_list: Vec<PackageRef> = Vec::new();
|
||||||
|
|
||||||
// Add default theme to the enabled list.
|
// Add default layout to the enabled list.
|
||||||
add_to_enabled(&mut enabled_list, &crate::base::theme::Basic);
|
add_to_enabled(&mut enabled_list, &crate::base::layout::Basic);
|
||||||
|
|
||||||
// If a root package is provided, add it to the enabled list.
|
// If a root package is provided, add it to the enabled list.
|
||||||
if let Some(package) = root_package {
|
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.
|
// Add the package itself to the enabled list.
|
||||||
list.push(package);
|
list.push(package);
|
||||||
|
|
||||||
// Check if the package has an associated theme to register.
|
// Check if the package has an associated layout to register.
|
||||||
if let Some(theme) = package.theme() {
|
if let Some(layout) = package.layout() {
|
||||||
let mut registered_themes = THEMES.write().unwrap();
|
let mut registered_layouts = LAYOUTS.write().unwrap();
|
||||||
// Ensure the theme is not already registered to avoid duplicates.
|
// Ensure the layout is not already registered to avoid duplicates.
|
||||||
if !registered_themes
|
if !registered_layouts
|
||||||
.iter()
|
.iter()
|
||||||
.any(|t| t.type_id() == theme.type_id())
|
.any(|t| t.type_id() == layout.type_id())
|
||||||
{
|
{
|
||||||
registered_themes.push(theme);
|
registered_layouts.push(layout);
|
||||||
trace::debug!("Enabling \"{}\" theme", theme.short_name());
|
trace::debug!("Enabling \"{}\" layout", layout.short_name());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trace::debug!("Enabling \"{}\" package", package.short_name());
|
trace::debug!("Enabling \"{}\" package", package.short_name());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::core::action::ActionBox;
|
use crate::core::action::ActionBox;
|
||||||
use crate::core::theme::ThemeRef;
|
use crate::core::layout::LayoutRef;
|
||||||
use crate::core::AnyBase;
|
use crate::core::AnyBase;
|
||||||
use crate::locale::L10n;
|
use crate::locale::L10n;
|
||||||
use crate::{actions, service};
|
use crate::{actions, service};
|
||||||
|
|
@ -16,7 +16,7 @@ pub trait PackageTrait: AnyBase + Send + Sync {
|
||||||
L10n::default()
|
L10n::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Option<ThemeRef> {
|
fn layout(&self) -> Option<LayoutRef> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ include_config!(SETTINGS: Settings => [
|
||||||
// [app]
|
// [app]
|
||||||
"app.name" => "My App",
|
"app.name" => "My App",
|
||||||
"app.description" => "Developed with the amazing PageTop framework.",
|
"app.description" => "Developed with the amazing PageTop framework.",
|
||||||
"app.theme" => "",
|
"app.layout" => "",
|
||||||
"app.language" => "en-US",
|
"app.language" => "en-US",
|
||||||
"app.text_direction" => "ltr",
|
"app.text_direction" => "ltr",
|
||||||
"app.startup_banner" => "Slant",
|
"app.startup_banner" => "Slant",
|
||||||
|
|
@ -50,9 +50,9 @@ pub struct App {
|
||||||
/// A brief description of the application.
|
/// A brief description of the application.
|
||||||
/// Default: *"Developed with the amazing PageTop framework."*.
|
/// Default: *"Developed with the amazing PageTop framework."*.
|
||||||
pub description: String,
|
pub description: String,
|
||||||
/// Default theme.
|
/// Default layout.
|
||||||
/// Default: *""*.
|
/// Default: *""*.
|
||||||
pub theme: String,
|
pub layout: String,
|
||||||
/// Default language (localization).
|
/// Default language (localization).
|
||||||
/// Default: *"en-US"*.
|
/// Default: *"en-US"*.
|
||||||
pub language: String,
|
pub language: String,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! **OptionClasses** implements a *helper* for dynamically adding class names to components.
|
//! **OptionClasses** implements a *helper* for dynamically adding class names to components.
|
||||||
//!
|
//!
|
||||||
//! This *helper* differentiates between default classes (generally associated with styles provided
|
//! 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
|
//! Classes can be added using [Add]. Operations to [Remove], [Replace] or [Toggle] a class, as well
|
||||||
//! as [Clear] all classes, are also provided.
|
//! as [Clear] all classes, are also provided.
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,17 @@
|
||||||
//! </div>
|
//! </div>
|
||||||
//!
|
//!
|
||||||
//! The `PageTop` core API provides a comprehensive toolkit for extending its functionalities to
|
//! The `PageTop` core API provides a comprehensive toolkit for extending its functionalities to
|
||||||
//! specific requirements and application scenarios through actions, components, packages, and
|
//! specific requirements and application scenarios through actions, components, layouts, and
|
||||||
//! themes:
|
//! packages:
|
||||||
//!
|
//!
|
||||||
//! * **Actions** serve as a mechanism to customize `PageTop`'s internal behavior by intercepting
|
//! * **Actions** serve as a mechanism to customize `PageTop`'s internal behavior by intercepting
|
||||||
//! its execution flow.
|
//! its execution flow.
|
||||||
//! * **Components** encapsulate HTML, CSS, and JavaScript into functional, configurable, and
|
//! * **Components** encapsulate HTML, CSS, and JavaScript into functional, configurable, and
|
||||||
//! well-defined units.
|
//! 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
|
//! * **Packages** extend or customize existing functionality by interacting with `PageTop` APIs
|
||||||
//! or third-party package APIs.
|
//! or third-party package APIs.
|
||||||
//! * **Themes** enable developers to alter the appearance of pages and components without
|
|
||||||
//! affecting their functionality.
|
|
||||||
//!
|
//!
|
||||||
//! # ⚡️ Quick start
|
//! # ⚡️ Quick start
|
||||||
//!
|
//!
|
||||||
|
|
@ -105,11 +105,11 @@ pub mod locale;
|
||||||
pub mod datetime;
|
pub mod datetime;
|
||||||
// Essential web framework.
|
// Essential web framework.
|
||||||
pub mod service;
|
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;
|
pub mod core;
|
||||||
// Web request response variants.
|
// Web request response variants.
|
||||||
pub mod response;
|
pub mod response;
|
||||||
// Base actions, components, packages, and themes.
|
// Base actions, components, layouts, and packages.
|
||||||
pub mod base;
|
pub mod base;
|
||||||
// Prepare and run the application.
|
// Prepare and run the application.
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,13 @@ pub use crate::core::{AnyBase, AnyTo};
|
||||||
|
|
||||||
pub use crate::core::action::*;
|
pub use crate::core::action::*;
|
||||||
pub use crate::core::component::*;
|
pub use crate::core::component::*;
|
||||||
|
pub use crate::core::layout::*;
|
||||||
pub use crate::core::package::*;
|
pub use crate::core::package::*;
|
||||||
pub use crate::core::theme::*;
|
|
||||||
|
|
||||||
pub use crate::response::{json::*, page::*, redirect::*, ResponseError};
|
pub use crate::response::{json::*, page::*, redirect::*, ResponseError};
|
||||||
|
|
||||||
pub use crate::base::action;
|
pub use crate::base::action;
|
||||||
pub use crate::base::component::*;
|
pub use crate::base::component::*;
|
||||||
pub use crate::base::theme;
|
pub use crate::base::layout;
|
||||||
|
|
||||||
pub use crate::app::Application;
|
pub use crate::app::Application;
|
||||||
|
|
|
||||||
|
|
@ -156,23 +156,23 @@ impl Page {
|
||||||
// Page RENDER.
|
// Page RENDER.
|
||||||
|
|
||||||
pub fn render(&mut self) -> ResultPage<Markup, ErrorPage> {
|
pub fn render(&mut self) -> ResultPage<Markup, ErrorPage> {
|
||||||
// Theme-specific operations before rendering the page body.
|
// Layout-specific operations before rendering the page body.
|
||||||
self.context.theme().before_render_body(self);
|
self.context.layout().before_render_body(self);
|
||||||
|
|
||||||
// Execute package actions before rendering the page body.
|
// Execute package actions before rendering the page body.
|
||||||
action::page::BeforeRenderBody::dispatch(self);
|
action::page::BeforeRenderBody::dispatch(self);
|
||||||
|
|
||||||
// Render the page body.
|
// 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.
|
// Layout-specific operations after rendering the page body.
|
||||||
self.context.theme().after_render_body(self);
|
self.context.layout().after_render_body(self);
|
||||||
|
|
||||||
// Execute package actions after rendering the page body.
|
// Execute package actions after rendering the page body.
|
||||||
action::page::AfterRenderBody::dispatch(self);
|
action::page::AfterRenderBody::dispatch(self);
|
||||||
|
|
||||||
// Render the page head.
|
// 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.
|
// Render the full page with language and direction attributes.
|
||||||
let lang = &self.context.langid().language;
|
let lang = &self.context.langid().language;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue